]> git.saurik.com Git - apple/ld64.git/commitdiff
ld64-77.tar.gz mac-os-x-105 mac-os-x-1051 v77
authorApple <opensource@apple.com>
Fri, 21 Mar 2008 01:48:04 +0000 (01:48 +0000)
committerApple <opensource@apple.com>
Fri, 21 Mar 2008 01:48:04 +0000 (01:48 +0000)
459 files changed:
ChangeLog
doc/man/man1/ld.1
ld64.xcodeproj/project.pbxproj
src/Architectures.hpp
src/ExecutableFile.h
src/LLVMReader.hpp [new file with mode: 0644]
src/MachOFileAbstraction.hpp
src/MachOReaderArchive.hpp
src/MachOReaderDylib.hpp
src/MachOReaderRelocatable.hpp
src/MachOWriterExecutable.hpp
src/ObjectDump.cpp
src/ObjectFile.h
src/OpaqueSection.hpp [new file with mode: 0644]
src/Options.cpp
src/Options.h
src/SectCreate.cpp [deleted file]
src/ld.cpp
src/machochecker.cpp
unit-tests/bin/exit-non-zero-pass.pl
unit-tests/bin/fail-if-exit-non-zero.pl
unit-tests/bin/fail-if-exit-zero.pl
unit-tests/bin/fail-if-no-stdin.pl
unit-tests/bin/fail-if-stdin.pl
unit-tests/bin/fail-iff-exit-zero.pl
unit-tests/bin/make-recursive-newtest.pl [new file with mode: 0755]
unit-tests/bin/make-recursive.pl
unit-tests/bin/mkld [new file with mode: 0755]
unit-tests/bin/pass-iff-exit-non-zero.pl [new file with mode: 0755]
unit-tests/bin/pass-iff-exit-zero.pl
unit-tests/bin/pass-iff-no-stdin.pl
unit-tests/bin/pass-iff-stdin.pl
unit-tests/bin/result-filter.pl
unit-tests/bin/rm-stale-test-logs [new file with mode: 0755]
unit-tests/clean-tests [new file with mode: 0755]
unit-tests/include/common.makefile
unit-tests/proctor-run [new file with mode: 0755]
unit-tests/run-all-unit-tests
unit-tests/run-all-unit-tests-debug [new file with mode: 0755]
unit-tests/src/Makefile [new file with mode: 0644]
unit-tests/src/results-to-xml.cpp [new file with mode: 0644]
unit-tests/src/xmlparser/xmlparser.1 [new file with mode: 0644]
unit-tests/src/xmlparser/xmlparser.m [new file with mode: 0644]
unit-tests/src/xmlparser/xmlparser.xcodeproj/project.pbxproj [new file with mode: 0644]
unit-tests/src/xmlparser/xmlparser_Prefix.pch [new file with mode: 0644]
unit-tests/test-cases/16-byte-alignment/Makefile [new file with mode: 0644]
unit-tests/test-cases/16-byte-alignment/comment.txt [new file with mode: 0644]
unit-tests/test-cases/16-byte-alignment/tl_test2.c [new file with mode: 0644]
unit-tests/test-cases/absolute-symbol/Makefile [new file with mode: 0644]
unit-tests/test-cases/absolute-symbol/abs.s [new file with mode: 0644]
unit-tests/test-cases/absolute-symbol/main.c [new file with mode: 0644]
unit-tests/test-cases/alias-command-line/Makefile [new file with mode: 0644]
unit-tests/test-cases/alias-command-line/aliases.s [new file with mode: 0644]
unit-tests/test-cases/alias-command-line/aliases.txt [new file with mode: 0644]
unit-tests/test-cases/alias-objects/Makefile [new file with mode: 0644]
unit-tests/test-cases/alias-objects/aliases.s [new file with mode: 0644]
unit-tests/test-cases/align-modulus/Makefile
unit-tests/test-cases/align-modulus/comment.txt [new file with mode: 0644]
unit-tests/test-cases/allow-stack-execute/Makefile
unit-tests/test-cases/allow-stack-execute/comment.txt [new file with mode: 0644]
unit-tests/test-cases/allowable-client/Makefile
unit-tests/test-cases/allowable-client/comment.txt [new file with mode: 0644]
unit-tests/test-cases/archive-ObjC/Makefile [new file with mode: 0644]
unit-tests/test-cases/archive-ObjC/bar.c [new file with mode: 0644]
unit-tests/test-cases/archive-ObjC/baz.m [new file with mode: 0644]
unit-tests/test-cases/archive-ObjC/foo.m [new file with mode: 0644]
unit-tests/test-cases/archive-ObjC/main.c [new file with mode: 0644]
unit-tests/test-cases/archive-basic/Makefile
unit-tests/test-cases/archive-basic/comment.txt [new file with mode: 0644]
unit-tests/test-cases/archive-duplicate/Makefile [new file with mode: 0644]
unit-tests/test-cases/archive-duplicate/bar.c [new file with mode: 0644]
unit-tests/test-cases/archive-duplicate/foo.c [new file with mode: 0644]
unit-tests/test-cases/archive-duplicate/main.c [new file with mode: 0644]
unit-tests/test-cases/archive-weak/Makefile
unit-tests/test-cases/archive-weak/comment.txt [new file with mode: 0644]
unit-tests/test-cases/auto-arch/Makefile
unit-tests/test-cases/auto-arch2/Makefile [new file with mode: 0644]
unit-tests/test-cases/auto-arch2/comment.txt [new file with mode: 0644]
unit-tests/test-cases/auto-arch2/hello.c [new file with mode: 0644]
unit-tests/test-cases/blank-stubs/Makefile
unit-tests/test-cases/blank-stubs/comment.txt [new file with mode: 0644]
unit-tests/test-cases/bundle_loader/Makefile
unit-tests/test-cases/bundle_loader/comment.txt [new file with mode: 0644]
unit-tests/test-cases/commons-alignment/Makefile [new file with mode: 0644]
unit-tests/test-cases/commons-alignment/foo.s [new file with mode: 0644]
unit-tests/test-cases/commons-coalesced-dead_strip/Makefile [new file with mode: 0644]
unit-tests/test-cases/commons-coalesced-dead_strip/a.c [new file with mode: 0644]
unit-tests/test-cases/commons-coalesced-dead_strip/b.c [new file with mode: 0644]
unit-tests/test-cases/commons-coalesced-dead_strip/c.c [new file with mode: 0644]
unit-tests/test-cases/commons-coalesced-dead_strip/c.h [new file with mode: 0644]
unit-tests/test-cases/commons-mixed/Makefile [new file with mode: 0644]
unit-tests/test-cases/commons-mixed/bar.c [new file with mode: 0644]
unit-tests/test-cases/commons-mixed/foo.c [new file with mode: 0644]
unit-tests/test-cases/commons-order/Makefile [new file with mode: 0644]
unit-tests/test-cases/commons-order/bar.c [new file with mode: 0644]
unit-tests/test-cases/commons-order/baz.c [new file with mode: 0644]
unit-tests/test-cases/commons-order/expected.order [new file with mode: 0644]
unit-tests/test-cases/commons-order/foo.c [new file with mode: 0644]
unit-tests/test-cases/commons-order/main.c [new file with mode: 0644]
unit-tests/test-cases/cpu-sub-types/Makefile [new file with mode: 0644]
unit-tests/test-cases/cpu-sub-types/comment.txt [new file with mode: 0644]
unit-tests/test-cases/cpu-sub-types/foo.c [new file with mode: 0644]
unit-tests/test-cases/cpu-sub-types/main.c [new file with mode: 0644]
unit-tests/test-cases/dead_strip-archive-global/Makefile [new file with mode: 0644]
unit-tests/test-cases/dead_strip-archive-global/foo.c [new file with mode: 0644]
unit-tests/test-cases/dead_strip-archive-global/main.c [new file with mode: 0644]
unit-tests/test-cases/dead_strip-archive/Makefile
unit-tests/test-cases/dead_strip-archive/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dead_strip/Makefile
unit-tests/test-cases/dead_strip/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dead_strip_dylibs/Makefile [new file with mode: 0644]
unit-tests/test-cases/dead_strip_dylibs/bar.c [new file with mode: 0644]
unit-tests/test-cases/dead_strip_dylibs/baz.c [new file with mode: 0644]
unit-tests/test-cases/dead_strip_dylibs/foo.c [new file with mode: 0644]
unit-tests/test-cases/dead_strip_dylibs/main.c [new file with mode: 0644]
unit-tests/test-cases/dead_strip_section_attribute/Makefile [new file with mode: 0644]
unit-tests/test-cases/dead_strip_section_attribute/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dead_strip_section_attribute/main.c [new file with mode: 0644]
unit-tests/test-cases/dtrace-static-probes/Makefile [new file with mode: 0644]
unit-tests/test-cases/dtrace-static-probes/bar.d [new file with mode: 0644]
unit-tests/test-cases/dtrace-static-probes/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dtrace-static-probes/foo.d [new file with mode: 0644]
unit-tests/test-cases/dtrace-static-probes/main.c [new file with mode: 0644]
unit-tests/test-cases/dwarf-archive-all_load/Makefile [new file with mode: 0644]
unit-tests/test-cases/dwarf-archive-all_load/bar.c [new file with mode: 0644]
unit-tests/test-cases/dwarf-archive-all_load/baz.c [new file with mode: 0644]
unit-tests/test-cases/dwarf-archive-all_load/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dwarf-archive-all_load/expected-stabs [new file with mode: 0644]
unit-tests/test-cases/dwarf-archive-all_load/foo.c [new file with mode: 0644]
unit-tests/test-cases/dwarf-archive-all_load/stabs-filter.pl [new file with mode: 0755]
unit-tests/test-cases/dwarf-debug-notes-r/Makefile
unit-tests/test-cases/dwarf-debug-notes-r/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dwarf-debug-notes/Makefile
unit-tests/test-cases/dwarf-debug-notes/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dwarf-ignore/Makefile
unit-tests/test-cases/dwarf-ignore/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dwarf-strip/Makefile
unit-tests/test-cases/dwarf-strip/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dylib-aliases/Makefile [new file with mode: 0644]
unit-tests/test-cases/dylib-aliases/bar.c [new file with mode: 0644]
unit-tests/test-cases/dylib-aliases/foo.c [new file with mode: 0644]
unit-tests/test-cases/dylib-aliases/main.c [new file with mode: 0644]
unit-tests/test-cases/dylib-re-export-cycle/Makefile [new file with mode: 0644]
unit-tests/test-cases/dylib-re-export-cycle/bar.c [new file with mode: 0644]
unit-tests/test-cases/dylib-re-export-cycle/foo.c [new file with mode: 0644]
unit-tests/test-cases/dylib-re-export-cycle/main.c [new file with mode: 0644]
unit-tests/test-cases/dylib_file-missing/Makefile [new file with mode: 0644]
unit-tests/test-cases/dylib_file-missing/bar.c [new file with mode: 0644]
unit-tests/test-cases/dylib_file-missing/foo.c [new file with mode: 0644]
unit-tests/test-cases/dylib_file-missing/main.c [new file with mode: 0644]
unit-tests/test-cases/dylib_file/Makefile [new file with mode: 0644]
unit-tests/test-cases/dylib_file/bar.c [new file with mode: 0644]
unit-tests/test-cases/dylib_file/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dylib_file/foo.c [new file with mode: 0644]
unit-tests/test-cases/dylib_file/main.c [new file with mode: 0644]
unit-tests/test-cases/dylib_init/Makefile [new file with mode: 0644]
unit-tests/test-cases/dylib_init/comment.txt [new file with mode: 0644]
unit-tests/test-cases/dylib_init/foo.c [new file with mode: 0644]
unit-tests/test-cases/eh-strip-test/Makefile [new file with mode: 0644]
unit-tests/test-cases/eh-strip-test/comment.txt [new file with mode: 0644]
unit-tests/test-cases/eh-strip-test/main.cxx [new file with mode: 0644]
unit-tests/test-cases/eh_frame/Makefile [new file with mode: 0644]
unit-tests/test-cases/eh_frame/bar.cxx [new file with mode: 0644]
unit-tests/test-cases/eh_frame/foo.cxx [new file with mode: 0644]
unit-tests/test-cases/end-label/Makefile [new file with mode: 0644]
unit-tests/test-cases/end-label/bar.s [new file with mode: 0644]
unit-tests/test-cases/end-label/foo.s [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/Makefile [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/expect1 [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/expect2 [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/expect3 [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/expect4 [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/expect5 [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/expect6 [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/expect7 [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/expect8 [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/foo.c [new file with mode: 0644]
unit-tests/test-cases/exported-symbols-wildcards/list5 [new file with mode: 0644]
unit-tests/test-cases/exported_symbols_list-eol/Makefile [new file with mode: 0644]
unit-tests/test-cases/exported_symbols_list-eol/expected.nm [new file with mode: 0644]
unit-tests/test-cases/exported_symbols_list-eol/test.c [new file with mode: 0644]
unit-tests/test-cases/exported_symbols_list-eol/test.exp [new file with mode: 0644]
unit-tests/test-cases/exported_symbols_list-r/Makefile [new file with mode: 0644]
unit-tests/test-cases/exported_symbols_list-r/test-bad.exp [new file with mode: 0644]
unit-tests/test-cases/exported_symbols_list-r/test.c [new file with mode: 0644]
unit-tests/test-cases/exported_symbols_list-r/test.exp [new file with mode: 0644]
unit-tests/test-cases/external-reloc-sorting/Makefile [new file with mode: 0644]
unit-tests/test-cases/external-reloc-sorting/foo.c [new file with mode: 0644]
unit-tests/test-cases/external-reloc-sorting/main.c [new file with mode: 0644]
unit-tests/test-cases/filelist/Makefile
unit-tests/test-cases/filelist/comment.txt [new file with mode: 0644]
unit-tests/test-cases/flat-dylib/Makefile [new file with mode: 0644]
unit-tests/test-cases/flat-dylib/main.c [new file with mode: 0644]
unit-tests/test-cases/flat-indirect-undefines/Makefile [new file with mode: 0644]
unit-tests/test-cases/flat-indirect-undefines/bar.c [new file with mode: 0644]
unit-tests/test-cases/flat-indirect-undefines/foo.c [new file with mode: 0644]
unit-tests/test-cases/flat-indirect-undefines/main.c [new file with mode: 0644]
unit-tests/test-cases/flat-main/Makefile [new file with mode: 0644]
unit-tests/test-cases/flat-main/main.c [new file with mode: 0644]
unit-tests/test-cases/got-elimination/Makefile [new file with mode: 0644]
unit-tests/test-cases/got-elimination/bar.c [new file with mode: 0644]
unit-tests/test-cases/got-elimination/foo.c [new file with mode: 0644]
unit-tests/test-cases/header-pad/Makefile
unit-tests/test-cases/header-pad/comment.txt [new file with mode: 0644]
unit-tests/test-cases/hello-world/Makefile
unit-tests/test-cases/hello-world/comment.txt [new file with mode: 0644]
unit-tests/test-cases/implicit-common2/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/implicit-common2/a.c [new file with mode: 0644]
unit-tests/test-cases/implicit-common2/comment.txt [new file with mode: 0644]
unit-tests/test-cases/implicit-common2/test.c [new file with mode: 0644]
unit-tests/test-cases/implicit-common3/Makefile [new file with mode: 0644]
unit-tests/test-cases/implicit-common3/a.c [new file with mode: 0644]
unit-tests/test-cases/implicit-common3/comment.txt [new file with mode: 0644]
unit-tests/test-cases/implicit-common3/test.c [new file with mode: 0644]
unit-tests/test-cases/implicit-common4/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/implicit-common4/a.c [new file with mode: 0644]
unit-tests/test-cases/implicit-common4/comment.txt [new file with mode: 0644]
unit-tests/test-cases/implicit-common4/test.c [new file with mode: 0644]
unit-tests/test-cases/implicit-common5/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/implicit-common5/a.c [new file with mode: 0644]
unit-tests/test-cases/implicit-common5/comment.txt [new file with mode: 0644]
unit-tests/test-cases/implicit-common5/test.c [new file with mode: 0644]
unit-tests/test-cases/indirect-dylib/Makefile
unit-tests/test-cases/indirect-dylib/comment.txt [new file with mode: 0644]
unit-tests/test-cases/indirect-path-search/Makefile [new file with mode: 0644]
unit-tests/test-cases/indirect-path-search/bar.c [new file with mode: 0644]
unit-tests/test-cases/indirect-path-search/baz.c [new file with mode: 0644]
unit-tests/test-cases/indirect-path-search/foo.c [new file with mode: 0644]
unit-tests/test-cases/indirect-path-search/main.c [new file with mode: 0644]
unit-tests/test-cases/large-data/Makefile [new file with mode: 0644]
unit-tests/test-cases/large-data/test1.c [new file with mode: 0644]
unit-tests/test-cases/large-data/test2.c [new file with mode: 0644]
unit-tests/test-cases/large-data/test3.c [new file with mode: 0644]
unit-tests/test-cases/large-data/test4.c [new file with mode: 0644]
unit-tests/test-cases/late-link-error/Makefile
unit-tests/test-cases/late-link-error/comment.txt [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce-alignment/Makefile
unit-tests/test-cases/literals-coalesce-alignment2/Makefile [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce-alignment2/comment.txt [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce-alignment2/cstring-align-0.s [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce-alignment2/cstring-align-3.s [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce-alignment3/Makefile [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce-alignment3/comment.txt [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce-alignment3/cstring-align-0.s [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce-alignment3/cstring-align-3.s [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce/Makefile
unit-tests/test-cases/literals-coalesce2/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce2/comment.txt [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce2/literals.s [new file with mode: 0644]
unit-tests/test-cases/literals-coalesce2/test.sh [new file with mode: 0755]
unit-tests/test-cases/llvm-integration/Makefile [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a1.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a10.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a11.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a12.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a12.h [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a13.cc [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a13.h [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a2.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a3.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a4.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a5.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a6.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a7.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a8.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a9.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/a9.list [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b1.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b10.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b10.h [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b2.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b3.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b4.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b5.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/b7.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main1.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main10.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main11.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main12.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main13.cc [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main2.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main3.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main4.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main5.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main6.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main7.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main8.c [new file with mode: 0644]
unit-tests/test-cases/llvm-integration/main9.c [new file with mode: 0644]
unit-tests/test-cases/loader_path/Makefile [new file with mode: 0644]
unit-tests/test-cases/loader_path/bar.c [new file with mode: 0644]
unit-tests/test-cases/loader_path/foo.c [new file with mode: 0644]
unit-tests/test-cases/loader_path/main.c [new file with mode: 0644]
unit-tests/test-cases/local-symbol-partial-stripping/Makefile [new file with mode: 0644]
unit-tests/test-cases/local-symbol-partial-stripping/a.expect [new file with mode: 0644]
unit-tests/test-cases/local-symbol-partial-stripping/a.list [new file with mode: 0644]
unit-tests/test-cases/local-symbol-partial-stripping/b.expect [new file with mode: 0644]
unit-tests/test-cases/local-symbol-partial-stripping/b.list [new file with mode: 0644]
unit-tests/test-cases/local-symbol-partial-stripping/c.list [new file with mode: 0644]
unit-tests/test-cases/local-symbol-partial-stripping/foo.c [new file with mode: 0644]
unit-tests/test-cases/local-symbol-partial-stripping/main.c [new file with mode: 0644]
unit-tests/test-cases/main-stripped/Makefile [new file with mode: 0644]
unit-tests/test-cases/main-stripped/main.c [new file with mode: 0644]
unit-tests/test-cases/main-stripped/main.exp [new file with mode: 0644]
unit-tests/test-cases/missing-option-args/Makefile [new file with mode: 0644]
unit-tests/test-cases/missing-option-args/comment.txt [new file with mode: 0644]
unit-tests/test-cases/multiple-entry-points/Makefile
unit-tests/test-cases/multiple-entry-points/comment.txt [new file with mode: 0644]
unit-tests/test-cases/no-dynamic-common/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/no-dynamic-common/a.c [new file with mode: 0644]
unit-tests/test-cases/no-dynamic-common/comment.txt [new file with mode: 0644]
unit-tests/test-cases/no-dynamic-common/test.c [new file with mode: 0644]
unit-tests/test-cases/no-uuid/Makefile
unit-tests/test-cases/no-uuid/comment.txt [new file with mode: 0644]
unit-tests/test-cases/non-lazy-r/Makefile [new file with mode: 0644]
unit-tests/test-cases/non-lazy-r/foo.c [new file with mode: 0644]
unit-tests/test-cases/non-lazy-r/other.c [new file with mode: 0644]
unit-tests/test-cases/objc-gc-checks/Makefile [new file with mode: 0644]
unit-tests/test-cases/objc-gc-checks/bar.m [new file with mode: 0644]
unit-tests/test-cases/objc-gc-checks/comment.txt [new file with mode: 0644]
unit-tests/test-cases/objc-gc-checks/foo.m [new file with mode: 0644]
unit-tests/test-cases/objc-references/Makefile
unit-tests/test-cases/objc-references/comment.txt [new file with mode: 0644]
unit-tests/test-cases/order_file-ans/Makefile [new file with mode: 0644]
unit-tests/test-cases/order_file-ans/main.cxx [new file with mode: 0644]
unit-tests/test-cases/order_file-ans/main.expected [new file with mode: 0644]
unit-tests/test-cases/order_file-ans/main.order [new file with mode: 0644]
unit-tests/test-cases/order_file/Makefile [new file with mode: 0644]
unit-tests/test-cases/order_file/extra.s [new file with mode: 0644]
unit-tests/test-cases/order_file/main.c [new file with mode: 0644]
unit-tests/test-cases/order_file/main1.expected [new file with mode: 0644]
unit-tests/test-cases/order_file/main1.order [new file with mode: 0644]
unit-tests/test-cases/order_file/main2.expected [new file with mode: 0644]
unit-tests/test-cases/order_file/main2.order [new file with mode: 0644]
unit-tests/test-cases/order_file/main3.expected [new file with mode: 0644]
unit-tests/test-cases/order_file/main3.order [new file with mode: 0644]
unit-tests/test-cases/prebound-split-seg/Makefile [new file with mode: 0644]
unit-tests/test-cases/prebound-split-seg/address_table [new file with mode: 0644]
unit-tests/test-cases/prebound-split-seg/bar.c [new file with mode: 0644]
unit-tests/test-cases/private-non-lazy/Makefile
unit-tests/test-cases/private-non-lazy/comment.txt [new file with mode: 0644]
unit-tests/test-cases/re-export-cases/Makefile [new file with mode: 0644]
unit-tests/test-cases/re-export-cases/bar.c [new file with mode: 0644]
unit-tests/test-cases/re-export-cases/baz.c [new file with mode: 0644]
unit-tests/test-cases/re-export-cases/foo.c [new file with mode: 0644]
unit-tests/test-cases/re-export-flag/Makefile [new file with mode: 0644]
unit-tests/test-cases/re-export-flag/bar.c [new file with mode: 0644]
unit-tests/test-cases/re-export-flag/foo.c [new file with mode: 0644]
unit-tests/test-cases/re-export-optimizations/Makefile [new file with mode: 0644]
unit-tests/test-cases/re-export-optimizations/bar.c [new file with mode: 0644]
unit-tests/test-cases/re-export-optimizations/foo.c [new file with mode: 0644]
unit-tests/test-cases/re-export-optimizations/main.c [new file with mode: 0644]
unit-tests/test-cases/re-export-relative-paths/Makefile [new file with mode: 0644]
unit-tests/test-cases/re-export-relative-paths/bar.c [new file with mode: 0644]
unit-tests/test-cases/re-export-relative-paths/foo.c [new file with mode: 0644]
unit-tests/test-cases/re-export-relative-paths/main.c [new file with mode: 0644]
unit-tests/test-cases/re-export-relative-paths/wrap.c [new file with mode: 0644]
unit-tests/test-cases/read-only-relocs/Makefile
unit-tests/test-cases/read-only-relocs/comment.txt [new file with mode: 0644]
unit-tests/test-cases/rebase-basic/Makefile
unit-tests/test-cases/rebase-basic/comment.txt [new file with mode: 0644]
unit-tests/test-cases/relocs-asm/Makefile
unit-tests/test-cases/relocs-asm/comment.txt [new file with mode: 0644]
unit-tests/test-cases/relocs-asm/relocs-asm.s
unit-tests/test-cases/relocs-c/Makefile
unit-tests/test-cases/relocs-c2/Makefile [new file with mode: 0644]
unit-tests/test-cases/relocs-c2/comment.txt [new file with mode: 0644]
unit-tests/test-cases/relocs-c2/test.c [new file with mode: 0644]
unit-tests/test-cases/relocs-literals/Makefile
unit-tests/test-cases/relocs-literals/test.c
unit-tests/test-cases/relocs-literals2/Makefile [new file with mode: 0644]
unit-tests/test-cases/relocs-literals2/test.c [new file with mode: 0644]
unit-tests/test-cases/relocs-literals3/Makefile [new file with mode: 0644]
unit-tests/test-cases/relocs-literals3/comment.txt [new file with mode: 0644]
unit-tests/test-cases/relocs-literals3/test.c [new file with mode: 0644]
unit-tests/test-cases/relocs-objc/Makefile
unit-tests/test-cases/relocs-objc/comment.txt [new file with mode: 0644]
unit-tests/test-cases/segment-order/Makefile [new file with mode: 0644]
unit-tests/test-cases/segment-order/expected.order [new file with mode: 0644]
unit-tests/test-cases/segment-order/main.c [new file with mode: 0644]
unit-tests/test-cases/segment-order/segJJJ.s [new file with mode: 0644]
unit-tests/test-cases/segment-order/segKKK.s [new file with mode: 0644]
unit-tests/test-cases/segment-order/segLLL.s [new file with mode: 0644]
unit-tests/test-cases/special-labels/Makefile [new file with mode: 0644]
unit-tests/test-cases/special-labels/extra.s [new file with mode: 0644]
unit-tests/test-cases/special-labels/main.c [new file with mode: 0644]
unit-tests/test-cases/stabs-coalesce/Makefile
unit-tests/test-cases/stabs-coalesce/comment.txt [new file with mode: 0644]
unit-tests/test-cases/stabs-directory-slash/Makefile [new file with mode: 0644]
unit-tests/test-cases/stabs-directory-slash/main.c [new file with mode: 0644]
unit-tests/test-cases/stack_addr_no_size/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/stack_addr_no_size/comment.txt [new file with mode: 0644]
unit-tests/test-cases/stack_addr_no_size/main.c [new file with mode: 0644]
unit-tests/test-cases/stack_addr_size/Makefile [new file with mode: 0644]
unit-tests/test-cases/stack_addr_size/comment.txt [new file with mode: 0644]
unit-tests/test-cases/stack_addr_size/main.c [new file with mode: 0644]
unit-tests/test-cases/stack_size_no_addr/Makefile [new file with mode: 0644]
unit-tests/test-cases/stack_size_no_addr/comment.txt [new file with mode: 0644]
unit-tests/test-cases/stack_size_no_addr/main.c [new file with mode: 0644]
unit-tests/test-cases/static-executable/Makefile
unit-tests/test-cases/static-executable/comment.txt [new file with mode: 0644]
unit-tests/test-cases/static-strip/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/static-strip/comment.txt [new file with mode: 0644]
unit-tests/test-cases/static-strip/test.c [new file with mode: 0644]
unit-tests/test-cases/strip-test2/Makefile [new file with mode: 0644]
unit-tests/test-cases/strip-test2/comment.txt [new file with mode: 0644]
unit-tests/test-cases/strip-test2/main.cxx [new file with mode: 0644]
unit-tests/test-cases/strip-test3/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/strip-test3/comment.txt [new file with mode: 0644]
unit-tests/test-cases/strip-test3/main.cxx [new file with mode: 0644]
unit-tests/test-cases/strip_local/Makefile [new file with mode: 0644]
unit-tests/test-cases/strip_local/foo.c [new file with mode: 0644]
unit-tests/test-cases/strip_local/hello.c [new file with mode: 0644]
unit-tests/test-cases/stripped-indirect-symbol-table/Makefile [new file with mode: 0644]
unit-tests/test-cases/stripped-indirect-symbol-table/a.c [new file with mode: 0644]
unit-tests/test-cases/stripped-indirect-symbol-table/b.c [new file with mode: 0644]
unit-tests/test-cases/stripped-indirect-symbol-table/c.c [new file with mode: 0644]
unit-tests/test-cases/stripped-indirect-symbol-table/func.c [new file with mode: 0644]
unit-tests/test-cases/stripped-indirect-symbol-table/strip.list [new file with mode: 0644]
unit-tests/test-cases/stub-generation/Makefile [new file with mode: 0644]
unit-tests/test-cases/stub-generation/test.c [new file with mode: 0644]
unit-tests/test-cases/symbol-moving/Makefile [new file with mode: 0644]
unit-tests/test-cases/symbol-moving/aaa.c [new file with mode: 0644]
unit-tests/test-cases/symbol-moving/anotb.c [new file with mode: 0644]
unit-tests/test-cases/symbol-moving/bar.c [new file with mode: 0644]
unit-tests/test-cases/symbol-moving/bbb.c [new file with mode: 0644]
unit-tests/test-cases/symbol-moving/bnota.c [new file with mode: 0644]
unit-tests/test-cases/symbol-moving/foo.c [new file with mode: 0644]
unit-tests/test-cases/symbol-moving/main.c [new file with mode: 0644]
unit-tests/test-cases/tentative-to-real/Makefile
unit-tests/test-cases/tentative-to-real/comment.txt [new file with mode: 0644]
unit-tests/test-cases/undefined-dynamic-lookup/Makefile [new file with mode: 0644]
unit-tests/test-cases/undefined-dynamic-lookup/main.c [new file with mode: 0644]
unit-tests/test-cases/weak-def-ordinal/Makefile [new file with mode: 0644]
unit-tests/test-cases/weak-def-ordinal/bar.c [new file with mode: 0644]
unit-tests/test-cases/weak-def-ordinal/foo.c [new file with mode: 0644]
unit-tests/test-cases/weak-def-ordinal/main.c [new file with mode: 0644]
unit-tests/test-cases/weak_import/Makefile
unit-tests/test-cases/weak_import2/Makefile.newtest [new file with mode: 0644]
unit-tests/test-cases/weak_import2/comment.txt [new file with mode: 0644]
unit-tests/test-cases/weak_import2/foo.c [new file with mode: 0644]
unit-tests/test-cases/weak_import2/foo.h [new file with mode: 0644]
unit-tests/test-cases/weak_import2/foo1.c [new file with mode: 0644]
unit-tests/test-cases/weak_import2/main.c [new file with mode: 0644]
unit-tests/test-cases/weak_import3/Makefile [new file with mode: 0644]
unit-tests/test-cases/weak_import3/comment.txt [new file with mode: 0644]
unit-tests/test-cases/weak_import3/foo.c [new file with mode: 0644]
unit-tests/test-cases/weak_import3/foo.h [new file with mode: 0644]
unit-tests/test-cases/weak_import3/foo1.c [new file with mode: 0644]
unit-tests/test-cases/weak_import3/main.c [new file with mode: 0644]
unit-tests/test-cases/zero-fill/Makefile
unit-tests/test-cases/zero-fill2/Makefile [new file with mode: 0644]
unit-tests/test-cases/zero-fill2/comment.txt [new file with mode: 0644]
unit-tests/test-cases/zero-fill2/test.c [new file with mode: 0644]
unit-tests/test-cases/zero-fill3/Makefile [new file with mode: 0644]
unit-tests/test-cases/zero-fill3/comment.txt [new file with mode: 0644]
unit-tests/test-cases/zero-fill3/test.c [new file with mode: 0644]

index ce470b099478b0df82881abeb3b35bc899771038..7a63394ac89b86f5ca26916437edfebe5f5bc225 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
+----- Tagged ld64-77
+
+2007-07-3     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5351380> Kernel is linked with some global symbols unsorted
+       * src/MachOWriterExecutable.hpp: Add NListNameSorter to allow global atoms and extra labels to be sorted
+
+
+2007-07-20     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5254468> Can't do objc_msgSendSuper dispatches after loading a Fix&Continue bundle
+       * src/MachOWriterExecutable.hpp: when calculating what kind of reloc to use, never use an 
+         external reloc to reference 32-bit ObjC symbols.
+
+
+2007-07-20     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5349847> Runtime crash with ICC math library on Leopard
+       * src/MachOReaderRelocatable.hpp: detect if section starts with a symbol that is not 
+         aligned to section and correct it.
+
+
+----- Tagged ld64-76
+
+2007-06-29     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5303718> export hiding does not work for frameworks
+       * src/MachOReaderDylib.hpp: fix checks in isPublicLocation()
+       * unit-tests/test-cases/symbol-moving: update to test frameworks as well as dylibs
+
+
+2007-06-27     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5299907> linker should use undefines from flat dylibs when linking a main flat
+       * src/ObjectFile.h: added fLinkingMainExecutable
+       * src/Options.cpp: set up fLinkingMainExecutable
+       * src/MachOReaderDylib.hpp: when linking a main executable for flat namespace, the reader for
+               any loaded flat namespace dylib will have a new atoms that has references to all undefined
+               symbols in the dylib
+       * unit-tests/test-cases/flat-indirect-undefines: added test case
+       * doc/man/man1/ld.1: update man page to describe when dylib undefines are used
+       
+
+2007-06-27     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5277857> OpenGL.framework and X11 both have a libGL.dylib which can cause ld to segfault if both are found
+       * src/MachOReaderDylib.hpp: add assertNoReExportCycles() method
+       * unit-tests/test-cases/dylib-re-export-cycle: added test case
+
+
+2007-06-27     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5286462> ld64 has slightly different warning message formats than the old ld
+       * src/ld.cpp: standardize all warning messages to start with "ld: warning"
+       * src/MachOWriterExecutable.hpp: ditto
+       * src/MachOReaderRelocatable.hpp: ditto
+       * src/MachOReaderDylib.hpp:ditto
+
+
+2007-06-26     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5297034> -dead_strip can cause duplicate external commons
+       * src/ld.cpp: don't use discarded coalesced global atoms as dead strip roots
+       * src/machochecker.cpp: error if duplicate external symbols
+       * unit-tests/test-cases/commons-coalesced-dead_strip: added test case
+       
+
+2007-06-26     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4135857> update man page that linker does not search indirect libraries with two-level namespace
+       * doc/man/man1/ld.1: add new "Indirect dynamic libraries" section to man page
+       
+
+2007-06-26     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5285473> Xc9A466: Exports file cannot use Mac line ends
+       * src/Options.cpp: check for \r or \n when parsing .exp files
+       * unit-tests/test-cases/exported_symbols_list-eol: added test case
+       
+
+----- Tagged ld64-75
+
+2007-05-31     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4607755> Simplier, generalized way to re-export dylibs: LC_REEXPORT_DYLIB
+       * src/MachOWriterExecutable.hpp: Use LC_REEXPORT_DYLIB when targetting 10.5
+
+
+----- Tagged ld64-74.5
+
+2007-05-31     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5241902> set OSO timestamp to zero for when building in buildit
+       * src/ld.cpp: check for RC_RELEASE and if exists set all OSO timestamps to zero
+       
+
+2007-05-30     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5224676> BUILD_STABS now causes ld of xnu to bus error
+       * src/ld.cpp: Change || to && in collectStabs()
+
+
+----- Tagged ld64-74.4
+
+2007-05-18     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5211667> static probes don't work with libraries in dyld shared cache
+       *  src/OpaqueSection.hpp: the __TEXT segment is executable
+
+
+----- Tagged ld64-74.3
+
+2007-05-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5201463> ppc: linker adds stubs to cstring references
+       * src/MachOWriterExecutable.hpp: update ppc stubableReference() to only allow high/low references
+               to be stubed if they reference a symbol in some other dylib.
+       * unit-tests/test-cases/stub-generation: added test case
+       
+
+2007-05-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5008421> ppc64: need to make LOCAL indirect symbol table entry for now local symbol
+       * src/MachOWriterExecutable.hpp: factored local tests into indirectSymbolIsLocal()
+       * unit-tests/test-cases/non-lazy-r: added test case
+       
+
+2007-05-15     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5198807> ld64 drops fix&continue bit in __OBJC, __image_info.
+       * src/MachOReaderRelocatable.hpp: implement objcReplacementClasses()
+       
+
+2007-05-15     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5066152> support __image_info in __DATA segment for 64-bits
+       * src/MachOReaderRelocatable.hpp: use strncmp() for __objc_imageinfo since it is 16 bytes long
+       * src/MachOWriterExecutable.hpp: specialize segment/section names for synthesized objc image info section
+
+
+2007-05-15     Nick Kledzik    <kledzik@apple.com>
+
+       * unit-tests/include/common.makefile: set COMPILER_PATH so harness works with latest compiler
+
+
+----- Tagged ld64-74.2
+
+2007-05-11     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5195447> ld64-74.1 breaks libstdc++ DejaGnu test (G5 only)
+       * src/MachOWriterExecutable.hpp: don't stub a reference if the target offset is non-zero
+       
+
+----- Tagged ld64-74.1
+
+2007-05-09     Nick Kledzik    <kledzik@apple.com>
+       
+       * src/Options.h: add emitWarnings()
+       * src/Options.cpp: wire up -w to emitWarnings()
+
+
+2007-05-09     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5137285> ld64 won't link wine (regression from Tiger)
+       * src/Architectures.hpp: add x86::kPointerDiff16 and x86::kPCRel16
+       * src/MachOReaderRelocatable.hpp: add support to parse new relocs
+       * src/MachOWriterExecutable.hpp: add support fo new relocs
+       
+
+2007-05-08     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5182537> need way for ld and dyld to see different exported symbols in a dylib
+       * src/MachOReaderDylib.hpp: update parse and use $ld$ symbols
+       * src/Options.h: move VersionMin to ReaderOptions
+       * src/ObjectFile.h: move VersionMin to ReaderOptions
+       * src/Options.cpp:  move VersionMin to ReaderOptions
+       * src/MachOWriterExecutable.hpp: move VersionMin to ReaderOptions
+       * unit-tests/test-cases/symbol-moving: added test case
+       
+
+2007-05-03     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5181105> typo in error message for linking -pie
+       * src/MachOWriterExecutable.hpp: fix typo in error messages
+       
+
+----- Tagged ld64-74
+
+2007-05-03     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
+       <rdar://problem/4019497> ld64 should handle linking against dylibs that have @loader_path based dylib load commands
+       * src/ObjectFile.h: add from parameter to findDylib()
+       * src/MachOReaderDylib.hpp: supply from parameter to findDylib()
+       * src/ld.cpp: use from parameter for @loader_path substitution in findDylib()
+       * unit-tests/test-cases/re-export-relative-paths: added test case
+       
+
+2007-05-02     Nick Kledzik    <kledzik@apple.com>
+
+       * src/ObjectFile.h: add fLogObjectFiles and fLogAllFiles
+       * src/Options.cpp: hook up -t to fLogAllFiles and -whatsloaded to fLogObjectFiles 
+       * src/MachOReaderDylib.hpp: log if fLogAllFiles
+       * src/MachOReaderRelocatable.hpp: log if fLogObjectFiles or fLogAllFiles 
+       * src/MachOReaderArchive.hpp: log if fLogAllFiles
+       * doc/man/man1/ld.1: update man page
+
+
+2007-05-02     Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/5177848> typo in message, frameowrk
+       * src/Options.cpp: fix typo
+
+
+2007-05-01     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4977301> "ld" man page is missing the description for many options 
+       * doc/man/man1/ld.1: add documentation on all obsolete options
+       
+       
+2007-05-01     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5113424> ld doesn't handle -mlong-branch .o files that have had local symbols stripped
+       <rdar://problem/4965359> warning about dwarf line info with -mlong-branch
+       * src/MachOReaderRelocatable.hpp: don't lop -mlong-branch stubs off end of functions
+       * src/MachOWriterExecutable.hpp: allow code references besides BR24 to be stubable
+       
+
+2007-04-30     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5065659> unable to link VTK because __textcoal_nt too large
+       * src/MachOReaderRelocatable.hpp: when doing a final link map __textcoal_nt to __text
+
+
+2007-04-30     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5062685> ld does not report error when -r is used and exported symbols are not defined.
+       <rdar://problem/4637139> ld leaves global common symbols not in exported symbols list.
+       * src/ld.cpp: stop special casing -r mode in checkUndefines() 
+       * src/MachOWriterExecutable.hpp: don't create proxy atom in -r mode if it is supposed to be exported.
+               mark tentative definitions are private extern in -r mode even without -keep_private_externs
+       * unit-tests/test-cases/exported_symbols_list-r: added test case
+
+
+2007-04-27     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5137732> ld should keep looking when it finds a weak definition in a dylib
+       * src/ld.cpp: modified addJustInTimeAtoms() to keep looking when a weak defintion is found
+       * unit-tests/test-cases/weak-def-ordinal: added test case
+       
+
+2007-04-27     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5166572> better error message for indirect dylibs missing required architecture
+       * src/ld.cpp: when loading indirect dylib add path to error messages
+
+
+2007-04-25     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5109373> the i386 slice of dyld does not need __IMPORT segment
+       * src/ObjectFile.h: add fForDyld
+       * src/Options.cpp: set up fForDyld
+       * src/MachOReaderRelocatable.hpp: if fForDyld, change __IMPORT segment to __DATA
+       * src/MachOWriterExecutable.hpp: recognize __DATA/__pointers in dyld as a non-lazy section
+
+
+2007-04-24     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5008421> ppc64: need to make LOCAL indirect symbol table entry for now local symbol
+       * src/MachOWriterExecutable.hpp: use INDIRECT_SYMBOL_LOCAL for any non-global symbol
+       * unit-tests/test-cases/strip_local: update test case
+       
+       
+2007-04-24     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5150407> ld64 -sectorder and -order_file files don't accept white space following the :
+       * src/Options.cpp: prune white space after colon and before symbol name
+       * unit-tests/test-cases/order_file: update test case to have a space after the colon
+       
+
+2007-04-24     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5055233> ld64 corrupts debug symbol table entries, nm doesn't print them
+       * src/MachOWriterExecutable.hpp: properly set ilocalsym in module table
+
+
+2007-04-24     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5066152> support __image_info in __DATA segment for 64-bits
+       * src/MachOReaderRelocatable.hpp: look for new objc info section name too
+
+
+2007-04-24     Nick Kledzik    <kledzik@apple.com>
+       
+       * src/MachOWriterExecutable.hpp: fix -non_global_symbols_strip_list to work with -r
+       * unit-tests/test-cases/local-symbol-partial-stripping: update test case
+
+
+
+----- Tagged ld64-73.7
+
+2007-05-10     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5194804> can't use dtrace static probes in x86_64 dylib
+       * src/MachOWriterExecutable.hpp: x86_64:kPointerDiff32 is ok in shared region
+       * unit-tests/test-cases/dtrace-static-probes: update to build dylib too
+
+
+2007-05-09     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5191610> 9A430: using -dead_strip with static dtrace probes causes ld to crash
+       * src/ld.cpp: fix markLive() to look at right name in dtrace probe refernce
+       * unit-tests/test-cases/dtrace-static-probes: added -dead_strip case
+
+
+----- Tagged ld64-73.6
+
+2007-04-17     Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/5140897> Add options to do partial stripping of local symbols
+       * src/MachOWriterExecutable.hpp: use fOptions.keepLocalSymbol()
+       * src/Options.cpp: implement -non_global_symbols_no_strip_list and -non_global_symbols_strip_list
+       * src/Options.h: replace stripLocalSymbols() with localSymbolHandling() and keepLocalSymbol()
+       * doc/man/man1/ld.1: document -non_global_symbols_no_strip_list and -non_global_symbols_strip_list
+       * unit-tests/test-cases/local-symbol-partial-stripping: added test case
+       
+
+----- Tagged ld64-73.5
+
+2007-04-17     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5129379> ld64-73.3 XBS logging incorrectly reporting "direct" dynamic libraries
+       * src/ld.cpp: restore direct vs indirect library for LD_TRACE_DYLIBS logging
+       
+
+2007-04-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5067034> data initialized to a weak imported symbol is missing relocation
+       * src/MachOWriterExecutable.hpp: check for A::kPointerWeakImport in buildExecutableFixups()
+       * unit-tests/test-cases/weak_import: updated test case to catch this problem
+
+
+2007-04-13     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5071047> Support -U 
+       * src/MachOWriterExecutable.hpp: create proxies for -U symbols
+       * src/Options.cpp: process -U 
+       * src/Options.h: add allowedUndefined() and someAllowedUndefines()
+       * src/ld.cpp: create proxies for -U symbols
+       * doc/man/man1/ld.1:  document -U and -undefined options
+       * unit-tests/test-cases/undefined-dynamic-lookup: added test case
+
+
+----- Tagged ld64-73.4
+
+2007-04-12     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5125280> ld changes needed to support read-only DOF
+       * src/Options.cpp: remove -read_only_dof
+       * src/Options.h: remove fReadOnlyDOFs
+       * src/ld.cpp: only generate read-only DOF sections
+       
+
+----- Tagged ld64-73.3.1
+
+2007-04-13     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5130496> -framework vecLib -framework Accelerate causes bad ordinals 
+       * src/MachOWriterExecutable.hpp: fix bug optimizeDylibReferences() when there are two readers with same install name
+
+
+----- Tagged ld64-73.3
+
+2007-04-03     Nick Kledzik    <kledzik@apple.com>
+
+       * src/ld.cpp: read-only-dofs should use 32-bit offsets for x86_64
+       * src/MachOReaderDylib.hpp: if "public" re-export is not marked implict, still mark it as re-exported
+       
+
+2007-04-02     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5105971> if replacement file for -dylib_file is missing, warn instead of error
+       * src/ld.cpp: a try/catch to turn -dylib_file error into a warning.
+       * unit-tests/test-cases/dylib_file-missing: add test case
+       * doc/man/man1/ld.1: update man page about -dead_strip_dylibs
+       
+
+----- Tagged ld64-73.2
+
+2007-03-31     Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/5102873> ld64-73: atom sorting error with duplicate zero sized bss symbols
+       * src/MachOReaderRelocatable.hpp: suppress warning on sorting zero size zero fill atoms
+       
+2007-03-31     Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/5102845> ld64-73 fails anything linking with -lm
+       * src/ld.cpp: when processing dylbs that are sylinks ensure that fDylibMap contains all paths  
+       * src/MachOWriterExecutable.hpp: when dead stripping dylibs and renumbering ordinals make sure
+               aliases dylib get renumbered too
+       * unit-tests/test-cases/dylib-aliases: added
+       
+       
+----- Tagged ld64-73.1
+       
+2007-03-30     Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: back out use of LC_REEXPORT_DYLIB until rdar://problem/5009909 is in build fleet
+       
+       
+----- Tagged ld64-73
+       
+2007-03-30     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4175790> ER: -dead_strip_dylibs
+       <rdar://problem/3904828> linker should add implicit load commands for indirectly used public dylibs
+       * src/ObjectFile.h: change dylib reader interface to implictly/explicitlyLinked
+       * src/ld.cpp: use new dylib reader interface
+       * src/Options.h: add deadStripDylibs()
+       * src/Options.cpp: support -dead_strip_dylibs
+       * src/MachOReaderDylib.hpp: use new dylib reader interface
+       * src/MachOWriterExecutable.hpp: remove dylib load commands for unused dylibs and alter ordinals 
+       * unit-tests/test-cases/re-export-optimizations: added
+       * unit-tests/test-cases/dead_strip_dylibs: added
+       
+
+2007-03-30     Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.cpp: enable -lfoo to search for libfoo.so as well as libfoo.dylib, 
+               remove seg addr table hack for transitioning to new linker
+
+2007-03-30     Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/5073800> ADOBE XCODE3: Linker is slow with large C++ .o files
+       * src/MachOReaderRelocatable.hpp: the compiler generates stubs to weak functions in the
+               same translation unit.  Don't treat those like the spurios stubs to static functions.
+
+
+2007-03-29     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4739044> ld64 should link mach_kernel during xnu builds to support dtrace
+       * src/MachOReaderRelocatable.hpp: To handle duplicate labels properly, rework how atoms sizes are set 
+               by iterating through sorted fAtoms rather than fAddrToAtom, . Change default alignment of commons
+               to be the natural alignment of the size rounded up to the closest power of two and max it at 12.
+               Build atoms in reverse symbol table order so that global atoms are constructed before locals.
+               This assures that if there is a global and local label at the same location, the global label
+               will become the atom's name and the local will be an alias.  Properly handle a label
+               at the end of a section.  Handle R_ABS in relocations.  Handle sect-diff relocs with addends.
+               Don't auto-strip 'l' symbols in static executables (mach_kernel).
+       * src/OpaqueSection.hpp:  opaque_section now has an ordinal
+       * src/ld.cpp: opaque_section now requires an ordinal
+       * src/ObjectFile.h: add ReaderOptions.fForStatic
+       * src/Options.cpp: set fForStatic when building a static executable
+       * src/MachOWriterExecutable.hpp: add from atom to StubAtom<ppc>.  Properly write out i386
+               sect-diff relocs with addends.  properly write out ppc PICbase relocs where pic base
+               is not in the atom.
+
+
+2007-03-27     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5085863> Typo in ld man page (-exported_symbols_list)
+       * doc/man/man1/ld.1: fix typo
+       
+
+2007-03-26     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4727750> consider generating LC_UUID from a checksum of the file
+       * src/Options.h: change emitUUID() to getUUIDMode()
+       * src/Options.cpp: support -random_uuid
+       * src/MachOWriterExecutable.hpp: set uuid to be md5 hash of entire output file
+       
+
+2007-03-24     Nick Kledzik    <kledzik@apple.com>
+       
+       * src/MachOWriterExecutable.hpp: restructure writeAtoms() to copy all atoms in memory if possible
+
+
+2007-03-24     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5082603> ld -r of stripped .o file can incorrectly merge non-lazy pointers
+       * src/MachOWriterExecutable.hpp: when generating a .o file, non-lazy pointer with target offsets should be
+               encoded as LOCAL in the indirect symbol table
+       * unit-tests/test-cases/stripped-indirect-symbol-table: added test case
+
+
+2007-03-23     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5084564> SWB: ld64-72 errors building with gcc-4.2      
+       * src/MachOReaderDylib.hpp: add curly brackets in switch cases
+       * src/MachOWriterExecutable.hpp: rearrange classes so there are no template specialization forward references
+
+
+2007-03-23     Nick Kledzik    <kledzik@apple.com>
+
+       * src/ld.cpp: fix -print_statistics when using -dead_strip
+
+
+2007-03-23     Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOReaderRelocatable.hpp: generate better names for non-lazy pointers to the interior of atoms
+
+
+2007-03-16     Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: speed up ld -r a little by reversing relocs en mas
+
+
+2007-03-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4975277> ld Bus Error on missing command line arguments
+       * src/Options.cpp: check next argv[] is not NULL
+
+
+2007-03-16     Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/4832049> need to be able to order symbols in anonymous namespaces
+       * src/ld.cpp: add logic to do fuzzy matching of symbols with anonymous namespace usage
+       * unit-tests/test-cases/order_file-ans: added test case
+
+
+2007-03-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5042552> headerpad_max_install_names deprecated for 64-bit
+       * src/ld.cpp: make sure dylib load command order matches command line order
+       * src/Options.h: add maxMminimumHeaderPad()
+       * src/Options.cpp: add maxMminimumHeaderPad() set by -headerpad_max_install_names
+       * src/src/MachOWriterExecutable.hpp: check maxMminimumHeaderPad()
+       * doc/man/man1/ld.1: update man page about -headerpad_max_install_names
+
+
+2007-03-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4592484> Linker returns success although exported symbols are undefined.
+       * src/ld.cpp: turn missing symbols back into an error
+
+
+2007-03-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4019497> ld64 should handle linking against dylibs that have @loader_path based dylib load commands
+       * unit-tests/test-cases/loader_path: added test case
+       
+
+2007-03-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/3904828> linker should add implicit load commands for indirectly used public dylibs
+       <rdar://problem/4142277> Indirect libraries should be found using -F and -L options
+       <rdar://problem/4607755> Simplier, generalized way to re-export dylibs: LC_REEXPORT_DYLIB
+       * src/ld.cpp: reworked all dylib processing.  Readers can now add the dylib list.
+       * src/Options.h: add findFileUsingPaths()
+       * src/MachOReaderDylib.hpp: look in re-exported children instead of requring linker to do that
+       * src/ObjectFile.h: add processIndirectLibraries(), remove getDependentLibraryPaths()  
+       * src/machochecker.cpp: support LC_REEXPORT_DYLIB
+    * src/ExecutableFile.h: simplify DyLibUsed
+       * src/Options.cpp: add findFileUsingPaths().  add new re-export options
+       * src/MachOWriterExecutable.hpp: Use LC_REEXPORT_DYLIB when targetting 10.5
+       * doc/man/man1/ld.1: updated with new re-export options
+       * unit-tests/test-cases/indirect-path-search: added tests that -F and -L work with indirect dylibs
+       * unit-tests/test-cases/re-export-cases: added tests for all combinations of re-exporting
+       
+
+2007-03-14     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4982400> sort external relocations to optimize dyld performance 
+       * src/MachOWriterExecutable.hpp: added ExternalRelocSorter
+       * src/machochecker.cpp: verify external relocations are grouped by symbol number
+       * unit-tests/test-cases/external-reloc-sorting: added test case
+       
+       
+----- Tagged ld64-72
+
+2007-03-06     Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.cpp: ignore .objc_category_name_* symbols in .exp files
+       
+
+2007-03-06     Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.cpp: stop special casing mach_kernel and instead requre kernel to be built with -new_linker 
+       
+
+2007-03-06     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5044253> ld64-72 (experimental) is causing DejaGnu test failures
+       * src/MachOWriterExecutable.hpp: add optimizableGOTReferenceKind() to track GOT uses that cannot be optimized
+
+
+2007-03-06     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5026135> minimum header padding should be 32 to allow code signing
+       * src/Options.cpp: initialize fMinimumHeaderPad to 32
+       * src/MachOWriterExecutable.hpp: better calculation of header padding 
+       
+
+2007-03-06     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5033206> Linker crashes with -flat_namespace against two-level dylibs that might have re-exports
+       * src/ld.cpp: flat namespace should not allow NULL indirect readers
+
+
+2007-03-06     Nick Kledzik    <kledzik@apple.com>
+               
+       * src/MachOReaderRelocatable.hpp: don't error on S_COALESCED sections with anonymous atoms
+       * src/MachOWriterExecutable.hpp: set MH_PIE bit when linking -pie
+       * ld64.xcodeproj/project.pbxproj: don't echo environment when running unit test
+
+
+2007-03-01     Nick Kledzik    <kledzik@apple.com>
+
+       * doc/man/man1/ld.1: Add descriptions to all "rarely used options"
+
+
+2007-03-01     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4971033> Remove support for Essential Symbols: Warn about use of -Sp option; remove man page entry
+       * src/Options.cpp: make -Sp obsolete
+       * doc/man/man1/ld.1: make -Sp obsolete
+       
+
+2007-03-01     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/5040314> Support -pie   
+       * src/Options.h: Add positionIndependentExecutable()
+       * src/Options.cpp: Support -pie option to set positionIndependentExecutable()
+       * src/MachOWriterExecutable: if -pie is used, add extra local relocations and error if any
+               absolute addressing is used
+               
+
+2007-03-01     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4739044> ld64 should link mach_kernel during xnu builds to support dtrace
+       * src/ld.cpp: Ensure segments are laid out in discovery order.  Add support for kAbsoluteSymbol.
+                       Warn when merging symbols of different visiblity.  Warn when a tentative definition 
+                       is replaced by one a real definition with a smaller size.  Lay out __common section
+                       so that ones built with -fno-commons come before regular commons.
+       * src/ObjectFile.h: remove SegmentOffset ivar and getter/setters
+       * src/machochecker.cpp: allow images with no r/w segments
+       * src/MachOReaderRelocatable: Add AbsoluteAtom.  Sort tentative definitions by name instead of by size
+                       Add support for custom commons alignment.  
+       * src/Options.cpp: Fix spurious -sectalign warnings.  Don't use ld_classic when linking mach_kernel
+       * src/MachOWriterExecutable.hpp: Support kAbsoluteSymbol atoms. In -r mode, set custom alignment 
+                       for commons if alignment is not its size.  Support global __dtrace_probe labels.
+       * src/ObjectDump.cpp: add support for kAbsoluteSymbol atoms.
+       * unit-tests/test-cases/commons-alignment: Added test case for custom commons alignment
+       * unit-tests/test-cases/absolute-symbol: Added test case for basic absolute symbols
+       * unit-tests/test-cases/segment-order: Added test case that segments lay out in discovery order
+       * unit-tests/test-cases/commons-order: Added test case that commons lay out correctly
+       * unit-tests/test-cases/end-label: Added test case that a label used to mark the end of a section does not
+                       get associcated with the next section.
+       
+
+2007-02-23     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/3965017> gcc-5005: DejaGnu failures due to -frepo
+       * src/ld.cpp: Add quotes to referenced from name to make collect2 and -frepo happy
+       
+
+2007-02-22     Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: rework how padding after load commands is calculated
+
+
+2007-02-21     Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: extend special case of __mh_execute_header to static executables too
+
+
+2007-02-21     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/3882294> gcc link map option ( "-M" ) should be redirectable to file
+       * doc/man/man1/ld.1: added -map option description
+       * src/Options.h: added generatedMapPath()
+       * src/Options.cpp: set up generatedMapPath() if -map option is used
+       * src/MachOWriterExecutable.hpp: add writeMap() method to generate map file
+
+
+2007-02-19     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4557734> Implement GOT Load elimination optimization
+       * src/ld.cpp: track size of all atoms and if > 2GB sort large zero-fill atoms to end
+       * src/MachOWriterExecutable.hpp: If image size < 2GB, only generate GOT entries if value must be
+       updatable by dyld.  If > 2GB, only eliminate GOT entries to non-zero-fill atoms.  Any use
+       of an eliminated GOT entry has its code changed from MOVQ _foo@GOT(%rip) to LEAQ _foo(%rip).
+       * unit-tests/test-cases/large-data: added
+       * unit-tests/test-cases/got-elimination: added
+
+
+----- Tagged ld64-71.2
+
+2007-02-13     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4995303> new ld ignores -segprot option
+       * src/Options.h: expose customSegmentProtections()
+       * src/Options.cpp: parse -segprot option and populate customSegmentProtections()
+       * src/MachOWriterExecutable.hpp: use customSegmentProtections()
+
+
+2007-02-13     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4988068> i386 -stack_addr doesn't work
+       * src/MachOWriterExecutable.hpp: use correct offset into thread state record
+
+
+----- Tagged ld64-71.1
+
+2007-02-07     Nick Kledzik    <kledzik@apple.com>
+
+       * src/ld.cpp: sort __OBJC2 segment to be next to __OBJC segment
+
+
+2007-02-07     Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.cpp: change missing -seg_addr_table from an error to a warning
+
+
+2007-02-06     Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/4977311> Leopard 9A357: -dylib_file broken?
+       * src/MachOWriterExecutable.hpp: remove use of fInstallPathOverride
+       * src/Options.cpp: wire up -dylib_file option 
+       * src/Options.h: remove fInstallPathOverride.  add fDylibOverrides
+       * src/ld.cpp: check dylibOverrides() for indirect libraries
+       * unit-tests/test-cases/dylib_file: add test case
+       
+
+2007-02-05     Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOReaderDylib.hpp: don't warn about zero size __image_info sections
+
+
+2007-02-04      Rick Balocca    <rbalocca@apple.com>
+       Enable the failing cases for missing command line arguments
+
+2007-02-04      Rick Balocca    <rbalocca@apple.com>
+       Make sure that all .o's are checked by ObjectDump
+       and all macho are checked by machochecker
+
+2007-02-04      Rick Balocca    <rbalocca@apple.com>
+       Fix an endian problem with machochecker
+       Fix blank-stubs Makefile
+
+----- Tagged ld64-71
+
+2007-02-02      Rick Balocca    <rbalocca@apple.com>
+       blank-stubs test case: handle the case of a native ppc compile--this
+       sets the subtype, which must be passed to lipo
+
+2007-02-01      Rick Balocca    <rbalocca@apple.com>
+       make cpu-sub-types test more robust
+
+2007-02-01      Rick Balocca    <rbalocca@apple.com>
+       auto-arch tests were resulting in a false FAILs
+
+2007-02-01      Rick Balocca    <rbalocca@apple.com>
+       test cpu-sub-types was resulting in a false FAIL
+
+2007-02-01      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4969335> STD:VSC: c99 -o writes to file that does not have write permission
+       * src/MachOWriterExecutable.hpp: check file is writable before using it
+
+2007-02-01      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4965743> debug map (N_OSO) timestamps for object files in ranlib archive are incorrect
+       * src/MachOReaderArchive.hpp: parse modTime for .o files out of archive header
+
+2007-01-31      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4967535> 9A354: ld -all_load does *NOT* produce the same dSYM as *.o or -u
+       * src/ld.cpp: when using -all_load don't assume that all atoms have same reader
+       * unit-tests/test-cases/dwarf-archive-all_load: added
+
+----- Tagged ld64-70.1
+
+2007-01-31      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: in addObjectRelocs_powerpc() mask scattered r_address to 16-bits
+
+----- Tagged ld64-70
+
+
+2007-01-30      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4810668> linker should verify GC consistency of modules being linked into library
+       <rdar://problem/4474195> Support cpu-sub-types for ppc
+       * src/ObjectFile.h: Add getObjCConstraint() and getCpuConstraint()
+       * src/MachOReaderRelocatable.hpp:  don't make atom for __image_info section, instead parse constaints
+       * src/MachOReaderDylib.hpp: look at __image_info content to get constaints
+       * src/ld.cpp: add updateContraints() and checkObjc()
+       * src/MachOWriterExecutable.hpp: add ObjCInfoAtom to sythesize __image_info content
+       
+       
+2007-01-28      Nick Kledzik    <kledzik@apple.com>
+
+       src/*: remove ObjectFile::requiresFollowOnAtom() method
+       
+
+2007-01-28      Nick Kledzik    <kledzik@apple.com>
+
+       src/ld.cpp: enable LLVM_SUPPORT by default
+       src/LLVMReader.hpp: don't use absolute paths for llvm headers and libraries
+       
+
+2007-01-26      Rick Balocca    <rbalocca@apple.com>
+       * src/ObjectDump.cpp: The usage() message was incorrect.
+
+
+2007-01-25      Rick Balocca    <rbalocca@apple.com>
+       * unit-tests/test-cases/zero-fill3:  It was reporting FAIL on ld64 error return.
+               It should have been checking for non-error return.
+
+
+2007-01-24      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4952297> x86 fast stubs should not cross 64-byte boundries
+       * src/MachOWriterExecutable.hpp: for x86, 64-byte align __jump_table section 
+       and make 64-btye crossing stubs be empty entries with indirect symbol table 
+       entry of INDIRECT_SYMBOL_ABS
+
+
+2007-01-19      Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.h: add readOnlyx86Stubs()
+       * src/Options.cpp: support -read_only_stubs
+       * src/MachOWriterExecutable.hpp: make __IMPORT segment not writable if -read_only_stubs is used
+       
+
+2007-01-16  Eric Christopher  <echristo@apple.com>
+
+       <rdar://problem/4856341> ld64 --help isn't recognized
+       * src/Options.cpp (Options::parse): Support --help and -help.
+
+
+2007-01-15      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOFileAbstraction.hpp: add range checking on macho_scattered_relocation_info::set_r_address()
+
+
+2007-01-14      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4514409> Support wildcards in contents of -exported_symbols_list
+       * src/Options.h: add SetWithWildcards class
+       * src/Options.cpp: add -exported_symbol and -unexported_symbol and use SetWithWildcards
+       * doc/man/man1/ld.1: add -exported_symbol and wildcard explanation
+       * unit-tests/test-cases/exported-symbols-wildcards: added test case
+
+
+2007-01-10      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4868270> [U]SDT probes should use C calling convention
+       * src/Options.cpp: Add -read_only_dof
+       * src/ld.cpp: create __dof section(s) based on probe and isenabled sites
+       * src/MachOReaderRelocatable.hpp: parse new sdt 2.0 probes encoded in .o files
+       * src/MachOWriterExecutable.hpp: handle regenerating dtrace probes into .o files
+       * unit-tests/test-cases/dtrace-static-probes: added test case
+
+
+----- Tagged ld64-69.8
+
+2007-01-30      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4964508> Support LD_FORCE_NO_SEG_ADDR_TABLE
+       * src/Options.cpp: Support LD_FORCE_NO_SEG_ADDR_TABLE
+       
+
+----- Tagged ld64-69.7
+
+2007-01-25      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4949507> Leopard9A351: CFM Apps Are Broken because CFM glue is missing
+       * src/MachOReaderRelocatable.hpp: check S_ATTR_NO_DEAD_STRIP in dontDeadStrip()
+
+
+----- Tagged ld64-69.6
+
+2007-01-24      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4947347> LD_TRACE_ARCHIVES should only print out when a .o is actually used from an archive
+       * src/ld.cpp: create and use logArchive() 
+
+       
+----- Tagged ld64-69.5
+
+2007-01-22      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4946075> 9A350: can't link ppc programs with ld_classic
+       * src/Options.cpp: Remove support for LD_NO_CLASSIC_LINKER. Add support for -classic_linker
+
+       
+----- Tagged ld64-69.4
+       
+2007-01-17      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4925645> QTComponents does not link with ld64
+       * src/MachOReaderRelocatable.hpp: handle N_RSYM and N_PSYM stabs
+
+       
+----- Tagged ld64-69.3
+
+2007-01-03      Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.cpp: If the same dylib is specified twice and the second is specified weak, make it weak
+
+
+----- Tagged ld64-69.2
+
+2006-12-18      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4889729> -dead_strip without -exported_symbols_list should not strip global functions from archives
+       * src/ld.cpp: when adding a .o file from an archive, add all its global symbols to live roots
+       * unit-tests/test-cases/dead_strip-archive: added
+
+
+2006-12-18      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4889409> flat_namespace main executables do not need to indirect interior references
+       * src/MachOWriterExecutable.hpp: don't indirect references to global symbols in main executables
+       * unit-tests/test-cases/flat-main: updated to test for indirection
+       * unit-tests/test-cases/flat-dylib: added
+
+
+----- Tagged ld64-69.1
+
+2006-12-15      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4886721> -flat_namespace does not work with -mdynamic-no-pic
+       * src/MachOWriterExecutable.hpp: rework checking for use of ppc absolute addressing to allow them as long as
+         the target is within the same linkage unit.
+
+
+2006-12-15      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4886652> -ObjC should only load .o with .objc_ symbols
+       * src/Options.cpp: remove warning from -ObjC and have it instead set fLoadAllObjcObjectsFromArchives
+       * src/MachOReaderArchive.hpp: when -ObjC is used, preload all .o files from archives that contain .objc_ symbols
+
+
+----- Tagged ld64-69
+
+2006-12-13      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4879913> prebound interior pointers must be non-zero
+       * src/MachOWriterExecutable.hpp: in fixUpReference_powerpc() set lazy pointers bound to with the dylib to
+        their target value. Properly set REFERENCE_FLAG_UNDEFINED_* flags in reference table and n_desc
+
+
+2006-12-09      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4868738> ld64 fails to detect error that ld_classic does
+       * src/MachOWriterExecutable.hpp: check for absolute reloc to an external symbol
+       * src/MachOReaderRelocatable.hpp: ignore -mlong-branch stubs in .o files
+
+
+2006-12-09      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4874209> symbols with REFERENCED_DYNAMICALLY should never be stripped
+       * src/MachOWriterExecutable.hpp: update Writer<A>::shouldExport() to check for kSymbolTableInAndNeverStrip
+       * unit-tests/test-cases/main-stripped: add test that dynamically referenced symbol cannot be stripped
+
+
+2006-12-08      Nick Kledzik    <kledzik@apple.com>
+
+       * unit-tests/test-cases/allowable-client: add variant test cases (e.g. CoreServices_profile)
+       * src/ld.cpp: allow frameworks with variant install names (e.g. CoreServices_profile) to be private clients
+
+
+2006-12-08      Nick Kledzik    <kledzik@apple.com>
+
+       * doc/man/man1/ld.1: rewrite man page
+       * src/Options.h: add warnObsolete()
+       * src/Options.cpp: use warnObsolete() on many options.  Make nonWeak the weak-mis-match default.
+               Make -ObjC mean -all_load.
+
+----- Tagged ld64-68.3
+
+2006-12-05      Nick Kledzik    <kledzik@apple.com>
+
+       * src/ld.cpp: allow umbrella frameworks to have variant install names (e.g. CoreServices_profile) and still link
+
+
+----- Tagged ld64-68.2
+
+2006-12-05      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.cpp: Use N_PBUD in the symbol table for undefined symbols in prebound dylibs
+
+
+----- Tagged ld64-68.1
+
+2006-12-01      Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.cpp: always generate module tables for 32-bit architectures so that ld_classic
+               can link against them
+
+
+----- Tagged ld64-68
+
+2006-12-01      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4858299> seg_addr_table needs matching fuzziness
+       * src/Options.cpp: special case a how a dozen dylib are looked up in the seg_addr_table
+
+
+2006-12-01      Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.cpp: have all -static links for 32-bit archs roll over to ld_classic unless
+               LD_NO_CLASSIC_LINKER_STATIC is set.
+       * unit-tests/bin/make-recursive.pl: set LD_NO_CLASSIC_LINKER_STATIC for unit tests
+
+
+2006-11-29      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4855542> ld64-67: QTComponents fails to build
+       * src/MachOReaderRelocatable.hpp: don't error out when a local non-lazy pointer does not point to a symbol
+       * unit-tests/test-cases/strip_local: added test case
+
+
+2006-11-28      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4433496> Need a way to mark libraries usable by dynamic linker but unusable by static linker
+       * src/Options.cpp: allow -client_name to be used with main executables
+       * src/ld.cpp: generalize -allowable_client.  Any dylib can now restrict who can link against it.  As a convention
+               linking with -allowable_client '!' will mean no one can statically link with the dylib.  It can still be loaded
+               dynamically, or by any existing clients, but no new clients can link with it.
+       * unit-tests/test-cases/allowable-client/Makefile: enable previously commented out test cases.  Add test cases
+               of a dylib that allows no clients and just one client
+
+2006-11-27      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4795615> -final_output should be used if -install_name not used
+       * src/Options.cpp: fall back to using -final_output for install name
+
+
+----- Tagged ld64-67
+
+2006-11-17      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: support __IMPORT segment being slide independently of __DATA segment in shared cache
+
+
+2006-11-16      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4838262> 9a303: ld -filelist Bus Error
+       * src/Options.cpp: add check that -filelist is followed by an argument
+
+
+2006-11-16      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: when building split-seg dylibs, LINKEDIT goes in read-only side
+
+
+2006-11-15      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: set proper attributes for __eh_frame in ld -r mode
+       * unit-tests/test-cases/eh_frame: added test case
+
+
+2006-11-10      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOReaderRelocatable.hpp: redirect references to static weak stubs to the real target
+
+
+2006-11-09      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: r_address is offset from first LC_SEGMENT vmaddr - not from segment with lowest address
+
+
+----- Tagged ld64-66.1
+
+2006-11-09      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: initialize fModuleInfoAtom to zero
+
+
+2006-11-08      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4821985> FSF GCC's libjava doesn't link with Ochre ld64
+       * src/MachOReaderRelocatable.hpp: ignore debug_line section if debug_info section is missing or empty
+
+----- Tagged ld64-66
+
+2006-11-07      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4824368> SWB: d64-65 does not built usage split-seg dylibs
+       * src/MachOWriterExecutable.hpp: when prebinding split-seg correctly set r_address fields and on
+       disk values for external relocations
+       * unit-tests/test-cases/prebound-split-seg: added test case
+
+
+2006-11-03      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOReaderDylib.hpp: don't report dependent libraries if MH_NO_REEXPORTED_DYLIBS bit is set
+       * src/MachOWriterExecutable.hpp: set MH_NO_REEXPORTED_DYLIBS bit if dylib does not logically re-export any other dylibs
+       * unit-tests/test-cases/re-export-flag: added test case
+       * src/machochecker.cpp: validate use of MH_NO_REEXPORTED_DYLIBS
+
+
+2006-11-02      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4814565> Mysterious messages from ld64 with MACOSX_DEPLOYMENT_TARGET = 10.5
+       * src/MachOWriterExecutable.hpp: kPointerWeakImport is a valid reference type to cross segments
+
+
+2006-11-02      Nick Kledzik    <kledzik@apple.com>
+
+       * src/Options.cpp,h: Add support for -rpath
+       * src/MachOFileAbstraction.hpp: add macho_rpath_command
+       * src/MachOWriterExecutable.hpp: add RPathLoadCommandsAtom to create LC_RPATH for each -rpath
+
+
+----- Tagged ld64-65
+
+2006-10-30      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4729162> x86_64 default stack_addr is wrong
+       * src/Options.cpp: change default 64-bit stack location when using -stack_size
+
+
+2006-10-30      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4474316> dylibs need modules for 10.3 and for ld_classic in Salt
+       * src/MachOWriterExecutable.hpp: add ModuleInfoLinkEditAtom to create module table stuff
+       * src/Options.cpp,h: Add needsModuleTable()
+       * src/MachOFileAbstraction.hpp: Add macho_dylib_module, macho_dylib_reference, and macho_dylib_table_of_contents
+
+
+2006-10-27      Nick Kledzik    <kledzik@apple.com>
+
+       * unit-tests/test-cases/no-uuid/Makefile: add -gstabs+ to be compatible with latest compiler
+       * unit-tests/test-cases/stabs-coalesce/Makefile: add -gstabs+ to be compatible with latest compiler
+
+
+2006-10-26      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4585230> i386 -mdynamic-no-pic switch statement jump table is out of line
+       * src/MachOWriterExecutable.hpp: for i386 don't check for direct references to weak symbols
+
+
+2006-10-26  Devang Patel  <dpatel@apple.com>
+
+       * src/LLVMReader.hpp: Supply final output file path to optimizer.
+
+2006-10-26  Devang Patel  <dpatel@apple.com>
+
+       * src/ObjectFile.h: Make setSection* methods virtual.
+       * src/LLVMReader.hpp: Override setSection* methods.
+
+2006-10-26  Devang Patel  <dpatel@apple.com>
+
+       * unit-tests/test-case/llvm-integration/a13.h: New.
+       * unit-tests/test-case/llvm-integration/a13.cc: New.
+       * unit-tests/test-case/llvm-integration/main13.cc: New.
+
+2006-10-26  Devang Patel  <dpatel@apple.com>
+
+       * src/options.h, src/options.cpp: Add -save-temps command line option.
+       * src/LLVMReader.hpp: Use saveTemps option.
+
+
+2006-10-26  Devang Patel  <dpatel@apple.com>
+
+       * src/LLVMReader.hpp: Remove invalid module from memory.
+
+2006-10-26  Devang Patel  <dpatel@apple.com>
+
+       * src/LLVMReader.hpp: Collect symbol alignment info from LLVM optimizer.
+
+2006-10-21  Eric Christopher  <echristo@apple.com>
+
+       * src/ld.cpp (Linker::Linker): Check for LD_NO_CLASSIC_LINKER before
+       invoking ld_classic.
+       * unit-tests/test-cases/relocs-literals/Makefile: Run for -mdynamic-no-pic
+       and pic.
+       * unit-tests/test-cases/static-executable/Makefile: Skip for 64-bit. Add
+       -dead_strip to command line.
+
+----- Tagged ld64-64.2
+
+2006-10-19      Nick Kledzik    <kledzik@apple.com>
+
+       * ld64.xcodeproj/project.pbxproj: stop copying LLVMReader.hpp into man1 directory
+
+----- Tagged ld64-64.1
+
+2006-10-19      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4791643> ld64-63.1 erroneously coalesces an empty string with a non-empty string
+       * src/MachOReaderRelocatable.hpp: rework cstring parsing to not assume all strings are start
+         at section alignment boundaries, and when coalescing empty strings always use one with greatest
+         alignment requirement
+       * src/MachOWriterExecutable.hpp: in -r mode, don't pad end of cstring section
+       * src/ObjectFile.h: correctly name leadingZeros() as trailingZeros()
+       * src/ld.cpp: leadingZeros() --> trailingZeros()
+
+
+2006-10-18  Eric Christopher  <echristo@apple.com>
+
+       * unit-tests/test-cases/read-only-relocs/Makefile: Skip for x86_64.
+       * unit-tests/test-cases/llvm-integration/Makefile: Skip if llvm isn't
+       present.
+
+2006-10-18      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4783853> ld64 change required to go with assembler cstring change
+       <rdar://problem/4732996> ld64 should error when a local relocation references an address outside its section
+       * src/MachOReaderRelocatable.hpp: for x86_64  in order to work with local or external relocations to cstrings
+       change parser to allow atoms with a pending name that is resolved after references are instantiated.
+       Make direct references to kRegularDefinition atoms.
+       * src/MachOWriterExecutable.hpp: in -r mode for x86_64 generate L* labels for cstrings and use external relocations
+       * unit-tests/test-cases/relocs-literals/test.c: add two cases of cstring literal plus addend
+
+
+2006-10-06      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4786250> check MACOSX_DEPLOYMENT_TARGET if -macosx_version_min is not used
+       * src/Options.cpp: if -macosx_version_min is not used, check MACOSX_DEPLOYMENT_TARGET, if
+       that is unused, default to 10.5
+
+----- Tagged ld64-64
+
+2006-10-06      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4756806> crash in ppc64 program - bl to saveFP, but saveFP is too far away?
+       * src/MachOWriterExecutable.hpp: in addPPCBranchIslands(), properly account for growth of __text
+
+
+2006-10-06      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4769120> Linker-defined alias converts reference into definition and generates error.
+       * src/MachOReaderRelocatable.hpp: only alias symbols actually in the symbol table
+
+
+2006-10-06      Nick Kledzik    <kledzik@apple.com>
+
+       * unit-tests/test-cases/dwarf-debug-notes/Makefile: crt1.o no longer has stabs, so don't need to strip it
+       * unit-tests/test-cases/dwarf-debug-notes-r/Makefile: crt1.o no longer has stabs, so don't need to strip it
+
+
+2006-10-06      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOReaderRelocatable.hpp: rework dwarf line parsing to fix warnings that starting
+       showing up with gcc-5421
+
+
+2006-10-05  Eric Christopher  <echristo@apple.com>
+
+       <rdar://problem/4760935> ld64 needs to support libtool options
+       * src/Options.cpp (Options::parse): Add -noall_load, -install_name,
+       -current_version and -compatibility_version.
+
+2006-10-03  Eric Christopher  <echristo@apple.com>
+
+       * src/Options.cpp (Options::gotoClassicLinker): Use execvp
+       to call ld_classic.
+
+2006-10-03  Eric Christopher  <echristo@apple.com>
+
+       * unit-tests/test-cases/tentative-to-real/Makefile: Clean up after tests.
+
+2006-10-03  Eric Christopher  <echristo@apple.com>
+
+       * unit-tests/include/common.makefile (VALID_ARCHS): Add x86_64.
+       (OTOOL): Remove munging based on ARCH.
+
+2006-09-29      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4743925> problem merging .o files built with and without -fno-common
+       src/Options.*: make MakeTentativeDefinitionsReal a reader option
+       src/ObjectFile.h: make MakeTentativeDefinitionsReal a reader option
+       src/MachOWriterExecutable.hpp: make MakeTentativeDefinitionsReal a reader option
+       src/MachOReaderRelocatable.hpp: only assign a section name of __common to
+               tentative defintions when making a final linked image
+
+
+2006-09-28      Nick Kledzik    <kledzik@apple.com>
+
+       src/Options.h/.cpp: add support for -segaddr option
+       src/MachOWriterExecutable.hpp: In Writer::assignFileOffsets(), use -segaddr info
+
+
+2006-09-28      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4587349> Emit new CPU subtypes for ppc64 and x86-64 when targeting 10.5 or later
+       src/MachOWriterExecutable.hpp: set high bit of cpusubtype of 64-bit main executables when targeting 10.5 or later
+
+
+2006-09-28     Devang Patel    <dpatel@apple.com>
+
+       Add LLVM LTO support
+       src/LLVMReader.hpp: New file.
+       src/ld.cpp: Add optimization phase. Use LLVM LTO.
+       unit-tests/test-cases/llvm-integration: New tests.
+
+2006-09-27      Nick Kledzik    <kledzik@apple.com>
+
+       ld64.xcodeproj/project.pbxproj: remove accidental install of source file into man1
+
+
+2006-09-25      Nick Kledzik    <kledzik@apple.com>
+
+       src/Architectures.hpp: add kPointerDiff16 for ppc and ppc64
+       src/MachOReaderRelocatable.hpp: support kPointerDiff16
+       src/MachOWriterExecutable.hpp: support kPointerDiff16
+
+----- Tagged ld64-63.1
+
 2006-09-22      Nick Kledzik    <kledzik@apple.com>
 
-       ld64.xcodeproj/project.pbxproj: change install name back to ld64
-       src/Options.cpp: remove support for rolling over to ld_classic
-       src/ld.cpp: remove support for rolling over to ld_classic
+       src/MachOWriterExecutable.hpp: include stubs in LC_SEGMENT_SPLIT_INFO
+
+
+2006-09-21      Nick Kledzik    <kledzik@apple.com>
+
+       src/Options.cpp: disable split-seg dylibs for 64-bit architectures
+
+
+2006-09-19      Nick Kledzik    <kledzik@apple.com>
+
+       src/MachOReaderRelocatable.hpp: rework __cstring parsing to better handle mixed alignment cstrings
+       src/MachOWriterExecutable.hpp: in -r mode, make all __cstrings aligned to section alignment
+
+
+2006-09-19      Nick Kledzik    <kledzik@apple.com>
+
+       src/MachOWriterExecutable.hpp: rework encoding of LC_SEGMENT_SPLIT_INFO
+
+
+2006-09-19      Nick Kledzik    <kledzik@apple.com>
+
+       src/Options.cpp: check for -search_paths_first in first pass
+
+
+----- Tagged ld64-63
+
+2006-09-15      Nick Kledzik    <kledzik@apple.com>
+
+       src/Options.cpp: since the ld64 will repeatedly search an archive, and some project list archives
+               multiple times on command line to work with traditional linkers, automatically ignore duplicate libraries
+       unit-tests/test-cases/archive-duplicate: added test case
+
+
+2006-09-15      Nick Kledzik    <kledzik@apple.com>
+
+       src/Options.cpp: support -r -static
+       src/MachOWriterExecutable.hpp: support -r -static an don't generate LC_DYSYMTAB
+
+
+2006-09-14      Nick Kledzik    <kledzik@apple.com>
+
+       src/MachOWriterExecutable.hpp: in -r mode references to weak symbols should not create external relocations
+               as that can cause nmedit to errror later.
+
+
+2006-09-13      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4718189> ld64: Handle .objc_class_name exports specially
+       src/Options.cpp: add hack so that .objc_class_name_XXX in -exported_symbols_list imples _OBJC_CLASS_$_XXX
+       src/ld.cpp: add hack to supporess errors about .objc_class_name_XXX or _OBJC_CLASS_$_XXX being undefined
+
+
+2006-09-12      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4474172> Support -prebind when targeting ppc and OS < 10.4
+       src/Options.h: add splitSeg() and baseWritableAddress()
+       src/Options.cpp: Add support for -seg_addr_table and LD_SEG_ADDR_TABLE, and -prebind and LD_PREBIND.
+       src/src/MachOWriterExecutable.hpp: support split-seg and canonical prebound files to be generated
+
+
+2006-09-11      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4464904> Linking a dylib or binary from identical binaries should produce the same output
+       src/MachOWriterExecutable.hpp: set the timestamps to be constant
+
+
+2006-09-11      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4070025> Linker support for ordering all sections and symbols
+       src/Options.cpp: Add -order_file_statistics.  Allow architecture prefixes in order files
+       src/ld.cpp: Use fOptions.printOrderFileStatistics()
+
 
+2006-09-11      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/3894079> Support -sectorder
+       unit-tests/test-cases/order_file: added test case
+       src/ld.cpp: Implement order file support in Linker::sortAtoms()
+       src/Options.h: add Options.orderedSymbols()
+       src/Options.cpp: add parseOrderFile(), implement -order_file
+
+
+2006-09-07      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4637023> need -i for 64-bit (or equivalent)
+       <rdar://problem/4014529> Support -i for aliasing exported symbols
+       unit-tests/test-cases/alias-objects: added
+       unit-tests/test-cases/alias-command-line: added
+       src/ObjectFile.h: Added Atom::getOrdinal() as new way to sort atoms. Added ReaderOptions.fAliases
+       src/MachOReaderRelocatable.hpp: Added SymbolAliasAtom to handle multiple symbols to same address
+       src/MachOReaderArchive.hpp: implement Atom::getOrdinal() to space out atom ordinals across member objects
+       src/Options.cpp: support -i, -alias, -alias_list.  Move search of /Network/Library/Frameworks to after /System/Library/Frameworks
+       src/MachOWriterExecutable.hpp: pad out seg_info data.  Implement getOrdinal().
+       src/ObjectDump.cpp: call constructors directly instead of using make() wrapper
+
+
+2006-09-01      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4458878> Need the ability to tag libraries/plug-ins with security attributes
+       src/MachOReaderDylib.hpp: add warning if using -root_safe or -setuid_safe and link against dylib that is not
+       src/ObjectFile.h: add ReaderOption fRootSafe and fSetuidSafe
+       src/Options.cpp: handle -root_safe or -setuid_safe command line options
+       src/MachOWriterExecutable.hpp: set MH_ROOT_SAFE and MH_SETUID_SAFE flags
+
+
+2006-08-31      Nick Kledzik    <kledzik@apple.com>
+
+       src/ld.cpp: Add Linker::processDTrace() for processing dtrace static probes
+       src/OpaqueSection.hpp: renamed, add symbol name, add ability to add references
+       ld64.xcodeproj/project.pbxproj: remove SectCreate.cpp, add OpaqueSection.hpp
+
+
+2006-08-28      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4571042> Add convention for removing symbols at link time
+       <rdar://problem/3962731> Assembler -L option causes ld64 to split stubs
+       unit-tests/test-cases/special-labels: added test case
+       src/MachOReaderRelocatable.hpp: ignore L* labels, make l* labels as kSymbolTableNotIn
+
+
+2006-08-28      Nick Kledzik    <kledzik@apple.com>
+
+       src/lObjectFile.h: refactor isTargetUnbound() into getTargetBinding()
+       src/ld.cpp: create __dof section in final linked images from dtrace static probes
+       src/Architectures.hpp: add kDtraceProbe
+       src/Options.h/cpp: Add support for -dtrace
+       src/machochecker.cpp: support LC_SEGMENT_SPLIT_INFO
+       src/MachOWriterExecutable.hpp: support kDtraceProbe
+       src/MachOReaderRelocatable.hpp: suppport kDtraceProbe
+
+
+2006-08-25      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4701529> generate LC_SEGMENT_SPLIT_INFO for 10.5 or later dylibs
+       src/Options.h&.cpp: implement sharedRegionEligible() to control when LC_SEGMENT_SPLIT_INFO is added
+       src/MachOFileAbstraction.hpp: add macho_linkedit_data_command
+       src/MachOWriterExecutable.hpp: generate LC_SEGMENT_SPLIT_INFO load command and linkedit content
 
 ----- Tagged ld64-62
 
        src/MachOWriterExecutable.hpp: update for new Alignment type, use modulus when calculating layout address
        src/ObjectDump.cpp: print richer Alignment info
        unit-tests/test-cases/align-modulus: added test case
-       
+
 
 2006-08-11      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4654131> ld64 while linking cc1 [ when dead_strip is ON]
        src/ld.cpp: Add ivar fAtomsWithUnresolvedReferences to track atoms not initially resolvable
        unit-tests/test-cases/dead_strip-archive: added test case
-       
+
 
 2006-07-31      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4656617> x86_64: instructions with immediate and rip-relative operands need to use new relocation types
-       src/MachOWriterExecutable.hpp: generate new reloc types in -r mode      
+       src/MachOWriterExecutable.hpp: generate new reloc types in -r mode
        src/MachOReaderRelocatable.hpp: parse new reloc types
        unit-tests/test-cases/relocs-asm/relocs-asm.s: add test cases for new reloc type
-       
+
 
 2006-07-18      Nick Kledzik    <kledzik@apple.com>
 
        src/MachOReaderRelocatable.hpp: suppress warning about dwarf info parsing for one benign no-op case
        the compiler emits when there are not functions in the __text section
-       
+
 
 2006-07-17      Nick Kledzik    <kledzik@apple.com>
 
-       <rdar://problem/4634840> faster debug note generateion
-       src/ld.cpp: rework collectDebugInfo() to produce all debug notes in one pass, intead of a 
+       <rdar://problem/4634840> faster debug note generation
+       src/ld.cpp: rework collectDebugInfo() to produce all debug notes in one pass, intead of a
        pass per .o file. Added timing info for collectDebugInfo() to -print_statistics
-       unit-tests/test-cases/dwarf-debug-notes-r/Makefile: add expliced -arch to ld -r 
+       unit-tests/test-cases/dwarf-debug-notes-r/Makefile: add expliced -arch to ld -r
        unit-tests/test-cases/dwarf-debug-notes-r/expected-stabs: alter for new debug notes order
-       
+
 
 2006-07-17      Nick Kledzik    <kledzik@apple.com>
 
 ----- Tagged ld64-61.1
 
 2006-07-11      Nick Kledzik    <kledzik@apple.com>
-       
+
        <rdar://problem/4622049> ld64-61: gcc DejaGnu tests failing due to -arch followed by unknown architecture name
        src/Options.cpp: map ppc750, ppc7400, ppc7450, and ppc970 to ppc. Improve error message
 
        src/ld.cpp: alter version string
        ld64.xcodeproj/project.pbxproj: change install location to /usr/bin/ld, add symlink from /usr/bin/ld64
        doc/man/man1/ld.1: added
-       
+
 ----- Tagged ld64-60
 
 2006-06-28      Nick Kledzik    <kledzik@apple.com>
-       
+
        <rdar://problem/4604539> Can't link large ppc64 program: ld64 says "bl out of range"
        MachOWriterExecutable.hpp: fix branch island generation to work for weak_import functions
        and properly chain together branch islands
 
 2006-06-27      Nick Kledzik    <kledzik@apple.com>
 
-       src/MachOReaderRelocatable.hpp: handle N_GSYM without ending :G() since that is how 
-       dwarf debug notes are formed. 
+       src/MachOReaderRelocatable.hpp: handle N_GSYM without ending :G() since that is how
+       dwarf debug notes are formed.
 
 2006-06-23      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4599239 objc class with no superclass causes bad undefined symbol
        src/MachOReaderRelocatable.hpp: handle NULL superclass in objc_class
        unit-tests/test-cases/relocs-objc/test.m: add case with no super class
-       
+
 
 2006-06-23      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4596726> ld64 lost DWARF debug notes
        src/MachOReaderRelocatable.hpp: add fHasUUID so kDebugInfoStabsUUID can be set later
        unit-tests/test-cases/dwarf-debug-notes-r: added test case
-       
+
 2006-06-21      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4567995> python 64-bit address miscalculation
        src/MachOReaderRelocatable.hpp: change getTargetOffset() to sign extend the 32-bit value to 64-bits
-       
+
 2006-06-21      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4535036> ld64 seems to offset things incorrectly when using -r
 2006-06-15      Nick Kledzik    <kledzik@apple.com>
 
        src/rebase.cpp: fix to build in CurryWeed
-       ld64.xcodeproj/project.pbxproj: fix to build properly in CurryWeed 
+       ld64.xcodeproj/project.pbxproj: fix to build properly in CurryWeed
 
 2006-06-15      Nick Kledzik    <kledzik@apple.com>
 
-       <rdar://problem/4495309> Support .objc_class_name_* symbols     
+       <rdar://problem/4495309> Support .objc_class_name_* symbols
        src/ObjectFile.h: Add kSymbolTableInAsAbsolute
        src/MachOReaderRelocatable.hpp: synthesize references to required objc classes
        src/MachOWriterExecutable.hpp: write objc_class_name as absolute symbol
        unit-tests/test-cases/rebase-basic: added
        doc/man/man1/rebase.1: added
        ld64.xcodeproj/project.pbxproj:  added rebase target.  changed all targets to build with dwarf
-       
+
 
 2006-06-10      Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4565088> ld64 is not adding a final '/' char on the initial directory-name SO stab debug map entry
        ld.cpp: Change Linker::synthesizeStabs() to assure directory SO always has a trailing slash
        unit-tests/test-cases/dwarf-debug-notes/expected-stabs: update with trailing /
-       
+
 2006-06-06      Nick Kledzik    <kledzik@apple.com>
 
-       <rdar://problem/4572702> -sectcreate of a 0-byte section fails  
+       <rdar://problem/4572702> -sectcreate of a 0-byte section fails
        MachOWriterExecutable.cpp: Don't error out on zero length segments
        MachOWriterExecutable.cpp: For ppc64 reloc base address is the first writable segment iff
         there is a writable segment >4GB from base address
        * src/MachOReaderRelocatable.cpp: mark non-lazy-pointer atoms as scopeTranslationUnit if targetting a static symbol
 
 
+#ifndef __OPEN_SOURCE__
+2006-04-27      Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4498971> dyld crashes ungracefully on x86_64 when there is an internal exception
+       * src/MachOWriterExecutable.cpp: allow non-zero PCRELGOT addends (used by C++ eh frames)
+#endif
 
 2006-04-21      Nick Kledzik    <kledzik@apple.com>
 
 
 ----- Tagged ld64-50
 
+#ifndef __OPEN_SOURCE__
+2006-03-29      Nick Kledzik    <kledzik@apple.com>
+
+       * src/MachOWriterExecutable.hpp: fix x86_64 addends when -multi_module forces an external relocation
+#endif
 
 2006-03-29      Nick Kledzik    <kledzik@apple.com>
 
        * src/Options.cpp: setup ReaderOptions.fForFinalLinkedImage
        * src/MachOReaderRelocatable.hpp: mark .eh symbols kSymbolTableNotIn when building final linked image
 
+#ifndef __OPEN_SOURCE__
+2006-03-21     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4475928> Inca ld64-45 fatal error with C++ and asm() renaming
+       * src/MachOReaderRelocatable.hpp: fix Reader<x86_64>::makeReferenceToEH(() to walk relocations to find
+       target of eh symbol, rather assume target name is eh symbol name less .eh
+
+#endif
 2006-03-21     Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4473742> ld64 does not parse optional second argument to -filelist
        * unit-tests/test-cases/filelist: added
        * src/Options.cpp: in Options::loadFileList() handle comma option
 
+#ifndef __OPEN_SOURCE__
+2006-03-21     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4483625> 32-bit pointer difference out of range for cxx eh frame
+       * src/MachOReaderRelocatable.hpp: x86_64 doesn't have anonymous non-lazy-pointers
+       * src/machochecker.cpp: fix validFile() for x86_64
+       * unit-tests/run-all-unit-tests: add x86_64
+       * unit-tests/include/common.makefile: don't add -g to all compilers
+       * unit-tests/test-cases/relocs-asm/relocs-asm.s: add x86_64 test cases
+       * unit-tests/test-cases/relocs-c/Makefile: fix to work with x86_64
+       * src/ld.cpp: add hack to use i386 dylibs if x86_64 don't exist
+
+2006-03-19     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4483330> ld64 crashes whenever I try to link with dylib1.o
+       * src/MachOReaderRelocatable.hpp: in Reader<x86_64>::addRelocReference() fix local relocations
+#endif
 
 ----- Tagged ld64-47.1
 
+#ifndef __OPEN_SOURCE__
+2006-03-16     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4459633> ld64-41 in Leopard doesn't have x86_64 support
+       * ld64.xcodeproj/project.pbxproj: enable x86_64 for Leopard
+#endif
 
 ----- Tagged ld64-47
 
+#ifndef __OPEN_SOURCE__
+2006-03-14     Nick Kledzik    <kledzik@apple.com>
+
+       * src/Architectures.hpp: redo x86_64 relocation types
+       * src/MachOReaderRelocatable.hpp: redo x86_64 relocation types, make some section type illegal for x86_64
+       * src/MachOWriterExecutable.hpp: redo x86_64 relocation types
+
+2006-03-13     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4467122> ld64 -r does not handle internal relocations for x86_64
+       * src/MachOWriterExecutable.hpp: handle internal relocations in Writer<x86_64>::fixUpReferenceRelocatable()
+         and Writer<x86_64>::addObjectRelocs().
+#endif
 
 ----- Tagged ld64-46
 
 
 ----- Tagged ld64-45
 
+#ifndef __OPEN_SOURCE__
+2006-03-06     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4466930> <rdar://problem/4467982> ld64 failed: rel32 out of range when linking a dylib
+       * src/MachOWriterExecutable.cpp: in  Writer<x86_64>::fixUpReferenceFinal add (int32_t) cast
+#endif
 
 2006-03-06     Nick Kledzik    <kledzik@apple.com>
 
        <rdar://problem/4466930> LP64/9A122: ld64: hang when trying to link DiscRecording framework
        * src/Options.cpp: addSectionAlignment, warn on zero.  Use log2() for alignment conversion
 
+#ifndef __OPEN_SOURCE__
+2006-03-06     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4457818> x86_THREAD_STATE64_COUNT will change, ld64 must adapt
+       * src/MachOWriterExecutable.hpp: update ThreadsLoadCommandsAtom<x86_64> for new thread status layout
+#endif
 
 ----- Tagged ld64-44
 
 
 ----- Tagged ld64-43
 
+#ifndef __OPEN_SOURCE__
+2006-03-03     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/4465443> RIP-relative offsets aren't handled properly when the instruction has immediate operands
+       * src/Architectures.hpp: add x86_64::kPCRel32_*
+       * src/MachOReaderRelocatable.hpp: generate x86_64::kPCRel32_*
+       * src/MachOWriterExecutable.hpp: process x86_64::kPCRel32_*
+#endif
 
 2006-03-02     Nick Kledzik    <kledzik@apple.com>
 
index 835e69ef0614caf706a0f17612aa3ec8f7ecbf81..f5c4f158551da8992afc73461057f3bdfe5026fe 100644 (file)
-.TH LD 1 "March 18, 2006" "Apple Computer, Inc."
-.SH NAME
-ld \- Mach object file link editor
-.SH SYNOPSIS
-.B ld
-[
-.I "option \&..."
-] [
-.I "file \&..."
-]
-.SH DESCRIPTION
+.Dd December 8, 2006
+.Dt ld 1
+.Os Darwin
+.Sh NAME
+.Nm ld
+.Nd "linker"
+.Sh SYNOPSIS
+.Nm
+files... 
+.Op options 
+.Op Fl o Ar outputfile 
+.Sh DESCRIPTION
 The
-.I ld
-command combines several Mach-O (Mach object) files into one by combining like sections
-in like segments from all the object files, resolving external references, and
-searching libraries.  In the simplest case several object
-.I files
-are given, and
-.I ld
-combines them, producing an object file which can either be executed or
-become the input for a further
-.I ld
-run.  (In the latter case, the
-.B \-r
-option must be given to preserve the relocation information.)  Unless an output
-file is specified,
-.I ld
-produces a file named
-.BR a.out .
-This file is made executable only if no errors occurred during the link editing
-and there are no undefined symbols.
-.SH "UNIVERSAL FILE SUPPORT"
-The link editor accepts ``universal'' (multiple-architecture) input files, but
-always creates a ``thin'' (single-architecture), standard Mach-O output file.
-The architecture is specified using the
-.B \-arch
-.I " arch_type"
-option.  If this option is not used,
-.IR ld (1)
-attempts to determine the output architecture by examining the first object
-file encountered on the command line.  If it is a ``thin''
-file, its architecture determines that of the output file.  If the first input
-file is a ``universal'' file, the ``best'' architecture for the host is used.
-(See the explanation of the
-.B \-arch
-option, below.)
-.PP
-The compiler driver
-.IR cc (1)
-handles creating universal executables by calling
-.IR ld (1)
-multiple times and using
-.IR lipo (1)
-to create a ``universal'' file from the results of the
-.IR ld (1)
-executions.
-.SH "OUTPUT FILE LAYOUT"
-.PP
+.Nm ld
+command combines several object files and libraries, resolves references, and
+produces an ouput file. 
+.Nm ld
+can produce a final linked image (executable, dylib, or bundle), or with the -r
+option, produce another object file.  If the -o option is not used, the output
+file produced is named "a.out".
+.Ss Universal
+The linker accepts universal (multiple-architecture) input files, but
+always creates a "thin" (single-architecture), standard Mach-O output file.
+The architecture for the output file is specified using the -arch option.  
+If this option is not used,
+.Nm ld
+attempts to determine the output architecture by examining the object
+files in command line order.  The first "thin"
+architecture determines that of the output file.  If no input
+object file is a "thin" file, the native 32-bit architecture for the host is used.
+.Pp
+Usually, 
+.Nm ld
+is not used directly.  Instead the 
+.Xr gcc(1)
+compiler driver invokes
+.Nm ld.
+The compiler driver can be passed multiple -arch options and it will create a 
+universal final linked image by invoking 
+.Nm ld
+multiple times and then running
+.Xr lipo(1)
+merge the outputs into a universal file.
+.Ss Layout
 The object files are loaded in the order in which they are specified on the
-command line.  The segments and the
-sections in those segments will appear in the output file in the order they are
-encountered in the object files being linked.  All zero fill sections will appear
-after all non-zero fill sections in their segments.
-.PP
-Sections created from files with the
-.B \-sectcreate
-option will appear in the output file last.  Section names for sections created
-from files are not allowed to overlap with a section name in the same segment
-as a section coming from an object file.  Sections created from files may be in
-a segment which has sections from object files and if so will be loaded at the
-end of the non-zero fill sections for that segment.
-.PP
-If the option
-.B \-seglinkedit
-is specified, the segment it creates is the last segment in the output file.
-.PP
-The address of each segment can be specified with
-.B \-segaddr,
-which takes the segment's name as an argument.
-The address of the first segment can alternatively be specified using
-.B \-seg1addr,
-in which case a segment name is not used.
-Segments that do not have a specified
-address will be assigned addresses in the order in which they appear
-in the output file.  A segment's address will be assigned
-based on the ending address of the previous segment.
-If the address of the
-first segment has not been specified by name,
-its assigned address will be
-the specified (via
-.BR \-seg1addr )
-or default first segment address.
-If neither flag is used to specify the first segment's address, its
-default address is zero
-for all formats except the demand-paged executable format
-.SM (MH_EXECUTE),
-in which case the default first address is the value of the segment alignment.
-.PP
-For demand-paged executable format
-.SM (MH_EXECUTE)
-output files,
-if none of the segments' addresses covers address zero through
-the value of the segment alignment, a segment with no access protection
-will be created to cover those addresses.  This segment, named
-.SM "``_\|_PAGEZERO'',"
-is created so that any attempt to dereference a NULL pointer will cause a
-memory exception.
-.PP
-The entry point of the output file is the beginning of
-the first section in the first segment (unless the
-.B \-e
-option is specified).
-.SH STATIC ARCHIVE LIBRARIES
-.PP
-.I ld
-supports two types of libraries: static archive libraries and dynamic shared
-libraries.  Searching for undefined symbols is performed differently for dynamic
-shared libraries than it is for static archive libraries.  The searching of
-dynamic shared libraries is described later.
-.PP
-When a static archive library is specified as an argument to
-.IR ld ,
-it is searched exactly once, at the
-point it is encountered in the argument list.  Only those members defining an unresolved external
-reference, as defined by the static archive library's table of contents,
-are loaded.  To produce the table of contents, all static archive libraries must be processed by
-.IR ranlib (1).
-.PP
-Generally, a static archive library does not have multiple members that define
-the same symbol.  For these types of libraries, the order of the members is not important, so
-the table of contents can be sorted for faster link editing using the
-.B \-s
-option to
-.IR ranlib (1).
-The first member
-of the static archive library is named
-.SM "``\_\^\_.SYMDEF SORTED'',"
-which is understood to be a sorted table of contents.
-.PP
-If the static archive library does have multiple members that define
-the same symbol, the table of contents that
-.IR ranlib (1)
-produces can't be sorted.  Instead, it follows the order in which the members
-appear in the static archive library.  The link editor searches the table of
-contents iteratively, loading members until no further references are
-satisfied.  In the unsorted case, the first member of the static archive
-library is named
-.SM "``\_\^\_.SYMDEF'',"
-which is understood to be a table of contents in
-the order of the archive members.
-.PP
-Static archive library members can also be loaded in response to
-the
-.B \-ObjC
-and
-.B \-all_load
-flags. See their descriptions below.
-
-.SH DYNAMIC SHARED LIBRARIES
-.PP
-When a dynamic shared library or an object file that was linked against a
-dynamic shared library is specified as an argument to
-.IR ld ,
-that library is placed in the dynamic shared library search list. The order of
-the search list is always the same order the libraries were encountered on the
-command line. When linking -flat_namespace, all dynamic libraries that the
-dynamic libraries are dependent upon are added to the end of the search list.
-.PP
-Once the search list is constructed, the static link editor checks for undefined
-symbols by simulating the way the dynamic linker will search for undefined
-symbols at runtime. For each undefined symbol, the static link editor searches
-each library in the search list until it finds a module that defines the symbol.
-With each undefined symbol, the search starts with the first library in the
-list.  This is different than for static archive libraries, where each library
-is searched exactly once for all undefined symbols.
-.PP
-The static link editor simulates dynamic linking as if all the undefined
-symbols are to be bound at program launch time. The dynamic linker actually
-binds undefined symbols as they are encountered during execution instead of at
-program launch. However, the static link editor always produces the same linking
-as the dynamic linker as long as none of the dynamic shared libraries define the
-same symbol. Different linking can occur only when there is more than one
-definition of a symbol and the library modules that contain the definitions for
-that symbol do not define and reference exactly the same symbols.  In this case,
-even different executions of the same program can produce different linking
-because the dynamic linker binds undefined functions as they are called, and
-this affects the order in which undefined symbols are bound.  Because it can
-produce different dynamic linking, using dynamic shared libraries that define
-the same symbols in the same program is strongly discouraged.
-.PP
-If a static archive library appears after a dynamic shared library on the
-command line, the static library is placed in the dynamic library search list
-and is searched as a dynamic library.  In this way, when a dynamic library has
-undefined symbols, it will cause the appropriate members of the static libraries
-to be loaded into the output.  Searching static libraries as dynamic libraries
-can cause problems if the dynamic library later changes to reference symbols
-from the static library that it did not previously reference. In this case when
-the program runs, the dynamic linker will report these symbols as undefined
-because the members for these symbols were not loaded into the output.
-
-.SH TWO-LEVEL AND FLAT NAMESPACES
-.PP
-Two-level and flat namespaces refer to how references to symbols in dynamic
-libraries are resolved to a definition in specific dynamic library.  For
-two-level namespace that resolution is done at static link time when each
-image (program, bundle and shared library) is built.  When a program is using
-images built with two-level namespace there may be different global symbols
-with the same name being used by different images in the program (this is now
-the default).  When a program is using all flat namespace images then only one
-global symbol for each global symbol name is used by all images of the program
-(this was the default in MacOS X 10.0).
-.PP
-When creating an output file with the static link editor that links against
-dynamic libraries, the references to symbols in those libraries can be recorded
-at static link time to bind to a specific library definition (two-level
-namespace) or left to be bound at execution time to the first library in the
-search order of the program (flat namespace).  A program, its dynamic libraries
-and its bundles may each be either two-level or flat namespace images.  The
-dynamic linker will bind each image according to how it was built.
-.PP
-When creating an output file with the static link editor when
-.B \-twolevel_namespace
-is in effect (now the default) all undefined references must be satisfied at
-static link time.  The flags to allow undefined references,
-.BI \-U symbol_name,
-.BI \-undefined " warning"
-and
-.BI \-undefined " suppress"
-can't be used.
-When the environment variable
-.B MACOSX_DEPLOYMENT_TARGET
-is set to
-.B 10.3
-or higher then
-.BI \-undefined " dynamic_lookup"
-can also be used.  The specific library definition recorded
-for each reference is the first library that has a definition as listed on the
-link line.  Listing an umbrella framework implies all of its sub-frameworks,
-sub-umbrellas and sub-libraries.  For any reference to a definition found in
-an umbrella framework's sub-framework, sub-umbrella or sub-library will be
-recorded as coming from the umbrella framework.  Then at execution time the
-dynamic linker will search that umbrella framework's sub-frameworks,
-sub-umbrellas and sub-libraries for those references.
-Also when two-level namespace is in effect only those frameworks listed on the
-link line (and sub-frameworks, sub-umbrellas and sub-libraries of umbrella
-frameworks) are searched.  Other dependent libraries which are not
-sub-frameworks, sub-umbrellas or sub-libraries of umbrella frameworks are not
-searched.
-.RS
-.PP
-When creating bundles (MH_BUNDLE outputs) with the static link editor when
-two-level namespace is in effect (now the default) and the bundle has
-references to symbols
-expected to be defined in the program loading the bundle, then the
-.BI \-bundle_loader " executable"
-must be used.
-.PP
-When creating a output file with the static link editor when
-.B \-flat_namespace
-is in effect (the MacOS X 10.0 default) all undefined references must be
-satisfied at static link time when
-.BI \-undefined " error"
-(the default) is used.  The static
-link editor checks the undefined references by searching all the libraries
-listed on the link line then all dependent libraries.  The undefined symbols
-in the created output file are left to be resolved at execution time by the
-dynamic link editor in the dynamic libraries in the search order of the program.
-
-.SH MULTIPLY DEFINED SYMBOLS
-.PP
-If there are multiply defined symbols in the object files being linked into
-the output file being created this always results in a multiply defined
-symbol error.
-.PP
-When the static link editor links symbols in from a dynamic library that result
-in multiply defined symbols the handling depends on the type of name space of
-output file being created and possibly the type of name space of the dynamic
-library.
-.PP
-When the static link editor is creating a two-level namespace image and a
-there is a multiply defined symbol from dynamic library then that generates a
-multiply defined symbol warning (by default), where the treatment of this
-warning can be changed with the
-.B \-multiply_defined
-flag.
-.PP
-When the static link editor is creating a flat namespace image and a there is
-a multiply defined symbol from dynamic library, if the library is a flat
-namespace image then that generates a multiply defined symbol error.  If the
-library is a two-level namespace image then that generates a multiply defined
-symbol warning (by default), where the treatment of this warning can be changed
-with the
-.B \-multiply_defined
-flag.
-
-.SH "USING THE DYNAMIC LINK EDITOR AND DYNAMIC SHARED LIBRARIES"
-.PP
-The option
-.B \-dynamic
-must be specified in order to use dynamic shared libraries (and any of the features used to implement them) and/or the dynamic link editor.
-To make sure that the output is not using any features that would
-require the dynamic link editor, the flag
-.B \-static
-can be specified.
-Only one of these flags can be specified.
-
-.SH "LINK EDITOR DEFINED SYMBOLS"
-.PP
-There is a group of link editor defined symbols for the
-.SM MH_EXECUTE,
-.SM MH_DYLIB
-and
-.SM MH_PRELOAD
-file types (see the header file <mach-o/ldsyms.h>).  Link editor symbols are
-reserved; it is an error if an input object file defines such a symbol.
-Only those link editor symbols that are referenced by the object file
-appear in the output file's symbol table.
-.PP
-The link editor defined symbol `\_\^\_mh_execute_header'
-(`\_mh_execute_header' in C) is reserved when the output file format is
-.SM MH_EXECUTE.
-This symbol is the address of the Mach header in a Mach-O executable (a
-file of type
-.SM MH_EXECUTE).
-It does not appear in
-any other Mach-O file type.  It can be used to get to the addresses and
-sizes of all the segments and sections in the executable.  This can be done by parsing the headers
-and load commands (see
-.IR Mach-O (5)).
-.PP
-The link editor defined symbol `\_\^\_mh_dylib_header'
-(`\_mh_dylib_header' in C) is reserved when the output file format is
-.SM MH_DYLIB.
-This symbol is the address of the Mach header in a Mach-O dynamic shared library
-(a file of type
-.SM MH_DYLIB)
-and is a private external symbol.
-It does not appear in
-any other Mach-O file type.  It can be used to get to the addresses and
-sizes of all the segments and sections in a dynamic shared library.  The
-addresses, however, must have the value
-.IR _dyld_get_image_vmaddr_slide (3)
-added to them.
-.PP
-The
-.SM MH_PRELOAD
-file type has link editor defined symbols for the
-beginning and ending of each segment, and for the
-beginning and ending of each section within a segment.
-These names are provided for use in a Mach-O preloaded file,
-since it does not have its headers loaded as part of the first segment.
-The names of the symbols for a segment's beginning and end
-have the form: \_\^\_SEGNAME\_\^\_begin and \_\^\_SEGNAME\_\^\_end,
-where \_\^\_SEGNAME is the name of the segment.  Similarly, the symbols for
-a section have the form:
-\_\^\_SEGNAME\_\^\_sectname\_\^\_begin and \_\^\_SEGNAME\_\^\_sectname\_\^\_end,
-where \_\^\_sectname is the name of the section in the segment \_\^\_SEGNAME.
-These symbols' types are those of the section that the names refer to.
-(A symbol that refers to the end of a section actually has, as its value, the beginning address of the next section, but the symbol's type is still that of the section mentioned in the symbol's name.)
-.SH OPTIONS
-.PP
-.I Ld
-understands several options.  Filenames and
-options that refer to libraries (such as
-.B \-l
-and
-.BR \-framework ),
-as well as options that create symbols (such as
-.B \-u
-and
-.BR \-i ),
-are position-dependent: They define the load order and affect what gets
-loaded from libraries.
-Some
-.I ld
-options overlap with compiler options.  If the compiler driver
-.IR cc (1)
-is used to invoke
-.I ld ,
-it maybe necessary to pass the
-.IR ld (1)
-options to
-.IR cc (1)
-using
-.BR \-Wl,\-option,argument1,argument2 .
-
-In this release of the static link editor, 64-bit code (-arch ppc64) are processed by a separate
-tool /usr/bin/ld64.  Not all of the ld command line options are recognized by this tool.
-The options not currently support for building 64-bit binaries are flagged
-.BR "(32-bit only)" .
-
-The most common option is:
-.TP
-.BI  \-o " name"
-The output file is named
-.IR name ,
-instead of
-.BR a.out .
-
-.PP
-The following flags are related to architectures:
-.TP
-.BI \-arch " arch_type"
-Specifies the architecture,
-.I arch_type,
-for the output file. ``Universal'' input files that do not contain this
-specified architecture are ignored.  Only one
-.BI \-arch " arch_type"
-can be specified.  See
-.IR arch (3)
-for the currently known
-.IR arch_type s.
-If
-.I " arch_type"
-specifies a certain implementation of an architecture (such as
-.BI \-arch " m68040"
-or
-.BI \-arch " i486"
-), the resulting object file has that specific CPU subtype, and it is an
-error if any input file has a CPU subtype that will not combine to the CPU subtype
-for
-.IR " arch_type" .
-.IP
-The default output file architecture is determined by the first object file to
-be linked.  If it is a ``thin'' (standard Mach-O) file, or a ``universal'' file
-that contains only one architecture, the output file will have the same
-architecture.  Otherwise, if it is a ``universal'' file
-containing an architecture that would execute on the host, then the ``best''
-architecture is used, as defined by what the kernel exec(2) would select.
-Otherwise, it is an error, and a
-.BI \-arch " arch_type"
-must be specified.
-.TP
-.B \-arch_multiple
-This flag is used by the
-.IR cc (1)
-driver program when it is run with multiple
-.BI \-arch " arch_type"
-flags.  It instructs programs like
-.IR ld (1)
-to precede any displayed message with a line stating
-the program name, in this case
-.IR ld ,
-and the architecture (from the
-.BI \-arch " arch_type"
-flag).  This helps distinguish which architecture the error messages refer to.
-.TP
-.B \-force_cpusubtype_ALL
-The
-.B \-force_cpusubtype_ALL
-flag causes the CPU subtype to remain the
-.SM ALL
-CPU subtype and not to be combined or
-changed.  This flag has precedence over any
-.BI \-arch " arch_type"
-flag for a specific implementation.
-This is the default for all x86 architectures.
-.PP
-The following flags are related to using the dynamic link editor and/or
-dynamic shared libraries (and any of the features used to implement them):
-.TP
-.B \-dynamic
-Allows use of the features associated with dynamic link editor.  The default is
-.B \-dynamic.
-.TP
-.B \-static
-Causes those features associated with dynamic link editor to be treated as
-an error. (The description for the options that will cause an error if you use them in conjunction with
-.B \-static
-are marked with the statement "when
-.B \-dynamic
- is used").
-.TP
-.BI \-read_only_relocs " treatment"
-Specifies how relocation entries in read-only sections are to be treated when
-.B \-dynamic
-is used.
-To get the best possible sharing, the read-only sections should not have any
-relocation entries.
-If they do, the dynamic linker will write on the section.
-Having relocation entries appear in read-only sections is normally avoided by compiling with the option
-.B \-dynamic.
-But in such cases non-converted assembly code
-or objects not compiled with
-.B \-dynamic
-relocation entries will appear in read-only sections.
-The
-.I treatment
-can be:
-.I error,
-.I warning,
-or
-.I suppress.
-Which cause the treatment of relocation entries in read-only sections as either,
-errors, warnings, or suppressed messages.
-The default is to treat these as errors.
-.TP
-.BI \-sect_diff_relocs " treatment"
-Specifies how section difference relocation enries are to be treated when
-.B \-dynamic
-and
-.B \-execute
-are used.
-To get the best possible code generation the compiler should not generate code
-for executables (MH_EXECUTE format outputs) that have any section difference
-relocation entries.  The
-.IR gcc (1)
-compiler has the
-.B \-mdynamic-no-pic
-flag for generating code for executables.  The default treatment is
-.I suppress,
-where no message is printed.  The other treatments are
-.I error
-or
-.I warning.
-This option can also be specified by setting the environment variable
-.SM LD_SECT_DIFF_RELOCS
-to the treatment values.
-.TP
-.BI \-weak_reference_mismatches " treatment"
-Specifies how to treat mismatches of symbol references in the the object files
-being linked. Normally the all the undefined symbol references of the object
-files being linked should be consistent for each undefined symbol.  That is all
-undefined symbols should either be weak or non-weak references. The default
-treatment is
-.I error,
-where the link fails with an error message.  The other treatments are
-.I weak
-or
-.I non-weak,
-which makes mismatched undefined symbol references either weak or non-weak
-in the output, respectively.  Care must be taken when using the treatment
-.I weak
-as the use of the non-weak symbol references in an object file may cause the
-program to crash when the symbol is not present at execution time.
-.TP
-.B \-prebind (32-bit only)
-Have the static linker,
-.IR ld (1),
-prebind an executable's or dynamic shared library's undefined symbols to the
-addresses of the dynamic libraries it is being linked with.
-This optimization can only be done if the libraries don't overlap and
-no symbols are overridden.
-When the resulting program is run and the same libraries are used to run the
-program as when the program was linked, the dynamic linker can use the prebound
-addresses.
-If not, the dynamic linker undoes the prebinding and binds normally.
-This option can also be specified by setting the environment variable
-.SM LD_PREBIND.
-If the environment variable
-.SM LD_FORCE_NO_PREBIND
-is set both the option
-.B \-prebind
-.SM LD_PREBIND
-environment variable are ignore and the output is not prebound.
-Or if the environment variable
-.B MACOSX_DEPLOYMENT_TARGET
-is set to 10.4 or greater and the output is not a split a dynamic library the
-output is not prebound.
-.TP
-.B \-noprebind (32-bit only)
-Do not have the static linker,
-.IR ld (1),
-prebind the output.  If this is specified the environment variable
-.SM LD_PREBIND
-is ignored.
-.TP
-.B \-prebind_allow_overlap (32-bit only)
-Have the static linker,
-.IR ld (1),
-prebind the output even if the addresses of the dynamic libraries it uses
-overlap.  The resulting output can then have
-.IR redo_prebinding (1)
-run on it to fix up the prebinding after the overlapping dynamic libraries
-have been rebuilt.  This option can also be specified by setting the
-environment variable
-.SM LD_PREBIND_ALLOW_OVERLAP.
-.TP
-.B \-prebind_all_twolevel_modules (32-bit only)
-Have the static linker,
-.IR ld (1),
-mark all modules from prebound two-level namespace dynamic libraries as used
-by the program even if they are not statically referenced.  This can provide
-improved launch time for programs like Objective-C programs that use symbols
-indirectly through NIB files. This option can also be specified by setting the
-environment variable
-.SM LD_PREBIND_ALL_TWOLEVEL_MODULES.
-.TP
-.B \-noprebind_all_twolevel_modules (32-bit only)
-Don't have the static linker,
-.IR ld (1),
-mark all modules from prebound two-level namespace dynamic libraries as used
-by the program.  This flag overrides the setting of the
-environment variable
-.SM LD_PREBIND_ALL_TWOLEVEL_MODULES.
-.TP
-.B \-nofixprebinding (32-bit only)
-Have the static linker,
-.IR ld (1),
-mark the executable so that the dynamic linker will never notify the prebinding
-agent if this launched and its prebinding is out of date.  This is used when
-building the prebinding agent itself.
-.PP
-The following flags are related to libraries:
-.TP
-.BI \-l x
-This
-option is an abbreviation for the library name
-.RI `lib x .a',
-where
-.I x
-is a string.
-If
-.B \-dynamic
-is specified the abbreviation for the library name is first search as
-.RI `lib x .dylib'
-and then
-.RI `lib x .a'
-is searched for.
-.I ld
-searches for libraries first in any directories
-specified with
-.B \-L
-options, then in any directories specified in the colon separated set of paths
-in the environment variable LD_LIBRARY_PATH, then the standard directories 
-.BR /lib , 
-.BR /usr/lib , 
-and
-.BR "/usr/local/lib" .
-A library is searched when its name is encountered,
-so the placement of the
-.B  \-l
-flag is significant.  If string
-.I x
-is of the form
-.IR x .o,
-then that file is searched for in the same places, but without prepending
-`lib' or appending `.a' or `.dylib' to the filename.
-.TP
-.BI \-weak-l x
-This is the same as the
-.BI \-l x
-but forces the library and all references to it to be marked as weak imports.
-Care must be taken when using this as the use of the non-weak symbol references
-in an object file may cause the program to crash when the symbol or library is
-not present at execution time.
-.TP
-.BI \-weak_library " file_name_path_to_library"
-This is the same as listing a file name path to a library on the link line
-except that it forces the library and all references to it to be marked as
-weak imports.
-Care must be taken when using this as the use of the non-weak symbol references
-in an object file may cause the program to crash when the symbol or library is
-not present at execution time.
-.TP
-.BI \-L dir
-Add
-.I dir
-to the list of directories in which to search for libraries.
-Directories specified with
-.B \-L
-are searched before the standard directories.
-.TP
-.B \-Z
-Do not search the standard directories when searching for libraries.
-.TP
-.BI "\-syslibroot " rootdir " (32-bit only)"
-Prepend
-.I rootdir
-to the standard directories when searching for libraries or frameworks.
-.TP
-.B \-search_paths_first
-By default when the
-.B \-dynamic
-flag is in effect, the
-.BI \-l x
-and
-.BI \-weak-l x
-options first search for a file of the form
-.RI `lib x .dylib'
-in each directory in the library search path, then a file of the form
-.RI `lib x .a'
-is searched for in the library search paths.
-This option changes it so that in each path
-.RI `lib x .dylib'
-is searched for then
-.RI `lib x .a'
-before the next path in the library search path is searched.
-.TP
-.BI "\-framework " name[,suffix]
-Specifies a framework to link against. Frameworks are dynamic shared libraries,
-but they are stored in different locations, and therefore must be searched for
-differently. When this option is specified,
-.I ld
-searches for framework `\fIname\fR.framework/\fIname\fR'
-first in any directories
-specified with the
-.B \-F
-option, then in the standard framework directories
-.BR /Library/Frameworks ,
-.BR /Network/Library/Frameworks ,
-and
-.BR "/System/Library/Frameworks" .
-The placement of the
-.B \-framework
-option is significant, as it determines when and how the framework is searched.
-If the optional suffix is specified the framework is first searched for the
-name with the suffix and then without.
-.TP
-.BI "\-weak_framework " name[,suffix]
-This is the same as the
-.BI "\-framework " name[,suffix]
-but forces the framework and all references to it to be marked as weak imports.
-Care must be taken when using this as the use of the non-weak symbol references
-in an object file may cause the program to crash when the symbol or framework is
-not present at execution time.
-.TP
-.BI \-F dir
-Add
-.I dir
-to the list of directories in which to search for frameworks.
-Directories specified with
-.B \-F
-are searched before the standard framework directories.
-.TP
-.B \-ObjC
-Loads all members of static archive libraries that define an Objective C class or a category. This option does not apply to dynamic shared libraries.
-.TP
-.B \-all_load
+command line.  The segments and the sections in those segments will appear in 
+the output file in the order they are encountered in the object files being linked. 
+All zero fill sections will appear after all non-zero fill sections in their segments.
+Sections created from files with the -sectcreate option will be laid out at after 
+sections from .o files. The use of the -order_file option will alter the layout 
+rules above, and move the symbols specified to start of their section.
+.Ss Libraries
+A static library (aka static archive) is a collection of .o files with a table of contents
+that lists the global symbols in the .o files. 
+.Nm ld
+will only pull .o files out of a static library if needed to resolve some symbol reference.
+Unlike traditional linkers, 
+.Nm ld
+will continually search a static library while linking. There is no need to specify a static
+library multiple times on the command line.  
+.Pp
+A dynamic library (aka dylib or framework) is a final linked image.  Putting a dynamic
+library on the command line causes two things: 1) The generated final linked image 
+will have encoded that it depends on that dynamic library. 2) Exported symbols from the
+dynamic library are used to resolve references.  
+.Pp
+Both dynamic and static libraries are searched as they appear on the command line.  
+.Ss Search paths
+.Nm ld
+maintains a list of directories to search for a library or framework to use.  The default
+library search path is /usr/lib then /usr/local/lib.  The -L option will add a new library search
+path.  The default framework search path is /Library/Frameworks then /System/Library/Frameworks.
+The -F option will a new framework search path.  The -Z option will remove
+the standard search paths.  The -syslibroot option will prepend a prefix to all search
+paths.
+.Ss Two-level namespace
+By default all references resolved to a dynamic library record the library to which 
+they were resolved. At runtime, dyld uses that information to directly resolve
+symobls.  The alternative is to use the -flat_namespace option.  With flat namespace,
+the library is not recorded.  At runtime, dyld will search each dynamic library in load
+order when resolving symbols. This is slower, but more like how other operating systems 
+resolve symbols. 
+.Ss Indirect dynamic libraries
+If the command line specifies to link against dylib A, and when dylib A was built it linked
+against dylib B, then B is considered an indirect dylib.  
+When linking for two-level namespace, ld does not look at indirect dylibs, except when 
+re-exported by a direct dylibs.  On the other hand when linking for flat namespace, 
+ld does load all indirect dylibs and uses them to resolve references.
+Even though indirect dylibs are specified via a full path, 
+.Nm ld
+first uses the specified search paths to locate each indirect dylib.  If one cannot
+be found using the search paths, the full path is used.
+.Ss Dynamic libraries undefines
+When linking for two-level namespace, 
+.Nm ld 
+does not verify that undefines in dylibs actually
+exist.  But when linking for flat namespace, 
+.Nm ld
+does check that all undefines from all loaded dylibs have a matching definition.  
+This is sometimes used to force selected functions to be loaded from a static library.
+.Sh OPTIONS
+.Ss Options that control the kind of output
+.Bl -tag
+.It Fl execute
+The default.  Produce a mach-o main executable that has file type MH_EXECUTE.
+.It Fl dylib
+Produce a mach-o shared library that has file type MH_DYLIB.
+.It Fl bundle
+Produce a mach-o bundle that has file type MH_BUNDLE.
+.It Fl r
+Merges object files to produce another mach-o object file with file type MH_OBJECT.  
+.It Fl dylinker
+Produce a mach-o dylinker that has file type MH_DYLINKER.  Only used when building dyld.
+.It Fl dynamic
+The default.  Implied by -dynamiclib, -bundle, or -execute
+.It Fl static
+Produces a mach-o file that does not use the dyld.  Only used building the kernel. 
+.It Fl arch Ar arch_name
+Specifies which architecture (e.g. ppc, ppc64, i386, x86_64) the output file should be.
+.It Fl o Ar path
+Specifies the name and location of the output file.  If not specified, `a.out' is used.
+.El
+.Ss Options that control libraries
+.Bl -tag
+.It Fl l Ns x
+This option tells the linker to search for libx.dylib or libx.a in the library search path.
+If string x is of the form y.o, then that file is searched for in the same places, but without
+prepending `lib' or appending `.a' or `.dylib' to the filename.
+.It Fl weak-l Ns Ar x
+This is the same as the -lx but forces the library and all references to it to be marked as weak imports.
+That is, the library is allowed to be missing at runtime.
+.It Fl weak_library Ar path_to_library
+This is the same as listing a file name path to a library on the link line except that it forces the
+library and all references to it to be marked as weak imports. 
+.It Fl reexport-l Ns Ar x
+This is the same as the -lx but specifies that the all symbols in library x should be available to 
+clients linking to the library being created.  This was previously done with a separate -sub_library option.
+.It Fl reexport_library Ar path_to_library
+This is the same as listing a file name path to a library on the link line and it specifies that the 
+all symbols in library path should be available to clients linking to the library being created.
+This was previously done with a separate -sub_library option.
+.It Fl L Ns dir
+Add 
+.Ar dir 
+to the list of directories in which to search for libraries. 
+Directories specified with -L are searched in the order they appear on the command line
+and before the default search path.
+.It Fl Z
+Do not search the standard directories when searching for libraries and frameworks.
+.It Fl syslibroot Ar rootdir
+Prepend 
+.Ar rootdir 
+to all search paths when searching for libraries or frameworks.
+.It Fl search_paths_first
+By default the -lx and -weak-lx options first search for a file of the form `libx.dylib' in each directory
+in the library search path, then a file of the form `libx.a' is searched for in the library search paths.
+This option changes it so that in each path `libx.dylib' is searched for then `libx.a' before the 
+next path in the library search path is searched.
+.It Fl framework Ar name[,suffix]
+This option tells the linker to search for `name.framework/name' the framework search path.
+If the optional suffix is specified the framework is first searched for the name with the suffix and then without
+(e.g. look for `name.framework/name_suffix' first).
+.It Fl weak_framework Ar name[,suffix]
+This is the same as the -framework name[,suffix] but forces the framework and all 
+references to it to be marked as weak imports. 
+.It Fl reexport_framework Ar name[,suffix]
+This is the same as the -framework name[,suffix] but also specifies that the 
+all symbols in that framework should be available to clients linking to the library being created.
+This was previously done with a separate -sub_umbrella option.
+.It Fl F Ns dir
+Add 
+.Ar dir
+to the list of directories in which to search for frameworks. 
+Directories specified with -F are searched in the order they appear on the command line
+and before the default search path.
+.It Fl all_load
 Loads all members of static archive libraries.
-This option does not apply to dynamic shared
-libraries.
-.TP
-.BI \-dylib_file " install_name:file_name" (32-bit only)
-Specifies that a dynamic shared library is in a different location than its standard location. Use this option when you link with a library that is dependent on a dynamic library, and the dynamic library is in a location other than its default location.
-.I install_name
-specifies the path where the library normally resides.
-.I file_name
-specifies the path of the library you want to use instead.
-For example, if you link to a library that depends upon the dynamic library libsys and you have libsys installed in a nondefault location, you would use this option:
-\fB\-dylib_file /lib/libsys_s.A.dylib:/me/lib/libsys_s.A.dylib\fR.
-.TP
-.BI \-executable_path " path_name" (32-bit only)
-Specifies that
-.I path_name
-is used to replace
-.I @executable_path
-for dependent libraries.
-
-.PP
-The following options specify the output file format (the file type):
-.TP
-.B "\-execute"
-Produce a Mach-O demand-paged executable format file.  The headers are placed
-in the first segment, and all segments are padded to the segment alignment.
-This has a file type of
-.SM MH_EXECUTE.
-This is the default.  If no segment address is specified at address zero, a
-segment with no protection (no read, write, or execute permission) is created
-at address zero.
-This segment, whose size is that of the segment
-alignment, is named
-.SM ``_\|_PAGEZERO''.
-This option was previously named
-.BR "\-Mach" ,
-which will continue to be recognized.
-.TP
-.B \-object (32-bit only)
-Produce a Mach-O file in the relocatable object file format that is
-intended for execution.  This differs from using the
-.B \-r
-option in that it defines common symbols, does not allow undefined symbols and
-does not preserve relocation entries.  This has a file type of
-.SM MH_OBJECT.
-In this format all sections are placed in one unnamed segment with all
-protections (read, write, execute) allowed on that segment.  This is intended
-for extremely small programs that would otherwise be large due to segment
-padding.  In this format, and all
-.SM non-MH_EXECUTE
-formats, the link editor
-defined symbol ``\_\^\_mh_execute_header'' is not defined since the headers are
-not part of the segment.  This format file can't be used with the dynamic
-linker.
-.TP
-.B \-preload (32-bit only)
-Produce a Mach-O preloaded executable format file.  The headers are not placed
-in any segment.  All sections are placed in their proper segments and they are
-padded to the segment alignment.  This has a file type of
-.SM MH_PRELOAD.
-This option was previously
-.BR "\-p" ,
-which will continue to be recognized.
-.TP
-.B "\-dylib"
-Produce a Mach-O dynamically linked shared library format file.  The headers are
-placed in the first segment.  All sections are placed in their proper segments
-and they are padded to the segment alignment.  This has a file type of
-.SM MH_DYLIB.
-This option is used by
-.IR libtool (1)
-when its
-.B \-dynamic
-option is specified.
-.TP
-.B "\-bundle"
-Produce a Mach-O bundle format file.  The headers are placed in the first
-segment.  All sections are placed in their proper segments
-and they are padded to the segment alignment.  This has a file type of
-.SM MH_BUNDLE.
-.TP
-.B "\-dylinker"
-Produces a Mach-O dynamic link editor format file.  The headers are placed in the
-first segment.  All sections are placed in their proper segments, and they are
-padded to the segment alignment.  This has a file type of
-.SM MH_DYLINKER.
-.TP
-.B \-fvmlib (32-bit only)
-Produce a Mach-O fixed VM shared library format file.  The headers are placed
-in the first segment but the first section in that segment will be placed on
-the next segment alignment boundary in that segment.  All sections are placed
-in their proper segments and they are padded to the segment alignment.
-This has a file type of
-.SM MH_FVMLIB.
-
-.PP
-The following flags affect the contents of the output file:
-.TP
-.B  \-r
-Save the relocation information in the output file
-so that it can be the subject of another
-.I ld
-run.  The resulting file type is a Mach-O relocatable file
-.SM (MH_OBJECT)
-if not otherwise specified.
-This flag also prevents final definitions from being
-given to common symbols,
-and suppresses the `undefined symbol' diagnostics.
-.TP
-.B  \-d (32-bit only)
-Force definition of common storage even if the
-.B \-r
-option is present.  This option also forces link editor defined symbols to be defined.
-This option is assumed when there is a dynamic link editor load command in the input
-and
-.B \-r
-is not specified.
-
-.PP
-The following flags support segment specifications:
-.TP
-.BI "\-segalign" " value" " (32-bit only)"
-Specifies the segment alignment.
-.I value
-is a hexadecimal number that must be an integral power of 2.
-The default is the target pagesize (currently 1000 hex for the PowerPC and
-i386).
-.TP
-.BI "\-seg1addr" " addr"
-Specifies the starting address of the first segment in the output file.
-.I addr
-is a hexadecimal number and must be a multiple of the segment alignment.
-This option can also be specified as
-.B "\-image_base."
-.TP
-.BI "\-segaddr" " name addr" " (32-bit only)"
-Specifies the starting address of the segment named
-.I name
-to be
-.I addr.
-The address must be a hexadecimal number that is a multiple of the segment alignment.
-.TP
-.BI "\-segs_read_only_addr" " addr" " (32-bit only)"
-Specifies the starting address of the read-only segments in a dynamic shared
-library.  When this option is used the dynamic shared library is built such
-that the read-only and read-write segments are split into separate address
-ranges.  By default the read-write segments are 256meg (0x10000000) after
-the read-only segments.
-.I addr
-is a hexadecimal number and must be a multiple of the segment alignment.
-.TP
-.BI "\-segs_read_write_addr" " addr" " (32-bit only)"
-Specifies the starting address of the read-write segments in a dynamic shared
-library.  When this option is used the
-.B \-segs_read_only_addr
-must also be used (see above).
-.I addr
-is a hexadecimal number and must be a multiple of the segment alignment.
-.TP
-.BI "\-seg_addr_table" " filename" " (32-bit only)"
-For dynamic shared libraries the
-.B "\-seg1addr"
-or the pair of
-.B "\-segs_read_only_addr"
-and
-.B "\-segs_read_write_addr"
-are specified by an entry in the segment address table in
-.I filename
-that matches the install name of the library.
-The entries in the table are lines containing either a single hex address and an
-install name or two hex addresses and an install name.  In the first form the
-single hex address is used as the
-.B "\-seg1addr".
-In the second form the first address is used as the
-.B "\-segs_read_only_addr"
-address and the second address is used as the
-.B "\-segs_read_write_addr"
-address.
-This option can also be specified by setting the environment variable
-.SM LD_SEG_ADDR_TABLE.
-If the environment variable is set then any
-.BR "\-seg1addr" ,
-.BR "\-segs_read_only_addr" ,
-.B "\-segs_read_write_addr"
-and
-.B "\-seg_addr_table"
-options are ignored and a warning is printed.
-.TP
-.BI "\-seg_addr_table_filename" " pathname" " (32-bit only)"
-Use
-.B pathname
-instead of the install name of the library for matching an entry in the segment
-address table.
-.TP
-.BI "\-segprot" " name max init" " (32-bit only)"
-Specifies the maximum and initial virtual memory protection of the named
-segment,
-.I name,
-to be
-.I max
-and
-.I init
-,respectively.  The values for
-.I max
-and
-.I init
-are any combination of the characters `r' (for read), `w' (for write),
-`x' (for execute) and '\-' (no access).  The default is `rwx' for the maximum
-protection for all segments for PowerPC architecures and `rw` for the all Intel
-architecures.
-The default for the initial protection for all segments is `rw' unless the
-segment contains a section which contains some machine instructions, in which
-case the default for the initial protection is `rwx' (and for Intel
-architecures it also sets the maximum protection to `rwx' in this case).
-The default for the initial protection for the
-.SM "``_\|_TEXT''"
-segment is `rx' (not writable).
-.TP
-.B \-seglinkedit (32-bit only)
-Create the link edit segment, named
-.SM "``_\|_LINKEDIT''"
-(this is the default).
-This segment contains all the link edit information (relocation information,
-symbol table, string table, etc.) in the object file.  If the segment protection
-for this segment is not specified, the initial protection is not writable.
-This can only be specified when the output file type is not
-.SM MH_OBJECT
-and
-.SM MH_PRELOAD
-output file types.  To get at the contents of this section, the Mach header
-and load commands must be parsed from the link editor defined symbols like
-`\_\^\_mh_execute_header' (see
-.IR Mach-O (5)).
-.TP
-.B \-noseglinkedit (32-bit only)
-Do not create the link edit segment (see
-.B \-seglinkedit
-above).
-.TP
-.BI "\-pagezero_size" " value"
-Specifies the segment size of _\|_PAGEZERO to be of size
-.IR value ,
-where
-.I value
-is a hexadecimal number rounded to the segment alignment.
-The default is the target pagesize (currently, 1000 hexadecimal for the PowerPC
-and for i386).
-.TP
-.BI "\-stack_addr" " value"
-Specifies the initial address of the stack pointer
-.IR value ,
-where
-.I value
-is a hexadecimal number rounded to the segment alignment.
-The default segment alignment is the target pagesize (currently, 1000
-hexadecimal for the PowerPC and for i386).
-If
-.B \-stack_size
-is specified and
-.B \-stack_addr
-is not, a default stack address specific for the architecture being linked will
-be used and its value printed as a warning message.
-This creates a segment named _\|_UNIXSTACK.  Note that the initial stack address
-will be either at the high address of the segment or the low address of the
-segment depending on which direction the stack grows for the architecture being
-linked.
-.TP
-.BI "\-stack_size" " value"
-Specifies the size of the stack segment
-.IR value ,
-where
-.I value
-is a hexadecimal number rounded to the segment alignment.
-The default segment alignment is the target pagesize (currently, 1000
-hexadecimal for the PowerPC and for i386).
-If
-.B \-stack_addr
-is specified and
-.B \-stack_size
-is not, a default stack size specific for the architecture being linked will be
-used and its value printed as a warning message.
-This creates a segment named _\|_UNIXSTACK .
-.TP
-.B \-allow_stack_execute
-Marks executable so that all stacks in the task will be given stack execution
-privilege.  This includes pthread stacks.
-
-.PP
-The following flags support section specifications:
-.TP
-.BI "\-sectcreate" " segname sectname file"
-The section
-.I sectname
-in the segment
-.I segname
-is created from the contents of
-.I file.
-The combination of
-.I segname
-and
-.I sectname
-must be unique; there cannot already be a section
-.I (segname,sectname)
-in any input object file.
-This option was previously called
-.BR "\-segcreate" ,
-which will continue to be recognized.
-.TP
-.BI "\-sectalign" " segname sectname value"
-The section named
-.I sectname
-in the segment
-.I segname
-will have its alignment set to
-.IR value ,
-where
-.I value
-is a hexadecimal number that must be an integral power of 2.
-This can be used to set the alignment of a section created from a file, or to
-increase the alignment of a section from an object file, or to set the maximum
-alignment of the
-.SM (_\|_DATA,_\|_common)
-section, where common symbols are defined
-by the link editor.  Setting the alignment of a literal section causes the
-individual literals to be aligned on that boundary.  If the section
-alignment is not specified by a section header in an object file or on the
-command line, it defaults to 10 (hex), indicating 16-byte alignment.
-.TP
-.BI "\-sectorder" " segname sectname orderfile" (32-bit only)
-The section
-.I sectname
-in the segment
-.I segname
-of the input files will be broken up into blocks associated with
-symbols in the section.  The output section will be created by ordering
-the blocks as specified by the lines in the
-.I orderfile.
-These blocks are aligned to the output file's section alignment for this
-section.  Any section can be ordered in the output file except symbol pointer and symbol stub sections.
-.IP
-For non-literal sections, each line of the
-.I orderfile
-contains an object name and a symbol name, separated by a single colon (':').
-Lines that start with # are ignored and treated as comments.
-If the object file is
-in an archive, the archive name, followed by a single colon, must precede the
-object file name.  The object file names and archive names should be exactly the
-names as seen by the link editor, but if not, the link editor attempts to match
-up the names the best it can.
-For non-literal sections, the easiest way to generate an order file is
-with the ``\f3\-jonls +\f2segname sectname\f1'' options to
-.IR nm (1).
-.IP
-The format of the
-.I orderfile
-for literal sections is specific to each type of literal section.  For C
-string literal sections, each line of the order file contains one literal C
-string, which may include ANSI C escape sequences.  For four-byte literal
-sections, the order file format is one 32-bit hex number with a leading 0x
-per
-line, with the rest of the line treated as a comment.  For eight-byte literal
-sections, the order file has two 32-bit hex numbers per line; each number
-has a leading 0x, the two numbers are separated by white
-space, and the rest of the line is treated as a comment.
-For literal pointer sections, the lines in the order file represent
-pointers, one per line.  A literal pointer is represented by the name of
-the segment that contains the literal being pointed to, followed by the
-section name, followed by the literal. These three strings are separated
-by colons with no extra white space.
-For all the literal sections, each line in the the order file is simply entered
-into the literal section and will appear in the output file in the same order
-as in the
-order file.  There is no check to see whether the literal is present
-in the loaded objects.
-For literal sections, the easiest way to generate an order file is with
-the ``\f3\-X \-v \-s \f2segname sectname\f1'' options to
-.IR otool (1).
-.TP
-.B \-sectorder_detail (32-bit only)
-When using the
-.B \-sectorder
-option,  any pairs of object file names and symbol names that are found in
-the loaded objects, but not specified in the
-.IR orderfile ,
-are placed last in the output file's section.   These pairs are ordered by
-object file (as the filenames appear
-on the command line), with the different symbols from a given object
-file being ordered by
-increasing symbol address (that is, the order
-in which the symbols occurred in the object file,
-not their order in the symbol table).  By default, the link editor displays a summary
-that simply shows the number
-of symbol names found in the loaded objects but not in the
-.IR orderfile ,
-as well as the number of symbol names listed in the
-.I orderfile
-but not found in the loaded objects.  (The summary is omitted if both values
-are zero.)  To instead produce a detailed list of these symbols, use the
-.B \-sectorder_detail
-flag.  If an object file-symbol name pair is listed multiple times, a
-warning is generated, and the first occurrence is used.
-.TP
-.BI "\-sectobjectsymbols" " segname sectname" " (32-bit only)"
-This causes the link editor to generate local symbols in the section
-.I sectname
-in the segment
-.IR segname .
-Each object file that has one of these sections will have a local
-symbol created
-whose name is that of the object file, or of the member of the archive.
-The symbol's value will be the first address where that object file's section
-was loaded.  The symbol has the type N_SECT and its section number is the
-the same as that of the section
-.I (segname,sectname)
-in the output file.
-This symbol will be placed in the symbol table just before all other local
-symbols
-for the object file.  This feature is typically used where the section is
-.SM (\_\^\_TEXT,\_\^\_text),
-in order to help the debugger debug object files produced by old versions of
-the compiler or by non-Apple compilers.
-
-.PP
-The following flags are related to name spaces:
-.TP
-.B \-twolevel_namespace
-Specifies the output to be built as a two-level namespace image.
-This option can also be specified by setting the environment variable
-.SM LD_TWOLEVEL_NAMESPACE.
-This is the default.
-.TP
-.B \-flat_namespace
-Specifies the output to be built as a flat namespace image.
-This is not the default (but was the default in MacOS X 10.0).
-.TP
-.B \-force_flat_namespace
-Specifies the executable output to be built and executed treating all its
-dynamic libraries as flat namespace images.  This marks the executable so that
-the dynamic link editor treats all dynamic libraries as flat namespace
-images when the program is executed.
-.TP
-.BI \-bundle_loader " executable" " (32-bit only)"
-This specifies the
-.I executable
-that will be loading the bundle output file being linked.  Undefined symbols
-from the bundle are checked against the specified executable like it was one of
-the dynamic libraries the bundle was linked with.  If the bundle being created
-with
-.B \-twolevel_namespace
-in effect then the searching of the executable for
-symbols is based on the placement of the
-.B \-bundle_loader
-flag relative to the dynamic libraries.  If the the bundle being created with
-.B \-flat_namespace
-then the searching of the executable is done before all dynamic libraries.
-.TP
-.B \-private_bundle (32-bit only)
-This allows symbols defined in the output to also be defined in executable in
-the
-.B \-bundle_loader
-argument
-when
-.B \-flat_namespace
-is in effect.
-This implies that the bundle output file being created is going to be loaded by
-the executable with the
-.B NSLINKMODULE_OPTION_PRIVATE
-option to
-.IR NSLinkModule (3).
-.TP
-.B \-twolevel_namespace_hints (32-bit only)
-Specifies to create the output with the two-level namespace hints table to be
-used by the dynamic linker.  This is the default except when the
-.B \-bundle
-flag is specified.  If this is used when the
-.B \-bundle
-flag is specified the bundle will fail to load on a MacOS X 10.0 system with a
-malformed object error.
-.TP
-.BI \-multiply_defined " treatment" " (32-bit only)"
-Specifies how multiply defined symbols in dynamic libraries when
-.B \-twolevel_namespace
-is in effect are to be treated.
-.I treatment
-can be:
-.I error,
-.I warning,
-or
-.I suppress.
-Which cause the treatment of multiply defined symbols in dynamic libraries
-as either, errors, warnings, or suppresses the checking of multiply symbols
-from dynamic libraries when
-.B \-twolevel_namespace
-is in effect.
-The default is to treat multiply defined symbols in dynamic libraries as
-warnings when
-.B \-twolevel_namespace
-is in effect.
-.TP
-.BI \-multiply_defined_unused " treatment" " (32-bit only)"
-Specifies how unused multiply defined symbols in dynamic libraries when
-.B \-twolevel_namespace
-is in effect are to be treated.
-An unused multiply defined symbol is one in which there is a symbol defined in
-the output that is also defined in the dynamic libraries the output is linked
-with but the symbol in the dynamic library is not used by any reference in the
-output.
-.I treatment
-can be:
-.I error,
-.I warning,
-or
-.I suppress.
-The default for unused multiply defined symbols is to suppress these messages.
-.TP
-.B -nomultidefs (32-bit only)
-specifying this flag marks the umbrella being created such that the dynamic
-linker is guaranteed that no multiple definitions of symbols in the umbrella's
-sub-images will ever exist.  This allows the dynamic linker to always use the
-two-level namespace lookup hints even if the timestamps of the sub-images
-do not match.  This flag implies
-.BI \-multiply_defined " error".
-
-.PP
-The following flags are related to symbols.  These flags' arguments
-are external symbols whose names have `_' prepended to the C,
-.SM FORTRAN,
-or Pascal variable name.
-.TP
-.BI \-y sym " (32-bit only)"
-Display each file in which
-.I sym
-appears, its type, and whether the file defines or references it.  Any
-multiply defined symbols are automatically
-traced.  Like most of the other symbol-related flags,
-.B \-y
-takes only one argument; the flag may be specified more than once in the
-command line to trace more than one symbol.
-.TP
-.BI \-Y " number" " (32-bit only)"
-For the first
-.I number
-undefined symbols, displays each file in which the symbol appears, its type and whether the file defines or references it (that is, the same style of output produced by the
-.B \-y
-option). To keep the output manageable, this option displays at most
-.I number
-references.
-.TP
-.B \-keep_private_externs
-Don't turn private external symbols into static symbols, but rather leave them
-as private external in the resulting output file.
-.TP
-.B \-m (32-bit only)
-Don't treat multiply defined symbols from the linked objects as a hard error;
-instead, simply print a warning.  The first linked object defining such a symbol
-is used for linking; its value is used for the symbol in the symbol table.  The
-code and data for all such symbols are copied into the output.  The duplicate
-symbols other than the first symbol may still end up being used in the resulting
-output file through local references.  This can still produce a resulting output
-file that is in error.  This flag's use is strongly discouraged!
-.TP
-.B \-whyload (32-bit only)
-Indicate why each member of a library is loaded.  In other words, indicate
-which currently undefined symbol is being resolved, causing that
-member to be loaded.  This in combination with the above
-.BI \-y sym
-flag can help determine exactly why a link edit is failing due to multiply
-defined symbols.
-.B
-.TP
-.BI  \-u " sym"
-Enter the argument
-.I sym
-into the symbol table as an undefined symbol.  This is useful
-for loading wholly from a library, since initially the symbol
-table is empty and an unresolved reference is needed
-to force the loading of the first object file.
-.TP
-.BI \-e " sym"
-The argument
-.I sym
-is taken to be the symbol name of the entry point of
-the resulting file.  By default, the entry point is the address of the
-first section in the first segment.
-.TP
-.BI \-i definition:indirect " (32-bit only)"
-Create an indirect symbol for the symbol name
-.I definition
-which is defined to be the same as the symbol name
-.I indirect
-(which is taken to be undefined).  When a definition of the symbol named
-.I indirect
-is linked, both symbols will take on the defined type and value.
-.IP
-This option overlaps with a compiler option.
-If you use the compiler driver
-.IR cc (1)
-to invoke \fIld\fR,
-invoke this option in this way:
-.BI \-Wl,\-i definition:indirect.
-
-.TP
-.BI \-undefined " treatment"
-Specifies how undefined symbols are to be treated.
-.I treatment
-can be:
-.I error,
-.I warning,
-or
-.I suppress.
-Which cause the treatment of undefined symbols as either, errors, warnings, or
-suppresses the checking of undefined symbols.
-The default is to treat undefined symbols as errors.
-When the environment variable
-.B MACOSX_DEPLOYMENT_TARGET
-is set to
-.B 10.3
-or higher then
-.BI \-undefined " dynamic_lookup"
-can also be used to allow any undefined symbols to be looked up dynamically at
-runtime.  Use of a binary built with this flag requires a system with a dynamic
-linker from Mac OS X 10.3 or later.
-The flag
-.BI \-undefined " define_a_way"
-can also be used to cause the static linker to create a private definition for
-all undefined symbols.  This flag should only be used if it is known that the
-undefined symbols are not referenced as any use of them may cause a crash.
-.TP
-.BI  \-U " sym"
-Allow the symbol
-.I sym
-to be undefined, even if the
-.B \-r
-flag is not given.  Produce an executable file if the only undefined
-symbols are those specified with
-.BR \-U.
-.IP
-This option overlaps with a compiler option.
-If you use the compiler driver
-.IR cc (1)
-to invoke \fIld\fR,
-invoke this option in this way:
-.BI \-Wl,\-U, sym.
-.TP
-.B \-bind_at_load
-Causes the output file to be marked such that the dynamic linker will bind all
-undefined references when the file is loaded or launched.
-.TP
-.BI \-commons " treatment" " (64-bit only)"
-Specifies how common symbols (tentative defintions) from object files interact with dynamic libraries.
-.I treatment
-can be:
-.I ignore_dylibs,
-.I use_dylibs,
-or
-.I error.
-The default is ignore_dylibs
-which means the static linker will use a common defintion from an object file even if a true definition
-exisits in a dynamic library.  If you want your code to use a dynamic library definition, then add
-the extern keyword to your tentative definition (e.g. change
-.I int foo;
-to
-.I extern int foo;
-).  The treatment use_dylibs means a definition form a dynamic library should override a common symbol
-in an object file. Note, the 32-bit linker always uses this treatment.
-The treatment error means the linker should abort whenever if finds a common symbol in
-an object file and an external definition with the same name in a dynamic library.
-.TP
-.B \-warn_commons (64-bit only)
-Causes the static linker to write a diagnostic line about how common symbols were processed.  This is
-useful for debugging problems with common symbols.
-
-.PP
-The following flags are related to stripping link edit information.
-This information can also be removed by
-.IR strip (1),
-which uses the same options.  (The
-exception is the
-.B \-s
-flag below, but this is the same as
-.IR strip (1)
-with no arguments.)
-The following flags are listed in decreasing level of stripping.
-.TP
-.B \-s (32-bit only)
-Completely strip the output; that is, remove the symbol table
-and relocation information.
-.TP
-.B \-x (32-bit only)
-Strips the non-global symbols; only saves external symbols.
-.IP
-This option overlaps with a compiler option.
-If you use the compiler driver
-.IR cc (1)
-to invoke \fIld\fR,
-invoke this option in this way:
-.B \-Wl,\-x.
-.TP
-.B \-S (32-bit only)
-Strip debugging symbols; only save local and global symbols.
-.TP
-.B \-X (32-bit only)
-Strip local symbols whose names begin with `L'; save all other symbols.
-(The compiler and assembler currently strip these internally-generated
-labels by default, so they generally do not appear in object files
-seen by the link editor.)
-.TP
-.B \-Sp
-Strip, edit and add debugging symbols so the debugger can used most of the
-debugging symbols from the object files.
-.TP
-.B \-Si (32-bit only)
-Strip duplicate debugging symbols from include files.  This is
-the default.
-.TP
-.B  \-b (32-bit only)
-Strip the base file's symbols from the output file.  (The base file
-is given as the argument to the
-.B \-A
-option.)
-.IP
-This option overlaps with a compiler option.
-If you use the compiler driver
-.IR cc (1)
-to invoke \fIld\fR,
-invoke this option in this way:
-.B \-Wl,\-b.
-.TP
-.B \-Sn (32-bit only)
-Don't strip any symbols.
-.TP
-.BI \-exported_symbols_list " filename"
-The specified
-.I filename
-contains lists of global symbol names that will remain as global symbols in the
-output file.  All other global symbols will be treated as if they were marked as
-.I __private_extern__
-and will not be global in the output file. The symbol names listed in
-.I filename
-must be one per line. Leading and trailing white space are not part of the
-symbol name.  Lines starting with # are ignored, as are lines with only white
-space.
-.TP
-.BI \-unexported_symbols_list " filename"
-The specified
-.I filename
-contains lists of global symbol names that will not remain as global symbols in
-the output file.  The symbols will be treated as if they were marked as
-.I __private_extern__
-and will not be global in the output file. The symbol names listed in
-.I filename
-must be one per line. Leading and trailing white space are not part of the
-symbol name.  Lines starting with # are ignored, as are lines with only white
-space.
-.TP
-.BI \-no_uuid
-Do not emit an LC_UUID load command in the linked output file.
-
-.TP
-.B -dead_strip (32-bit only)
-Remove blocks of code and data that are unreachable by the entry point or
-exported symbols.
-.TP
-.B -no_dead_strip_inits_and_terms (32-bit only)
-When specified along with
-.B -dead_strip
-cause all constructors and destructors to never be dead stripped.
-
-.PP
-The remaining options are infrequently used:
-.TP
-.B \-v
-Print the version of the linker.
-.TP
-.B \-w (32-bit only)
-Suppresses all warning messages.
-.TP
-.B \-no_arch_warnings
-Suppresses warning messages about files that have the wrong architecture for the
-.B \-arch
-flag.
-.TP
-.B \-arch_errors_fatal (32-bit only)
-Cause the errors having to do with files that have the wrong architecture to be
-fatal and stop the link editor.
-.TP
-.B \-M (32-bit only)
-Produce a load map, listing all the segments and sections.  The list
-includes the address where each input file's section appears in the
-output file, as well as the section's size.
-.IP
-This option overlaps with a compiler option.
-If you use the compiler driver
-.IR cc (1)
-to invoke \fIld\fR,
-invoke this option in this way:
-.B \-Wl,\-M.
-.TP
-.B \-whatsloaded (32-bit only)
-Display a single line listing each object file that is
-loaded.  Names of objects in archives have the form libfoo.a(bar.o).
-.TP
-.BI \-filelist " listfile[,dirname]"
-Specifies that the linker should link the files listed in
-.I listfile .
-This is an alternative to listing the files on the command line. The file names are listed one per line separated
-only by newlines. (Spaces and tabs are assumed to be part of the file name.)
-If the optional directory name,
-.I dirname
+.It Fl ObjC
+Loads all members of static archive libraries that implement an Objective-C class or category.
+.El
+.Ss Options that control additional content
+.Bl -tag
+.It Fl sectcreate Ar segname sectname file
+The section 
+.Ar sectname 
+in the segment 
+.Ar segname 
+is created from the contents of file 
+.Ar file. 
+The combination of segname and sectname must be unique Ð there cannot already be a section (segname,sectname) 
+from any other input.
+.It Fl filelist Ar file[,dirname]
+Specifies that the linker should link the files listed in 
+.Ar file . 
+This is an alternative to listing the files on the command line. 
+The file names are listed one per line separated only by newlines. (Spaces and tabs are assumed to be part of the file name.)
+If the optional directory name, 
+.Ar dirname 
 is specified, it is prepended to each name in the list file.
-.TP
-.BI "\-headerpad" " value"
-Specifies the minimum amount of space ("padding") following
-the headers for the
-.SM MH_EXECUTE
-format and all output file types with the dynamic linker.
-.I value
-is a hexadecimal number.
-When a segment's size is rounded up to the segment alignment, there
-is extra space left over, which is placed between the headers and the sections, rather than at the end of the segment.  The
-.B headerpad
-option specifies the minimum size of this padding,
-which can be useful if the headers will be altered later.
-The default value is the larger of 2 * sizeof(struct section) so the program
-/usr/bin/objcunique can always add two section headers, or if the output is an
-MH_EXECUTE filetype and
-.B \-prebind
-is specified 3 times the size of the LC_PREBOUND_DYLIB load commands.
-The actual amount of pad will be as large as the amount of the first
-segment's round-off.
-(That is, take the total size of the first segments'
-headers and non-zerofill sections, round this size
-up to the segment alignment,
-and use the difference between the rounded
-and unrounded sizes as the minimum amount of padding.)
-.TP
-.B \-headerpad_max_install_names (32-bit only)
-Add to the header padding enough space to allow changing all dynamic shared
-library paths recorded in the output file to be changed to MAXPATHLEN in length.
-.TP
-.B \-t
-Trace the progress of the link editor; display the name of each file
-that is
-loaded as it is processed in the first and second pass of the link
-editor.
-.TP
-.BI \-A " basefile" " (32-bit only)"
-Incremental loading: linking is to be done in a manner
-that lets the resulting object be read into an already executing
-program, the
-.IR basefile .
-.I basefile
-is the name of a file whose symbol table will be taken as a basis
-on which to define additional symbols.
-Only newly linked material will be entered into the
-.BR a.out
-file, but the new symbol table will reflect
-every symbol defined in the base file and the newly linked files.
-Option(s) to specify the addresses of the segments are typically
-needed, since
-the default addresses tend to overlap with the
-.I basefile.
-The default format of the object file is
-.SM MH_OBJECT.
-Note: It is strongly recommended that this option NOT be used,
-because the dyld package described in
-.IR dyld (3)
-is a much easier alternative.
-.TP
-.BI \-dylib_install_name " name"
-For dynamic shared library files, specifies the name of the file
-the library will be installed in for programs that use it.  If this is not
-specified, the name specified in the
-.BI \-o " name"
-option will be used.
-This option is used as the
-.IR libtool (1)
-.BI \-install_name " name"
-option when its
-.B \-dynamic
-option is specified.
-.TP
-.BI \-umbrella " framework_name"
-Specifies this is a subframework where
-.I framework_name
-is the name of the umbrella framework this subframework is a part of.  Where
-.I framework_name
-is the same as the argument to the
-.BI \-framework " framework_name"
-option.  This subframework can then only be linked into the umbrella framework
-with the same
-.I framework_name
-or another subframework with the same umbrella framework name.  Any other
-attempt to statically link this subframework directly will result in an error
-stating to link with the umbrella framework instead.  When building the umbrella
-framework that uses this subframework no additional options are required.
-However the install name of the umbrella framework, required to be specified
-with
-.BR \-dylib_install_name ,
-must have the proper format for an install name of a framework for the
-.I framework_name
-of the umbrella framework to be determined.
-.TP
-.BI \-allowable_client " client_name" " (32-bit only)"
-Specifies that for this subframework the
-.I client_name
-can link with this subframework without error even though it is not part of
-the umbrella framework that this subframework is part of.  The
-.I client_name
-can be another framework name or a name used by bundles (see the
-.BI \-client_name " client_name"
-option below).
-.TP
-.BI \-client_name " client_name" " (32-bit only)"
-Specifies the
-.I client_name
-of a bundle for checking of allowable clients of subframeworks (see the
-.BI \-allowable_client " client_name"
-option above).
-.TP
-.BI \-sub_umbrella " framework_name"
-Specifies that the
-.I framework_name
-being linked by a dynamic library is to be treated as one of the
-subframeworks with respect to twolevel namespace.
-.TP
-.BI \-sub_library " library_name"
-Specifies that the
-.I library_name
-being linked by a dynamic library is to be treated as one of the
-sublibraries with respect to twolevel namespace.  For example the
-.I library_name
-for
-.I /usr/lib/libobjc_profile.A.dylib
-would be
-.I libobjc.
-.TP
-.BI \-init " sym"
+.It Fl dtrace Ar file
+Enables dtrace static probes when producing a final linked image.  The file 
+.Ar file
+must be a DTrace script which declares the static probes.
+.El
+.Ss Options that control optimizations
+.Bl -tag
+.It Fl dead_strip
+Remove functions and data that are unreachable by the entry point or exported symbols.  
+.It Fl dead_strip_dylibs
+Remove dylibs that are unreachable by the entry point or exported symbols. That is,  
+suppresses the generation of load command commands for dylibs which supplied no
+symbols during the link. This option should not be used when linking against a dylib which 
+is required at runtime for some indirect reason such as the dylib has an important initializer.
+.It Fl order_file Ar file
+Alters the order in which functions and data are laid out.  For each section in the output file,
+any symbol in that section that are specified in the order file 
+.Ar file
+is moved to the start of its section and laid out in the same order as in the order file 
+.Ar file .
+Order files are text files with one symbol name per line.  Lines starting with a # are comments.
+A symbol name may be optionally preceded with its object file leafname and a colon (e.g. foo.o:_foo). 
+This is useful for static functions/data that occur in multiple files. 
+A symbol name may also be optionally preceded with the architecture (e.g. ppc:_foo or ppc:foo.o:_foo).
+This enables you to have one order file that works for multiple architectures. 
+Literal c-strings may be ordered by by quoting the string (e.g. "Hello, world\\n") in the order file.
+.It Fl macosx_version_min Ar version
+This is set to indicate the oldest Mac OS X version that that the output is to be used on.  Specifying
+a later version enables the linker to assumes features of that OS in the output file.  The format of
+.Ar version
+is a Mac OS X version number such as 10.4 or 10.5
+.It Fl image_base Ar address
+Specifies the perferred load address for a dylib or bundle. The argument
+.Ar address
+is a hexadecimal number with an optional leading 0x.  By choosing non-overlapping address for all
+dylibs and bundles that a program loads, launch time can be improved because dyld will not need to
+"rebase" the image (that is, adjust pointers within the image to work at the loaded address).
+It is often easier to not use this option, but instead use the rebase(1) tool, and give it a list of dylibs.  
+It will then choose non-overlapping addresses for the list and rebase them all.
+This option is also called -seg1addr for compatibility.
+.El
+.Ss Options when creating a dynamic library (dylib)
+.Bl -tag
+.It Fl install_name Ar name
+Sets an internal "install path" (LC_ID_DYLIB) in a dynamic library. Any clients linked against the library 
+will record that path as the way dyld should locate this library.  If this option is not specified, then 
+the -o path will be used.  This option is also called -dylib_install_name for compatibility.
+.It Fl compatibility_version Ar number
+Specifies the compatibility version number of the library.  When a library is loaded by dyld, the 
+compatibility version is checked and if the program's version is greater that the library's version, it is an error.
+The format of 
+.Ar number 
+is X[.Y[.Z]] where X must be a positive non-zero number less than or equal to 65535, 
+and .Y and .Z are optional and if present must be non-negative numbers less than or equal to 255. 
+If the compatibility version number is not specified, it has a value of 0 and no checking is done when the library is used. 
+This option is also called -dylib_compatibility_version for compatibility.
+.It Fl current_version Ar number
+Specifies the current version number of the library. The current version of the library can be obtained 
+programmatically by the user of the library so it can determine exactly which version of the library it is using. 
+The format of 
+.Ar number 
+is X[.Y[.Z]] where X must be a positive non-zero number less than or equal to 65535, 
+and .Y and .Z are optional and if present must be non-negative numbers less than or equal to 255. 
+If the version number is not specified, it has a value of 0.
+This option is also called -dylib_current_version for compatibility.
+.El
+.Ss Options when creating a main executable
+.Bl -tag
+.It Fl pie
+This makes a special kind of main executable that is position independent (PIE).  On Mac OS X 10.5, the OS
+will load a PIE at a random address each time it is executed.  You cannot create a PIE from .o files compiled 
+with -mdynamic-no-pic.  That means the codegen is less optimal, but the address randomization adds some 
+security. 
+.It Fl pagezero_size Ar size
+By default the linker creates an unreadable segment starting at address zero named __PAGEZERO.  Its existence
+will cause a bus error if a NULL pointer is dereferenced.  The argument
+.Ar size
+is a hexadecimal number with an optional leading 0x.  If  
+.Ar size
+is zero, the linker will not generate a page zero segment.  By default on 32-bit architectures the page zero size 
+is 4KB.  On 64-bit architectures, the default size if 4GB.  The ppc64 architecture has some special cases. Since Mac
+OS X 10.4 did not support 4GB page zero programs, the default page zero size for ppc64 will be 4KB unless 
+-macosx_version_min is 10.5 or later.  Also, the -mdynamic-no-pic codegen model for ppc64 will only work if the
+code is placed in the lower 2GB of the address space, so the if the linker detects any such code, the page zero
+size is set to 4KB and then a new unredable trailing segment is created after the code, filling up the lower 4GB.
+.It Fl stack_size Ar size
+Specifies the maximum stack size for the main thread in a program.  Without this option a program has a 8MB stack.
 The argument
-.I sym
-is taken to be the symbol name of the dynamic shared library initialization
-routine.  If any module is used from the dynamic library the library
-initialization routine is called before any symbol is used from the library
-including C++ static initializers (and #pragma CALL_ON_LOAD routines).
-.TP
-.B \-run_init_lazily (32-bit only)
+.Ar size
+is a hexadecimal number with an optional leading 0x. The 
+.Ar size
+should be an even multiple of 4KB, that is the last three hexadecimal digits should be zero.
+.It Fl allow_stack_execute 
+Marks executable so that all stacks in the task will be given stack execution privilege. This includes pthread stacks.
+.El
+.Ss Options when creating a bundle
+.Bl -tag
+.It Fl bundle_loader Ar executable
+This specifies the 
+.Ar executable 
+that will be loading the bundle output file being linked. 
+Undefined symbols from the bundle are checked against the specified 
+.Ar executable 
+like it was one of the 
+dynamic libraries the bundle was linked with.
+.El
+.Ss Options when creating an object file
+.Bl -tag
+.It Fl keep_private_externs
+Don't turn private external (aka visibility=hidden) symbols into static symbols, 
+but rather leave them as private external in the resulting object file.
+.It Fl d
+Force definition of common symbols.  That is, transform tentative defintions into real definitions.
+.El
+.Ss Options that control symbol resolution
+.Bl -tag
+.It Fl exported_symbols_list Ar filename
+The specified 
+.Ar filename 
+contains a list of global symbol names that will remain as global symbols in the output file. 
+All other global symbols will be treated as if they were marked as __private_extern__ (aka visibility=hidden) 
+and will not be global in the output file. The symbol names listed in filename must be one per line.
+Leading and trailing white space are not part of the symbol name. 
+Lines starting with # are ignored, as are lines with only white space.
+Some wildcards (similar to shell file matching) are supported.  The * matches zero or more characters.
+The ? matches one character.  [abc] matches one character which must be an 'a', 'b', or 'c'.  [a-z] matches
+any single lower case letter from 'a' to 'z'. 
+.It Fl exported_symbol Ar symbol
+The specified 
+.Ar symbol
+is added to the list of global symbols names that will remain as global symbols in the output file.  This 
+option can be used multiple times.  For short lists, this can be more convenient than creating a file and using 
+-exported_symbols_list.
+.It Fl unexported_symbols_list Ar file
+The specified 
+.Ar filename 
+contains a list of global symbol names that will not remain as global symbols in the output file. 
+The symbols will be treated as if they were marked as __private_extern__ (aka visibility=hidden) and will not be global
+in the output file. The symbol names listed in filename must be one per line. 
+Leading and trailing white space are not part of the symbol name. 
+Lines starting with # are ignored, as are lines with only white space.
+Some wildcards (similar to shell file matching) are supported.  The * matches zero or more characters.
+The ? matches one character.  [abc] matches one character which must be an 'a', 'b', or 'c'.  [a-z] matches
+any single lower case letter from 'a' to 'z'. 
+.It Fl unexported_symbol Ar symbol
+The specified 
+.Ar symbol
+is added to the list of global symbols names that will not remain as global symbols in the output file.  This 
+option can be used multiple times.  For short lists, this can be more convenient than creating a file and using 
+-unexported_symbols_list.
+.It Fl alias Ar symbol_name Ar alternate_symbol_name
+Create an alias named 
+.Ar alternate_symbol_name
+for the symbol
+.Ar symbol_name .
+By default the alias symbol has global visibility.  This option was previous the -idef:indir option.
+.It Fl alias_list Ar filename
+The specified 
+.Ar filename
+contains a list of aliases. The symbol name and its alias are on one line, separated by whitespace.
+Lines starting with # are ignored.
+.It Fl flat_namespace 
+Alters how symbols are resolved at build time and runtime.  With -two_levelnamespace (the default), the linker
+only searches dylibs on the command line for symbols, and records in which dylib they were found.  With -flat_namespace, 
+the linker searches all dylibs on the command line and all dylibs those original dylibs depend on.  The linker
+does not record which dylib an external symbol came from, so at runtime dyld again searches all images and uses
+the first definition it finds.  In addition, any undefines in loaded flat_namespace dylibs must be resolvable
+at build time.  
+.It Fl u Ar symbol_name
+Specified that symbol 
+.Ar symbol_name
+must be defined for the link to succeed.  This is useful to force selected functions to be loaded
+from a static library.
+.It Fl U Ar symbol_name
+Specified that it is ok for 
+.Ar symbol_name
+to have no definition.  With -two_levelnamespace, the resulting symbol will be marked dynamic_lookup which
+means dyld will search all loaded images.
+.It Fl undefined Ar treatment
+Specifies how undefined symbols are to be treated. Options are: error, warning, suppress, or dynamic_lookup.  The
+default is error. 
+.It Fl rpath Ar path
+Add 
+.Ar path
+to the runpath search path list for image being created.  At runtime, dyld uses the runpath when searching
+for dylibs whose load path begins with @rpath/.
+.El
+.Ss Options for introspecting the linker
+.Bl -tag
+.It Fl why_load
+Log why each object file in a static library is loaded. That is, what symbol was needed.  Also called -whyload
+for compatibility.
+.It Fl why_live Ar symbol_name
+Logs a chain of references to 
+.Ar symbol_name .
+Only applicable with -dead_strip .
+It can help debug why something that you think should be dead strip removed is not removed.
+.It Fl print_statistics
+Logs information about the amount of memory and time the linker used.
+.It Fl t
+Logs each file (object, archive, or dylib) the linker loads.  Useful for debugging problems with search paths where the wrong library is loaded.
+.It Fl whatsloaded
+Logs just object files the linker loads.
+.It Fl order_file_statistics
+Logs information about the processing of a -order_file.
+.It Fl map Ar map_file_path
+Writes a map file to the specified path which details all symbols and their addresses in the output image.
+.El
+.Ss Options for controling symbol table optimizations
+.Bl -tag
+.It Fl S
+Do not put debug information (STABS or DWARF) in the output file.
+.It Fl x
+Do not put non-global symbols in the output file's symbol table. Non-global symbols are useful when debugging and
+getting symbol names in back traces, but are not used at runtime.
+.It Fl non_global_symbols_strip_list Ar filename
+The specified 
+.Ar filename 
+contains a list of non-global symbol names that should be removed from the output file's symbol table.  All other 
+non-global symbol names will remain in the output files symbol table. See -exported_symbols_list for syntax and use
+of wildcards.
+.It Fl non_global_symbols_no_strip_list Ar filename
+The specified 
+.Ar filename 
+contains a list of non-global symbol names that should be remain in the output file's symbol table.  All other 
+symbol names will be removed from the output file's symbol table. See -exported_symbols_list for syntax and use
+of wildcards.
+.El
+.Ss Rarely used Options
+.Bl -tag
+.It Fl v
+Prints the version of the linker.
+.It Fl no_uuid
+Do not generate an LC_UUID load command in the output file.
+.It Fl root_safe
+Sets the MH_ROOT_SAFE bit in the mach header of the output file.
+.It Fl setuid_safe
+Sets the MH_SETUID_SAFE bit in the mach header of the output file.
+.It Fl interposable
+Indirects access to all to exported symbols when creating a dynamic library.  
+.It Fl init Ar symbol_name
+The specified symbol_name will be run as the first initializer.   Only used when creating a dynamic library.  
+.It Fl sub_library Ar library_name
+The specified dylib will be re-exported. For example the library_name for /usr/lib/libobjc_profile.A.dylib would be libobjc. 
+Only used when creating a dynamic library.  
+.It Fl sub_umbrella Ar framework_name
+The specified framework will be re-exported.  Only used when creating a dynamic library. 
+.It Fl allowable_client Ar name
+Restricts what can link against the dynamic library being created.  
+.It Fl client_name Ar name
+Enables a bundle to link against a dylib that was built with -allowable_client.  
+The name specified must match one of the -allowable_client names specified when the dylib was created.
+.It Fl umbrella Ar framework_name
+Specifies that the dylib being linked is re-exported through an umbrella framework of the specified name.
+.It Fl headerpad Ar size
+Specifies the minimum space for future expansion of the load commands.  Only useful if intend to run 
+install_name_tool to alter the load commands later. Size is a hexadecimal number.
+.It Fl headerpad_max_install_names
+Automatically adds space for future expansion of load commands such that all paths could expand to MAXPATHLEN. 
+Only useful if intend to run install_name_tool to alter the load commands later. Size is a hexadecimal number.
+.It Fl bind_at_load
+Sets a bit in the mach header of the resulting binary which tells dyld to bind all symbols when the binary is loaded, rather than lazily.
+.It Fl force_flat_namespace
+Sets a bit in the mach header of the resulting binary which tells dyld to not only use flat namespace for the binary,
+but force flat namespace binding on all dylibs and bundles loaded in the process.  Can only be used when linking main executables.
+.It Fl sectalign Ar segname Ar sectname Ar value
+The section named sectname in the segment segname will have its alignment set to value, where value is a hexadecimal 
+number that must be an integral power of 2. 
+.It Fl stack_addr Ar address
+Specifies the initial address of the stack pointer value, where value is a hexadecimal number rounded to a page boundary.
+.It Fl segprot Ar segname Ar max_prot Ar init_prot
+Specifies the maximum and initial virtual memory protection of the named segment, name, to be max and init ,respectively. 
+The values for max and init are any combination of the characters `r' (for read), `w' (for write), `x' (for execute) and `-' (no access).
+.It Fl seg_addr_table Ar filename
+Specifies a file containing base addresses for dynamic libraries.  Each line of the file is a hexadecimal base address 
+followed by whitespace then the install name of the corresponding dylib. The # character denotes a comment.
+.It Fl segs_read_write_addr Ar address
+Allows a dynamic library to be built where the read-only and read-write segments are not contiguous.  The address 
+specified is a hexadecimal number that indicates the base address for the read-write segments.
+.It Fl segs_read_only_addr Ar address
+Allows a dynamic library to be built where the read-only and read-write segments are not contiguous.  The address 
+specified is a hexadecimal number that indicates the base address for the read-only segments.
+.It Fl segaddr Ar name Ar address
+Specifies the starting address of the segment named name to be address. The address must be a hexadecimal number 
+that is a multiple of 4K page size.
+.It Fl dylib_file Ar install_name:file_name
+Specifies that a dynamic shared library is in a different location than its standard location. Use this option 
+when you link with a library that is dependent on a dynamic library, and the dynamic library is in a location other 
+than its default location. install_name specifies the path where the library normally resides. file_name specifies 
+the path of the library you want to use instead. For example, if you link to a library that depends upon the dynamic 
+library libsys and you have libsys installed in a nondefault location, you would use this option: 
+-dylib_file /lib/libsys_s.A.dylib:/me/lib/libsys_s.A.dylib.
+.It Fl prebind
+The created output file will be in the prebound format.  This was used in Mac OS X 10.3 and earlier to improve launch performance.  
+.It Fl weak_reference_mismatches Ar treatment
+Specifies what to do if a symbol is weak-imported in one object file but not weak-imported in another.  The valid 
+treatments are: error, weak, or non-weak.  The default is non-weak.
+.It Fl read_only_relocs Ar treatment
+Enables the use of relocations which will cause dyld to modify (copy-on-write) read-only pages.  The compiler will 
+normally never generate such code.  
+.It Fl force_cpusubtype_ALL
+The is only applicable with -arch ppc.  It tells the linker to ignore the PowerPC cpu requirements (e.g. G3, G4 or G5) encoded
+in the object files and mark the resulting binary as runnable on any PowerPC cpu.
+.It Fl dylinker_install_name Ar path
+Only used when building dyld.
+.It Fl no_arch_warnings
+Suppresses warning messages about files that have the wrong architecture for the -arch flag
+.It Fl arch_errors_fatal
+Turns into errors, warnings about files that have the wrong architecture for the -arch flag. 
+.It Fl e Ar symbol_name
+Specifies the entry point of a main executable.  By default the entry name is "start" which is found in crt1.o which contains
+the glue code need to set up and call main().
+.It Fl w
+Suppress all warning messages
+.It Fl final_output Ar name
+Specifies the install name of a dylib if -install_name is not used.  This option is used by gcc driver when it is invoked 
+with multiple -arch arguments.  
+.It Fl arch_multiple
+Specifes that the linker should augment error and warning messages with the architecture name.  This option is used by gcc 
+driver when it is invoked with multiple -arch arguments.  
+.It Fl twolevel_namespace_hints
+Specifies that hints should be added to the resulting binary that can help speed up runtime binding by dyld as long as the 
+libraries being linked against have not changed.
+.It Fl dot Ar path
+Create a file a file at the specified path containing a graph of symbol dependencies.  The .dot file can be viewed in GraphViz.
+.It Fl keep_relocs
+Add section based relocation records to a final linked image.  These relocations are ignored at runtime by dyld.
+.It Fl warn_stabs
+Print a warning when the linker cannot do a BINCL/EINCL optimzation because the compiler put a bad stab symbol inside
+a BINCL/EINCL range.
+.El
+.Ss Obsolete Options
+.Bl -tag
+.It Fl segalign Ar value
+All segments must be page aligned.  This option is obsolete.
+.It Fl seglinkedit
+Object files (MH_OBJECT) with a LINKEDIT segment are no longer supported. This option is obsolete.
+.It Fl noseglinkedit
+This is the default.  This option is obsolete.
+.It Fl fvmlib
+Fixed VM shared libraries (MH_FVMLIB) are no longer supported. This option is obsolete.
+.It Fl preload
+Preload executables (MH_PRELOAD) are no longer supported.  This option is obsolete.
+.It Fl sectobjectsymbols Ar segname Ar sectname
+Adding a local label at a section start is no longer supported.  This option is obsolete.
+.It Fl nofixprebinding
+The MH_NOFIXPREBINDING bit of mach_headers has been ignored since Mac OS X 10.3.9.  This option is obsolete.
+.It Fl noprebind_all_twolevel_modules
+Multi-modules in dynamic libraries have been ignored at runtime since Mac OS X 10.4.0.  This option is obsolete.
+.It Fl prebind_all_twolevel_modules
+Multi-modules in dynamic libraries have been ignored at runtime since Mac OS X 10.4.0.  This option is obsolete.
+.It Fl prebind_allow_overlap
+When using -prebind, the linker allows overlapping by default, so this option is obsolete.
+.It Fl noprebind
+LD_PREBIND is no longer supported as a way to force on prebinding, so there no longer needs to
+be a command line way to override LD_PREBIND.  This option is obsolete.
+.It Fl sect_diff_relocs Ar treatment
+This option was an attempt to warn about linking .o files compiled without -mdynamic-no-pic into 
+a main executable, but the false positive rate generated too much noise to make the option useful.
 This option is obsolete.
-.TP
-.BI \-dylib_compatibility_version " number"
-For dynamic shared library files, this specifies the compatibility version number
-of the library.  When a library is used by a program, the compatibility version is checked
-and if the program's version is greater that the library's version, it is an error.
-The format of
-.I number
-is
-.I X[.Y[.Z]]
-where
-.I X
-must be a positive non-zero number less than or equal to 65535, and
-.I .Y
-and
-.I .Z
-are optional and if present must be non-negative numbers less than or
-equal to 255.
-If the compatibility version number is not specified, it has a
-value of 0 and no checking is done when the library is used.
-This option is used as the
-.IR libtool (1)
-.BI \-compatibility_version " number"
-option
-when its
-.B \-dynamic
-option is set.
-.TP
-.BI \-dylib_current_version " number"
-For dynamic shared library files, specifies the current version number
-of the library.  The current version of the library can be obtained
-programmatically by the user of the library so it can determine exactly which version of the library it is using.
-The format of
-.I number
-is
-.I X[.Y[.Z]]
-where
-.I X
-must be a positive non-zero number less than or equal to 65535, and
-.I .Y
-and
-.I .Z
-are optional and if present must be non-negative numbers less than or
-equal to 255.
-If the version number is not specified, it has a
-value of 0.
-This option is used as the
-.IR libtool (1)
-.BI \-current_version " number"
-option when its
-.B \-dynamic
-option is set.
-.TP
-.BI \-single_module
-When building a dynamic library build the library so that it contains only
-one module.
-.TP
-.BI \-multi_module  (32-bit only)
-When building a dynamic library build the library so that it contains one
-module for each object file linked in.  This is the default.
-.TP
-.BI \-dylinker_install_name " name"
-For dynamic link editor files, specifies the name of the file
-the dynamic link editor will be installed in for programs that use it.
-.TP
-.BI \-macosx_version_min " version"
-This overrides the
-.B MACOSX_DEPLOYMENT_TARGET
-environment variable (see below).  Unlike other linker options, this one may
-be specified multiple times; only the last occurrence is effective.
-.PP
-The following environment variable is used to control the use of incompatible
-features in the output with respect to Mac OS X releases.
-.TP
-.B MACOSX_DEPLOYMENT_TARGET
-This is set to indicate the oldest Mac OS X version that that the output is to
-be used on.  When this is set to a release that is older than the current
-release features that are incompatible with that release will be disabled.  If
-a feature is seen in the input that can't be in the output due to this setting
-a warning is issued.  The current allowable values for this are
-.B 10.1,
-.B 10.2
-.B 10.3,
-and
-.B 10.4
-with the default being
-.B 10.4
-for the i386 architecture and
-.B 10.1
-for all other architectures.
-.PP
-The following environment variables are used by Apple's Build and Integration
-team:
-.TP
-.B LD_TRACE_ARCHIVES
-When this is set it causes a message of the form ``[Logging for XBS]
-Used static archive:
-.I filename''
-for each static archive that has members linked into the output.
-.TP
-.B LD_TRACE_DYLIBS
-When this is set it causes a message of the form ``[Logging for XBS]
-Used dynamic library:
-.I filename''
-for each dynamic library linked into the output.
-.TP
-.B RC_TRACE_PREBINDING_DISABLED
-When this is set it causes a message of the form ``[Logging for XBS
-prebinding disabled for
-.I filename
-because
-.I reason''.
-Where
-.I filename
-is the value of the
-.B \-final_output
-argument if specified or the value of the
-.B \-o
-argument.
-.TP
-.BI \-final_output " filename"
-The argument
-.I filename
-is used in the above message when RC_TRACE_PREBINDING_DISABLED is set.
-.TP
-.B LD_TRACE_FILE
-When this is set, messages displayed due to the
-.B LD_TRACE_ARCHIVES
-,
-.B LD_TRACE_DYLIBS
-, and
-.B LD_TRACE_PREBINDING_DISABLED
-environment variables are printed to the file whose path is specified
-by this variable instead of stdout.
-.TP
-.B LD_SPLITSEGS_NEW_LIBRARIES
-When set and
-.B MACOSX_DEPLOYMENT_TARGET
-is set to 10.4 or greater and the output is a dynamic library, and if the
-install name of the library is not listed the segment address table, and if the
-environment variable
-.B LD_UNPREBOUND_LIBRARIES
-is set with a file name with a list of library install names and the install
-name is not listed, then this is built as a split shared library.
-
-.PP
-Options available in early versions of the Mach-O link editor
-may no longer be supported.
-
-.SH FILES
-.ta \w'/Network/Library/Frameworks/*.framework/*\ \ 'u
-/lib/lib*.{a,dylib}    libraries
-.br
-/usr/lib/lib*.{a,dylib}
-.br
-/usr/local/lib/lib*.{a,dylib}
-.br
-/Library/Frameworks/*.framework/*      framework libraries
-.br
-/Network/Library/Frameworks/*.framework/*      framework libraries
-.br
-/System/Library/Frameworks/*.framework/*       framework libraries
-.br
-a.out  output file
-.SH "SEE ALSO"
-as(1), ar(1), cc(1), libtool(1), ranlib(1), nm(1), otool(1) lipo(1),
-arch(3), dyld(3), Mach-O(5), strip(1), redo_prebinding(1)
+.It Fl run_init_lazily
+This option was removed in Mac OS X 10.2.
+.It Fl single_module
+This is now the default so does not need to be specified. 
+.It Fl multi_module
+Multi-modules in dynamic libraries have been ignored at runtime since Mac OS X 10.4.0.  This option is obsolete.
+.It Fl no_dead_strip_inits_and_terms
+The linker never dead strips initialzation and termination routines.  They are considered "roots" of the dead strip graph.
+.It Fl A Ar basefile
+Obsolete incremental load format.  This option is obsolete.
+.It Fl b
+Used with -A option to strip base file's symbols.  This option is obsolete.
+..It Fl M
+Obsolete option to produce a load map.  Use -map option instead. 
+.It Fl Sn
+Don't strip any symbols.  This is the default.  This option is obsolete.
+.It Fl Si
+Optimize stabs debug symbols to remove duplicates.  This is the default.  This option is obsolete.
+.It Fl Sp
+Write minimal stabs which causes the debugger to open and read the original .o file for full stabs.
+This style of debugging is obsolete in Mac OS X 10.5.  This option is obsolete.
+.It Fl X
+Strip local symbols that being the 'L'.  This is the default.  This option is obsolete.
+.It Fl s
+Completely strip the output, including removing the symbol table.  This file format variant is no longer supported.  
+This option is obsolete.
+.It Fl m
+Don't treat multiple definitions as an error.  This is no longer supported. This option is obsolete.
+.It Fl y Ns symbol
+Display each file in which 
+.Ar symbol
+is used.  This was previously used to debug where an undefined symbol was used, but the linker now
+automatically prints out all usages.  The -why_live option can also be used to display what kept 
+a symbol from being dead striped.  This option is obsolete.
+.It Fl Y Ar number
+Used to control how many occurances of each symbol specifed with -y would be shown.  This option is obsolete.
+.It Fl nomultidefs
+Only used when linking an umbrella framework.  Sets the MH_NOMULTIDEFS bit in the mach_header.  The MH_NOMULTIDEFS
+bit has been obsolete since Mac OS X 10.4.  This option is obsolete.
+.It Fl multiply_defined_unused Ar treatment
+Previously provided a way to warn or error if any of the symbol definitions in the output file matched any
+definitions in dynamic library being linked.  This option is obsolete.
+.It Fl multiply_defined Ar treatment
+Previously provided a way to warn or error if any of the symbols used from a dynamic library were also 
+available in another linked dynamic library.  This option is obsolete.
+.It Fl private_bundle
+Previously prevented errors when -flat_namespace, -bundle, and -bundle_loader were used and the bundle 
+contained a definition that conflicted with a symbol in the main executable.  The linker no longer
+errors on such conflicts.  This option is obsolete.
+.It Fl noall_load
+This is the default.  This option is obsolete.
+.It Fl seg_addr_table_filename Ar path
+Use 
+.Ar path
+instead of the install name of the library for matching an entry in the seg_addr_table.  This option is obsolete.
+.It Fl sectorder Ar segname sectname orderfile
+Replaced by more general -order_file option.
+.It Fl sectorder_detail
+Produced extra logging about which entries from a sectorder entries were used.  Replaced by -order_file_statistics. 
+This option is obsolete. 
+.El
+.Sh SEE ALSO
+as(1), ar(1), cc(1), nm(1), otool(1) lipo(1),
+arch(3), dyld(3), Mach-O(5), strip(1), rebase(1)
index a468b0d99935e8cf5281a71737f236bdb23313e0..e8a771cadd276c6a80b0d4a8d2e5764307acac65 100644 (file)
@@ -39,7 +39,7 @@
 /* Begin PBXBuildFile section */
                F9023C4E06D5A272001BBF46 /* ld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9023C3F06D5A254001BBF46 /* ld.cpp */; };
                F933E3D9092E855B0083EAC8 /* ObjectDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F971EED706D5AD240041D381 /* ObjectDump.cpp */; };
-               F97288E707D277570031794D /* SectCreate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F97288E607D277570031794D /* SectCreate.cpp */; };
+               F97F5029070D0BB200B9FCD7 /* ld.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = F97F5028070D0BB200B9FCD7 /* ld.1 */; };
                F9B1A2640A3A563E00DA8FAB /* rebase.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = F9B1A2580A3A448800DA8FAB /* rebase.1 */; };
                F9C0D4BD06DD28D2001C7193 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9C0D48A06DD1E1B001C7193 /* Options.cpp */; };
                F9EA72D5097454FF008B4F1D /* machochecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9EA72D4097454FF008B4F1D /* machochecker.cpp */; };
                        dstPath = /usr/share/man/man1;
                        dstSubfolderSpec = 0;
                        files = (
+                               F97F5029070D0BB200B9FCD7 /* ld.1 in CopyFiles */,
                                F9FCC3F20A54A75600CEB866 /* ld64.1 in CopyFiles */,
                        );
                        runOnlyForDeploymentPostprocessing = 1;
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+               3DA587190ACC53BE0015C432 /* LLVMReader.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; name = LLVMReader.hpp; path = src/LLVMReader.hpp; sourceTree = "<group>"; };
                C02A29DE0953B26E001FB8C1 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
-               F9023C3906D5A23E001BBF46 /* ld64 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ld64; sourceTree = BUILT_PRODUCTS_DIR; };
+               F9023C3906D5A23E001BBF46 /* ld */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ld; sourceTree = BUILT_PRODUCTS_DIR; };
                F9023C3E06D5A254001BBF46 /* ExecutableFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExecutableFile.h; path = src/ExecutableFile.h; sourceTree = "<group>"; };
                F9023C3F06D5A254001BBF46 /* ld.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ld.cpp; path = src/ld.cpp; sourceTree = "<group>"; };
                F9023C4106D5A254001BBF46 /* ObjectFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ObjectFile.h; path = src/ObjectFile.h; sourceTree = "<group>"; };
                F933E3CE092E84250083EAC8 /* MachOWriterExecutable.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; name = MachOWriterExecutable.hpp; path = src/MachOWriterExecutable.hpp; sourceTree = "<group>"; };
                F971EED306D5ACF60041D381 /* ObjectDump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ObjectDump; sourceTree = BUILT_PRODUCTS_DIR; };
                F971EED706D5AD240041D381 /* ObjectDump.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectDump.cpp; path = src/ObjectDump.cpp; sourceTree = "<group>"; };
-               F97288E607D277570031794D /* SectCreate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SectCreate.cpp; path = src/SectCreate.cpp; sourceTree = "<group>"; };
-               F972890007D27FD00031794D /* SectCreate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SectCreate.h; path = src/SectCreate.h; sourceTree = "<group>"; };
                F97F5028070D0BB200B9FCD7 /* ld.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; name = ld.1; path = doc/man/man1/ld.1; sourceTree = "<group>"; };
+               F98D26850AA779BD00416316 /* OpaqueSection.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; name = OpaqueSection.hpp; path = src/OpaqueSection.hpp; sourceTree = "<group>"; };
                F9B1A2580A3A448800DA8FAB /* rebase.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; name = rebase.1; path = doc/man/man1/rebase.1; sourceTree = "<group>"; };
                F9C0D48A06DD1E1B001C7193 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Options.cpp; path = src/Options.cpp; sourceTree = "<group>"; };
                F9C0D48B06DD1E1B001C7193 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Options.h; path = src/Options.h; sourceTree = "<group>"; };
                                F933E3CB092E84250083EAC8 /* MachOReaderArchive.hpp */,
                                F933E3CC092E84250083EAC8 /* MachOReaderDylib.hpp */,
                                F933E3CE092E84250083EAC8 /* MachOWriterExecutable.hpp */,
+                               3DA587190ACC53BE0015C432 /* LLVMReader.hpp */,
                                F9023C3E06D5A254001BBF46 /* ExecutableFile.h */,
                                F9023C4106D5A254001BBF46 /* ObjectFile.h */,
+                               F98D26850AA779BD00416316 /* OpaqueSection.hpp */,
                                F9023C3F06D5A254001BBF46 /* ld.cpp */,
                                F9C0D48A06DD1E1B001C7193 /* Options.cpp */,
                                F9C0D48B06DD1E1B001C7193 /* Options.h */,
-                               F97288E607D277570031794D /* SectCreate.cpp */,
-                               F972890007D27FD00031794D /* SectCreate.h */,
                                F9EA7582097882F3008B4F1D /* debugline.c */,
                                F9EA7583097882F3008B4F1D /* debugline.h */,
                                F9EA72D4097454FF008B4F1D /* machochecker.cpp */,
                F9023C3A06D5A23E001BBF46 /* Products */ = {
                        isa = PBXGroup;
                        children = (
-                               F9023C3906D5A23E001BBF46 /* ld64 */,
+                               F9023C3906D5A23E001BBF46 /* ld */,
                                F971EED306D5ACF60041D381 /* ObjectDump */,
                                F9EA72CB097454A6008B4F1D /* machocheck */,
                                F9EC77EE0A2F85F6002A3E39 /* rebase */,
                                F9023C3606D5A23E001BBF46 /* Sources */,
                                F9023C3706D5A23E001BBF46 /* Frameworks */,
                                F97F5025070D0B6300B9FCD7 /* CopyFiles */,
+                               F9FCC3EF0A54A4ED00CEB866 /* ShellScript */,
                        );
                        buildRules = (
                                F9E8D4BE07FCAF2A00FD5801 /* PBXBuildRule */,
                        );
                        name = ld;
                        productName = ld64;
-                       productReference = F9023C3906D5A23E001BBF46 /* ld64 */;
+                       productReference = F9023C3906D5A23E001BBF46 /* ld */;
                        productType = "com.apple.product-type.tool";
                };
                F971EED206D5ACF60041D381 /* ObjectDump */ = {
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/csh;
-                       shellScript = "# Let tests set MACOSX_DEPLOYMENT_TARGET as they need\nunsetenv MACOSX_DEPLOYMENT_TARGET\n\n# always use new linker\nsetenv LD_NO_CLASSIC_LINKER\n\n# run full test suite\n$SRCROOT/unit-tests/run-all-unit-tests\n\nexit 0";
+                       shellScript = "# Let tests set MACOSX_DEPLOYMENT_TARGET as they need\nunsetenv MACOSX_DEPLOYMENT_TARGET\n\n# always use new linker\nsetenv LD_NO_CLASSIC_LINKER\nsetenv LD_NO_CLASSIC_LINKER_STATIC\n\n# run full test suite\n\"$SRCROOT\"/unit-tests/run-all-unit-tests\n\nexit 0";
+                       showEnvVarsInLog = 0;
+               };
+               F9FCC3EF0A54A4ED00CEB866 /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 8;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+                       shellPath = /bin/sh;
+                       shellScript = "cd ${DSTROOT}/usr/bin\nln -s ld ld64";
+                       showEnvVarsInLog = 0;
                };
 /* End PBXShellScriptBuildPhase section */
 
                        files = (
                                F9023C4E06D5A272001BBF46 /* ld.cpp in Sources */,
                                F9C0D4BD06DD28D2001C7193 /* Options.cpp in Sources */,
-                               F97288E707D277570031794D /* SectCreate.cpp in Sources */,
                                F9EA7584097882F3008B4F1D /* debugline.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                                GCC_WARN_UNUSED_VALUE = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                INSTALL_PATH = /usr/bin;
+                               MACOSX_DEPLOYMENT_TARGET = 10.5;
                                OTHER_CPLUSPLUSFLAGS = "$(OTHER_CPLUSPLUSFLAGS)";
                                OTHER_LDFLAGS = "";
                                PREBINDING = NO;
-                               PRODUCT_NAME = ld64;
+                               PRODUCT_NAME = ld;
                                SECTORDER_FLAGS = "";
                                VERSIONING_SYSTEM = "apple-generic";
                                WARNING_CFLAGS = "-Wall";
                                OTHER_CPLUSPLUSFLAGS = "$(OTHER_CPLUSPLUSFLAGS)";
                                OTHER_LDFLAGS = "";
                                PREBINDING = NO;
-                               PRODUCT_NAME = ld64;
+                               PRODUCT_NAME = ld;
                                SECTORDER_FLAGS = "";
                                VALID_ARCHS = "i386 ppc";
                                VERSIONING_SYSTEM = "apple-generic";
index e735f9e2ed0927d4ebb3fa06f8fa621ce1d83429..708936665eedd049dcef6938301ea8605c87f7d0 100644 (file)
@@ -35,28 +35,31 @@ struct ppc
 {
        typedef Pointer32<BigEndian>            P;
        
-       enum ReferenceKinds {  kNoFixUp, kFollowOn, kPointer, kPointerWeakImport, kPointerDiff32, kPointerDiff64,
+       enum ReferenceKinds {  kNoFixUp, kFollowOn, kPointer, kPointerWeakImport, kPointerDiff16, kPointerDiff32, kPointerDiff64,  
                                                        kBranch24, kBranch24WeakImport, kBranch14,
                                                        kPICBaseLow16, kPICBaseLow14, kPICBaseHigh16, 
-                                                       kAbsLow16, kAbsLow14, kAbsHigh16, kAbsHigh16AddLow };
+                                                       kAbsLow16, kAbsLow14, kAbsHigh16, kAbsHigh16AddLow, 
+                                                       kDtraceProbe, kDtraceProbeSite, kDtraceIsEnabledSite, kDtraceTypeReference };
 };
 
 struct ppc64
 {
        typedef Pointer64<BigEndian>            P;
        
-       enum ReferenceKinds {  kNoFixUp, kFollowOn, kPointer, kPointerWeakImport, kPointerDiff32, kPointerDiff64,
+       enum ReferenceKinds {  kNoFixUp, kFollowOn, kPointer, kPointerWeakImport, kPointerDiff16, kPointerDiff32, kPointerDiff64,
                                                        kBranch24, kBranch24WeakImport, kBranch14,
                                                        kPICBaseLow16, kPICBaseLow14, kPICBaseHigh16, 
-                                                       kAbsLow16, kAbsLow14, kAbsHigh16, kAbsHigh16AddLow };
+                                                       kAbsLow16, kAbsLow14, kAbsHigh16, kAbsHigh16AddLow, 
+                                                       kDtraceProbe, kDtraceProbeSite, kDtraceIsEnabledSite, kDtraceTypeReference  };
 };
 
 struct x86
 {
        typedef Pointer32<LittleEndian>         P;
        
-       enum ReferenceKinds {  kNoFixUp, kFollowOn, kPointer, kPointerWeakImport, kPointerDiff, 
-                                                       kPCRel32, kPCRel32WeakImport, kAbsolute32 };
+       enum ReferenceKinds {  kNoFixUp, kFollowOn, kPointer, kPointerWeakImport, kPointerDiff, kPointerDiff16,
+                                                       kPCRel32, kPCRel32WeakImport, kAbsolute32,  kPCRel16, 
+                                                       kDtraceProbe, kDtraceProbeSite, kDtraceIsEnabledSite, kDtraceTypeReference  };
 };
 
 struct x86_64
@@ -67,7 +70,8 @@ struct x86_64
                                                        kPCRel32, kPCRel32_1, kPCRel32_2, kPCRel32_4,
                                                        kBranchPCRel32, kBranchPCRel32WeakImport,
                                                        kPCRel32GOTLoad, kPCRel32GOTLoadWeakImport,
-                                                       kPCRel32GOT, kPCRel32GOTWeakImport };
+                                                       kPCRel32GOT, kPCRel32GOTWeakImport,
+                                                       kDtraceProbe, kDtraceProbeSite, kDtraceIsEnabledSite, kDtraceTypeReference  };
 };
 
 
index 576554c65336a6db04a18dd71f511db502eb5e73..8fa709984d3854ffc206226436f16ebe454dac19 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -38,8 +38,6 @@ namespace ExecutableFile {
        {
                ObjectFile::Reader*             reader;
                DynamicLibraryOptions   options;
-               bool                                    indirect;       // library found indirect.  Do not make load command
-               ObjectFile::Reader*             directReader;   // direct library which re-exports this library
        };
 
        class Writer : public ObjectFile::Reader
@@ -50,13 +48,16 @@ namespace ExecutableFile {
                virtual const char*                                                             getPath() = 0;
                virtual std::vector<class ObjectFile::Atom*>&   getAtoms() = 0;
                virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) = 0;
-
+               virtual ObjectFile::Atom&                                               makeObjcInfoAtom(ObjectFile::Reader::ObjcConstraint objcContraint, 
+                                                                                                                                               bool objcReplacementClasses) = 0;
                virtual class ObjectFile::Atom*                                 getUndefinedProxyAtom(const char* name) = 0;
                virtual uint64_t                                                                write(std::vector<class ObjectFile::Atom*>& atoms,
                                                                                                                          std::vector<class ObjectFile::Reader::Stab>& stabs,
                                                                                                                          class ObjectFile::Atom* entryPointAtom,
                                                                                                                          class ObjectFile::Atom* dyldHelperAtom,
-                                                                                                                         bool createUUID) = 0;
+                                                                                                                         bool createUUID, bool canScatter,
+                                                                                                                         ObjectFile::Reader::CpuConstraint cpuConstraint,
+                                                                                                                         bool biggerThanTwoGigs) = 0;
 
        protected:
                                                                        Writer(std::vector<DyLibUsed>&) {};
diff --git a/src/LLVMReader.hpp b/src/LLVMReader.hpp
new file mode 100644 (file)
index 0000000..e49c5ae
--- /dev/null
@@ -0,0 +1,561 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2006-2007 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@
+ */
+
+#ifndef __LLVM_READER_H__
+#define __LLVM_READER_H__
+
+#include <stdlib.h>
+#include <vector>
+#include "MachOFileAbstraction.hpp"
+#include "Architectures.hpp"
+#include "ObjectFile.h"
+#include "llvm/LinkTimeOptimizer.h"
+
+#define LLVMLinkTimeOptimizer "LLVMlto.dylib"
+
+class LLVMReader;
+
+//
+// LLVMReference handles LLVMAtom references. These references facilitate 
+// symbol resolution.
+//
+
+class LLVMReference : public ObjectFile::Reference
+{
+public:
+                                                                               LLVMReference (const char *n) : fName(n), fAtom(0), fFromAtom(0) { }
+
+       bool                                                            isTargetUnbound() const                         { return fAtom == 0; }
+       bool                                                            isFromTargetUnbound() const             { return true; }
+       uint8_t                                                         getKind() const                                         { return 0; }
+       uint64_t                                                        getFixUpOffset() const                          { return 0; }
+       const char *                                            getTargetName() const                           { return fName; }
+       ObjectFile::Atom&                                       getTarget() const                                       { return *fAtom; }
+       uint64_t                                                        getTargetOffset() const                         { return 0; }
+       bool                                                            hasFromTarget() const                           { return false; }
+       ObjectFile::Atom&                                       getFromTarget() const                           { return *fFromAtom; }
+       const char *                                            getFromTargetName() const                       { return NULL; }
+       uint64_t                                                        getFromTargetOffset() const             { return 0; }
+       TargetBinding                                           getTargetBinding() const;
+       TargetBinding                                           getFromTargetBinding() const  { return kDontBind; }
+       void                                                            setTarget (ObjectFile::Atom &a, uint64_t offset) 
+                                                                               { fAtom = &a; }
+       void                                                            setFromTarget(ObjectFile::Atom &a)      { }
+       const char *                                            getDescription() const                          { return NULL; }
+
+private:
+       const char *                                            fName;
+       ObjectFile::Atom *                                      fAtom;
+       ObjectFile::Atom *                                      fFromAtom;
+};
+
+ObjectFile::Reference::TargetBinding LLVMReference::getTargetBinding() const 
+{ 
+       if (strncmp (fName, "__ld64.llvm", 11) == 0)
+               return kDontBind;
+       else return kUnboundByName;
+}
+
+//
+// LLVMAtom acts as a proxy Atom for the symbols that are exported by LLVM bytecode file. Initially,
+// LLVMReader creates LLVMAtoms to allow linker proceed with usual symbol resolution phase. After
+// optimization is performed, real Atoms are created for these symobls. However these real Atoms
+// are not inserted into global symbol table. LLVMAtom holds real Atom and forwards appropriate
+// methods to real atom.
+//
+
+class LLVMAtom : public ObjectFile::Atom
+{
+public:
+       ObjectFile::Reader *                                            getFile() const                         { return fOwner; }
+       bool                                                                            getTranslationUnitSource (const char **dir, const char **name) const 
+                                                                                                                                                       { return fRealAtom->getTranslationUnitSource (dir, name); }
+       const char *                                                            getName () const                        { return fAtomName;     }
+       const char *                                                            getDisplayName() const          { return this->getName(); }
+       Scope                                                                           getScope() const                        { return fScope; }
+       DefinitionKind                                                          getDefinitionKind() const;
+       SymbolTableInclusion                                            getSymbolTableInclusion() const 
+                                                                                                                                                       { return fRealAtom->getSymbolTableInclusion(); }
+       bool                                                                            dontDeadStrip() const           { return false; }
+       bool                                                                            isZeroFill() const                      { return fRealAtom->isZeroFill(); }
+       uint64_t                                                                        getSize() const                         { return fRealAtom->getSize(); }
+       std::vector<ObjectFile::Reference*>&            getReferences() const 
+                                                                                                                                                       { return (fRealAtom ? fRealAtom->getReferences() : (std::vector<ObjectFile::Reference*>&)fReferences); }
+       bool                                                                            mustRemainInSection() const { return fRealAtom->mustRemainInSection(); }
+       const char *                                                            getSectionName() const          { return (fRealAtom ? fRealAtom->getSectionName() : NULL); }
+       // Linker::optimize() sets section for this atom, not fRealAtom. Use this Atom's fSection.
+       class ObjectFile::Section *                                     getSection() const                      { return fSection; }
+       ObjectFile::Segment&                                            getSegment() const                      { return fRealAtom->getSegment(); }
+       uint32_t                                                                        getOrdinal() const { return (fRealAtom ? fRealAtom->getOrdinal() : 0); }
+       ObjectFile::Atom&                                                       getFollowOnAtom() const         { return fRealAtom->getFollowOnAtom(); }
+       std::vector<ObjectFile::LineInfo>*                      getLineInfo() const             { return fRealAtom->getLineInfo(); }
+       ObjectFile::Alignment                                           getAlignment() const;
+       void                                                                            copyRawContent(uint8_t buffer[]) const 
+                                                                                                                                                       { fRealAtom->copyRawContent(buffer); }
+       void                                                                            setScope(Scope s)                       { if (fRealAtom) fRealAtom->setScope(s); }
+
+       LLVMAtom(ObjectFile::Reader *owner, const char *n, llvm::LLVMSymbol *ls);
+       
+       void                                                                            setRealAtom (ObjectFile::Atom *atom) 
+                                                                                                                                                       { fRealAtom = atom; }
+       void                                                                            addReference(ObjectFile::Reference *ref) 
+                                                                                                                                                       { fReferences.push_back(ref); }
+
+       void                                                                            setSectionOffset(uint64_t offset) { fSectionOffset = offset; if (fRealAtom) fRealAtom->setSectionOffset(offset); }
+       void                                                                            setSection(class ObjectFile::Section* sect) { fSection = sect; if (fRealAtom) fRealAtom->setSection(sect); }
+                                                                                                                                                       
+private:
+       ObjectFile::Reader *                                            fOwner;
+       const char *                                                            fAtomName;
+       llvm::LLVMSymbol *                                                      fLLVMSymbol;
+       ObjectFile::Atom *                                                      fRealAtom;
+       std::vector<ObjectFile::Reference*>             fReferences;
+       ObjectFile::Atom::Scope                                         fScope;
+       ObjectFile::Atom::DefinitionKind                        fDefKind;
+};
+
+ObjectFile::Atom::DefinitionKind LLVMAtom::getDefinitionKind() const 
+{ 
+       if (fRealAtom) 
+               return fRealAtom->getDefinitionKind();
+       else
+               return fDefKind;
+}
+
+LLVMAtom::LLVMAtom(ObjectFile::Reader *owner, const char *n, llvm::LLVMSymbol *ls) : fOwner(owner), fAtomName(n), fLLVMSymbol(ls), fRealAtom(0) 
+{
+
+       if (!ls) return;
+
+       switch (ls->getLinkage()) {
+       case llvm::LTOExternalLinkage:
+               fScope = scopeGlobal;
+               fDefKind = kRegularDefinition;
+               break;
+       case llvm::LTOLinkOnceLinkage:
+       case llvm::LTOWeakLinkage:
+               // ??? How to differentiate between this two linkage types ?
+               fScope = scopeGlobal;
+               fDefKind = kWeakDefinition;
+               break;
+       default:
+               throw "Unexpected LLVM Symbol Linkage info\n";
+               break;
+       }
+}
+
+ObjectFile::Alignment LLVMAtom::getAlignment() const
+{
+       if (fRealAtom)
+               return fRealAtom->getAlignment(); 
+       else {
+               ObjectFile::Alignment alignment(fLLVMSymbol->getAlignment());
+               return alignment;
+       }
+}
+
+//
+// LLVMReader does not expose internal symbols defined and used inside bytecode file. However, 
+// these symbols may refere other external symbols. IntercessorAtom facilitate by acting as a 
+// orignator of such references during pre-optimization symbol resoultion phase. These atoms
+// are immediately removed after optimization.
+//
+
+class IntercessorAtom : public ObjectFile::Atom
+{
+public:
+       ObjectFile::Reader *                                            getFile() const                         { return fOwner; }
+       bool                                                                            getTranslationUnitSource (const char **dir, const char **name) const 
+                                                                                                                                                       { return false; }
+       const char *                                                            getName () const                        { return fAtomName;     }
+       const char *                                                            getDisplayName() const          { return this->getName(); }
+       Scope                                                                           getScope() const                        { return scopeGlobal; }
+       DefinitionKind                                                          getDefinitionKind() const   { return kRegularDefinition; }
+       SymbolTableInclusion                                            getSymbolTableInclusion() const 
+       { return kSymbolTableNotIn; }
+       bool                                                                            dontDeadStrip() const           { return false; }
+       bool                                                                            isZeroFill() const                      { return false; }
+       uint64_t                                                                        getSize() const                         { return 0; }
+       std::vector<ObjectFile::Reference*>&            getReferences() const           { return  (std::vector<ObjectFile::Reference*>&)fReferences; }
+       bool                                                                            mustRemainInSection() const { return false; }
+       const char *                                                            getSectionName() const          { return NULL; }
+       class ObjectFile::Section *                                     getSection() const                      { return NULL; }
+       ObjectFile::Segment&                                            getSegment() const                      { return this->getSegment(); }
+       uint32_t                                                                        getOrdinal() const          { return 0; }
+       ObjectFile::Atom&                                                       getFollowOnAtom() const         { return this->getFollowOnAtom(); }
+       std::vector<ObjectFile::LineInfo>*                      getLineInfo() const             { return NULL; }
+       ObjectFile::Alignment                                           getAlignment() const            { ObjectFile::Alignment a(0); return a; }
+       void                                                                            copyRawContent(uint8_t buffer[]) const 
+                                                                                                                                                       { }
+       void                                                                            setScope(Scope s)                       { }
+
+
+       IntercessorAtom(ObjectFile::Reader *owner, std::set<std::string> &references);
+       
+       void                                                                            addReference(ObjectFile::Reference *ref) 
+                                                                                                                                                       { fReferences.push_back(ref); }
+       void                                                                            addReferences(std::set<std::string> &references);
+private:
+       ObjectFile::Reader *                                            fOwner;
+       char *                                                          fAtomName;
+       std::vector<ObjectFile::Reference*>             fReferences;
+       ObjectFile::Atom::Scope                                         fScope;
+       ObjectFile::Atom::DefinitionKind                        fDefKind;
+};
+
+IntercessorAtom::IntercessorAtom(ObjectFile::Reader *owner, std::set<std::string> &references)
+{
+       static int sCount = 0;
+       fOwner = owner;
+       fAtomName = (char *) malloc (sizeof(char)*20);
+       sprintf (fAtomName,"__ld64.llvm%d__",sCount++);
+
+       for (std::set<std::string>::iterator it = references.begin(); it != references.end(); it++) {
+       std::string r = *it;
+       this->addReference(new LLVMReference(r.c_str()));
+       }
+}
+
+void IntercessorAtom::addReferences(std::set<std::string> &references)
+{
+       for (std::set<std::string>::iterator it = references.begin(); it != references.end(); it++) {
+       std::string r = *it;
+       this->addReference(new LLVMReference(r.c_str()));
+       }
+}
+
+class InIntercessorSet
+{
+public:
+       InIntercessorSet(std::set<ObjectFile::Atom*>& iAtoms) : fIntercessorAtoms(iAtoms) {}
+
+       bool operator()(ObjectFile::Atom*& atom) const {
+               return ( fIntercessorAtoms.count(atom) != 0 );
+       }
+
+private:
+       std::set<ObjectFile::Atom*>& fIntercessorAtoms;
+};
+
+//
+// LLVMOptimizer class is responsible for communicating with LLVM LTO library.
+// One LLVMOptimizer object is created per Linker invocation. All LLVMReaders share this
+// one single optimizer object.
+//
+
+class LLVMOptimizer
+{
+public:
+                                                                                               LLVMOptimizer(Options &opt);
+                                                                                               ~LLVMOptimizer()                                { if (fLLVMHandle) dlclose(fLLVMHandle);        }
+
+
+       void                                                                            optimize(std::vector<ObjectFile::Atom *>&, std::vector<ObjectFile::Atom*>&, uint32_t);
+       void                                                                            read(ObjectFile::Reader *, const char *, std::set<std::string>&, std::vector<ObjectFile::Atom*>&, const char *);
+       void                                                                            reconcileOptimizedAtoms(std::vector<class ObjectFile::Atom*>&, std::vector<class ObjectFile::Atom*>&);
+       void                                                                            addIntercessor(IntercessorAtom * atom) { fIntercessorAtoms.insert(atom); }
+       void                                                                            addReader(ObjectFile::Reader *reader) { fLLVMReaders[reader->getPath()] = reader; }
+       cpu_type_t                                                                      getCpuType(std::string &targetTriple);
+       bool                                                                            validArchitecture(const char *path, cpu_type_t architecture);
+       class LCStringEquals
+       {
+       public:
+               bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
+       };
+       typedef hash_map<const char*, LLVMAtom*, hash<const char*>, LCStringEquals> LLVMAtomToNameMapper;
+       typedef hash_map<const char*, ObjectFile::Reader*, hash<const char*>, LCStringEquals> ReaderToPathMapper;
+       
+    typedef llvm::LinkTimeOptimizer * (*createLLVMOptimizer_func_t) ();
+private:
+       bool                                                                            fOptimized;
+       llvm::LinkTimeOptimizer                                         *fOptimizer;
+       void                                                                            *fLLVMHandle;
+       LLVMAtomToNameMapper                                            fLLVMSymbols;
+       Options&                                                                        fOptions;
+       std::set<ObjectFile::Atom*>                                     fIntercessorAtoms;
+       ReaderToPathMapper                                                      fLLVMReaders;
+};
+
+LLVMOptimizer::LLVMOptimizer(Options &opts) : fOptions(opts)
+{
+       fLLVMHandle = (llvm::LinkTimeOptimizer *) dlopen (LLVMLinkTimeOptimizer, RTLD_LAZY);
+       if (!fLLVMHandle)
+               throwf("Unable to load LLVM library: \n", dlerror());
+
+       createLLVMOptimizer_func_t createLLVMOptimizer_fp = (createLLVMOptimizer_func_t)dlsym(fLLVMHandle, "createLLVMOptimizer");
+       if (createLLVMOptimizer_fp == NULL)
+               throwf("couldn't find \"createLLVMOptimizer\" ", dlerror());
+       fOptimizer = createLLVMOptimizer_fp();
+       fOptimized = false;
+}
+
+cpu_type_t LLVMOptimizer::getCpuType(std::string &targetTriple)
+{
+       if ( strncmp (targetTriple.c_str(), "powerpc-", 8) == 0)
+               return CPU_TYPE_POWERPC;
+       else if ( strncmp (targetTriple.c_str(), "powerpc64-", 10))
+               return CPU_TYPE_POWERPC64;
+       // match "i[3-9]86-*".
+       else if ( targetTriple.size() >= 5 && targetTriple[0] == 'i' && targetTriple[2] == '8' && targetTriple[3] == '6' && targetTriple[4] == '-' && targetTriple[1] - '3' < 6  )
+               return CPU_TYPE_I386;
+       else
+               return CPU_TYPE_ANY;
+}
+
+bool LLVMOptimizer::validArchitecture(const char *path, cpu_type_t architecture)
+{
+       std::string targetTriple;
+       fOptimizer->getTargetTriple(path, targetTriple);
+       if (architecture != getCpuType(targetTriple)) {
+               fOptimizer->removeModule(path);
+               return false;
+       }
+
+       return true;
+}
+
+void LLVMOptimizer::optimize(std::vector<ObjectFile::Atom*> &allAtoms, std::vector<ObjectFile::Atom*> &newAtoms, uint32_t nextInputOrdinal)
+{
+       if (fOptimized)
+               return;
+
+       char * tmp = "/tmp/ld64XXXXXXXX";
+       char * bigOfile = (char *) malloc (strlen (tmp) + 3);
+       if (!bigOfile)
+               throw "Unable to create temp file name";
+       strcpy (bigOfile, tmp);
+       mktemp (bigOfile);
+       strcat (bigOfile, ".o");
+
+       std::vector <const char *> exportList;
+       for (std::vector<ObjectFile::Atom*>::iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) {
+               ObjectFile::Atom *atom = *it;
+               if (atom->getName()) {
+                       ReaderToPathMapper::iterator pos = fLLVMReaders.find(atom->getFile()->getPath());
+                       if (pos != fLLVMReaders.end())
+                               exportList.push_back(atom->getName());
+               }
+                       
+       }
+
+       std::string targetTriple;
+       llvm::LTOStatus status = fOptimizer->optimizeModules(bigOfile, exportList, targetTriple, fOptions.saveTempFiles(), fOptions.getOutputFilePath());
+       if (status != llvm::LTO_OPT_SUCCESS) {
+               if (status == llvm::LTO_WRITE_FAILURE)
+                       throw "Unable to write optimized output file";
+               if (status == llvm::LTO_ASM_FAILURE)
+                       throw "Unable to assemble optimized output file";
+               if (status == llvm::LTO_MODULE_MERGE_FAILURE)
+                       throw "Unable to merge bytecode files";
+               if (status == llvm::LTO_NO_TARGET)
+                       throw "Unable to load target optimizer";
+       }
+       fOptimized = true;
+
+       Options::FileInfo info = fOptions.findFile (bigOfile);
+       ObjectFile::Reader* nr = NULL;
+       int fd = ::open(info.path, O_RDONLY, 0);
+       if ( fd == -1 )
+               throwf("can't open file, errno=%d", errno);
+       if ( info.fileLen < 20 )
+               throw "file too small";
+
+       uint8_t* p = (uint8_t*)::mmap(NULL, info.fileLen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
+       if ( p == (uint8_t*)(-1) )
+               throwf("can't map file, errno=%d", errno);
+       
+       cpu_type_t cpt = getCpuType(targetTriple);
+       switch (cpt) {
+       case CPU_TYPE_POWERPC:
+               if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
+                       nr = new mach_o::relocatable::Reader<ppc>(p, info.path, info.modTime, fOptions.readerOptions(), nextInputOrdinal);
+               break;
+       case CPU_TYPE_POWERPC64:
+               if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
+                       nr = new mach_o::relocatable::Reader<ppc64>(p, info.path, info.modTime, fOptions.readerOptions(), nextInputOrdinal);
+               break;
+       case CPU_TYPE_I386:
+               if ( mach_o::relocatable::Reader<x86>::validFile(p) )
+                       nr = new mach_o::relocatable::Reader<x86>(p, info.path, info.modTime, fOptions.readerOptions(), nextInputOrdinal);
+               break;
+       default:
+               throw "file is not of required architecture";
+               break;
+       }
+
+       std::vector<class ObjectFile::Atom*> optimizedAtoms;
+       optimizedAtoms = nr->getAtoms();
+       reconcileOptimizedAtoms(optimizedAtoms, newAtoms);
+
+       allAtoms.erase(std::remove_if(allAtoms.begin(), allAtoms.end(), InIntercessorSet(fIntercessorAtoms)), allAtoms.end());
+       unlink(bigOfile);
+       free(bigOfile); 
+}
+
+void LLVMOptimizer::read(ObjectFile::Reader *reader, const char *path, std::set<std::string> &references, std::vector<ObjectFile::Atom*> &atoms, const char *intercessorName)
+{
+       llvm::LinkTimeOptimizer::NameToSymbolMap symbols;
+       llvm::LTOStatus status = fOptimizer->readLLVMObjectFile (path, symbols, references);
+       if (status != llvm::LTO_READ_SUCCESS)
+               throw "Unable to read LLVM bytecode file";
+
+       for (llvm::LinkTimeOptimizer::NameToSymbolMap::iterator itr = symbols.begin();
+                itr != symbols.end(); itr++) {
+               const char *name = itr->first;
+               llvm::LLVMSymbol *ls = itr->second;
+               LLVMAtom *a = new LLVMAtom(reader, name, ls);
+
+               LLVMAtomToNameMapper::iterator pos = fLLVMSymbols.find(name);
+               bool insertNewAtom = true;
+               if (pos != fLLVMSymbols.end()) {
+                       LLVMAtom *existingAtom = pos->second;
+                       ObjectFile::Atom::DefinitionKind newDefKind = a->getDefinitionKind();
+                       ObjectFile::Atom::DefinitionKind existingDefKind = existingAtom->getDefinitionKind();
+                       if (newDefKind == ObjectFile::Atom::kRegularDefinition 
+                               && existingDefKind == ObjectFile::Atom::kRegularDefinition)
+                               throwf ("duplicate symbol %s in %s and %s\n", name, a->getFile()->getPath(), existingAtom->getFile()->getPath());
+                       else if (newDefKind == ObjectFile::Atom::kWeakDefinition 
+                                        && existingDefKind == ObjectFile::Atom::kRegularDefinition)
+                               insertNewAtom = false;
+                       else if (newDefKind == ObjectFile::Atom::kWeakDefinition 
+                                        && existingDefKind == ObjectFile::Atom::kWeakDefinition)
+                               // pick one
+                               insertNewAtom = false;
+                       else if (newDefKind == ObjectFile::Atom::kRegularDefinition 
+                                        && existingDefKind == ObjectFile::Atom::kWeakDefinition)
+                               insertNewAtom = true;
+               }
+               if (insertNewAtom) {
+                       atoms.push_back(a);
+                       fLLVMSymbols[name] = a;
+                       a->addReference(new LLVMReference (intercessorName));
+               }
+       }
+}
+
+void LLVMOptimizer::reconcileOptimizedAtoms(std::vector<class ObjectFile::Atom*>& optimizedAtoms,
+                                                                                       std::vector<class ObjectFile::Atom*>& newAtoms)
+{
+       for (std::vector<ObjectFile::Atom *>::iterator itr = optimizedAtoms.begin(); 
+                itr != optimizedAtoms.end(); ++itr) {
+
+               ObjectFile::Atom* atom = *itr;
+               if (!atom->getName()) {
+                       newAtoms.push_back(atom);
+                       continue;
+               }
+
+               LLVMAtomToNameMapper::iterator pos = fLLVMSymbols.find(atom->getName());
+               if ( pos != fLLVMSymbols.end() ) {
+
+                       LLVMAtom *la = fLLVMSymbols[atom->getName()];
+                       la->setRealAtom(atom);
+
+               } 
+               else
+                       newAtoms.push_back(atom);
+       }
+}
+
+//
+// LLVM bytecode file reader
+//
+
+class LLVMReader : public ObjectFile::Reader
+{
+public:
+       static bool                                                                             validFile(const uint8_t* fileContent, const char *path, cpu_type_t architecture, Options &opts);
+       static LLVMReader*                                                              make(const uint8_t* fileContent, const char* path, time_t modTime, Options& options) 
+                                                                                                                                                       { return new LLVMReader(fileContent, path, modTime, options); }
+       virtual                                                                                 ~LLVMReader();
+       virtual std::vector<class ObjectFile::Atom*>&   getAtoms()                              { return (std::vector<class ObjectFile::Atom*>&)(fAtoms); }
+       virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) { return NULL; }
+       virtual const char*                                                             getPath()                               { return fPath; }
+       virtual time_t                                                                  getModificationTime()   { return fModTime; }
+       virtual ObjectFile::Reader::DebugInfoKind               getDebugInfoKind()              { return kDebugInfoNone; }
+       virtual std::vector<Stab>*                                              getStabs()                              { return NULL; }
+
+       ObjectFile::Atom *                                                              retriveIntercessorAtom()        { fAtoms.pop_back();return fIntercessorAtom; }
+       ObjectFile::Atom *                                                              getIntercessorAtom()    { return fIntercessorAtom; }
+
+private:
+
+                                                                                                       LLVMReader(const uint8_t* fileContent, const char* path, time_t modTime, Options& options);
+       void                                                                                    optimize(std::vector<ObjectFile::Atom*>& allAtoms, std::vector<ObjectFile::Atom*> &newAtoms, uint32_t);
+       
+       const char*                                                                             fPath;
+       time_t                                                                                  fModTime;
+       std::vector<ObjectFile::Atom*>                                  fAtoms;
+       IntercessorAtom *                                                               fIntercessorAtom;
+       static LLVMOptimizer                                                    *fOptimizer;
+       std::set<std::string>                                                   fLLVMReferences;
+};
+
+LLVMOptimizer  *LLVMReader::fOptimizer = NULL;
+
+LLVMReader::~LLVMReader()
+{
+       if (fOptimizer)
+               delete fOptimizer;
+}
+
+LLVMReader::LLVMReader (const uint8_t* fileContent, const char *path, time_t modTime, Options& options)
+{
+
+       fPath = path;
+       fModTime = modTime;
+       fIntercessorAtom = new IntercessorAtom(this, fLLVMReferences);
+       fOptimizer->read(this, path, fLLVMReferences, fAtoms, fIntercessorAtom->getName());
+       fIntercessorAtom->addReferences(fLLVMReferences);
+       fAtoms.push_back(fIntercessorAtom);
+       fOptimizer->addIntercessor(fIntercessorAtom);
+       fOptimizer->addReader(this);
+}
+
+bool LLVMReader::validFile(const uint8_t* fileContent, const char *path, cpu_type_t architecture, Options &opts)
+{
+       if (fileContent[0] == 'l'
+               && fileContent[1] == 'l'
+               && fileContent[2] == 'v'
+               && (fileContent[3] == 'c' || fileContent[3] == 'm')) {
+
+               // create optimizer
+               if (!fOptimizer)
+                       fOptimizer = new LLVMOptimizer(opts);
+
+               if (fOptimizer->validArchitecture(path, architecture))
+                       return true;
+       }
+               
+       return false;
+}
+
+void LLVMReader::optimize(std::vector<ObjectFile::Atom *> &allAtoms, std::vector<ObjectFile::Atom*> &newAtoms, uint32_t nextInputOrdinal)
+{ 
+       if (fOptimizer)  
+               fOptimizer->optimize(allAtoms, newAtoms, nextInputOrdinal);
+}
+
+#endif
+
index 5d46cbf5dbbfffc36dffbb823eeb64bbf1d4ac80..e0f5620d555629c117084e01dd6e967b09fdb1ad 100644 (file)
@@ -548,6 +548,106 @@ private:
 };
 
 
+
+
+//
+// mach-o module table entry (for compatibility with old ld/dyld)
+//
+template <typename P> struct macho_dylib_module_content {};
+template <> struct macho_dylib_module_content<Pointer32<BigEndian> >    { struct dylib_module          fields; };
+template <> struct macho_dylib_module_content<Pointer32<LittleEndian> > { struct dylib_module          fields; };
+template <> struct macho_dylib_module_content<Pointer64<BigEndian> >    { struct dylib_module_64       fields; };
+template <> struct macho_dylib_module_content<Pointer64<LittleEndian> > { struct dylib_module_64       fields; };
+
+template <typename P>
+class macho_dylib_module {
+public:
+       uint32_t                module_name() const                             INLINE { return E::get32(module.fields.module_name); }
+       void                    set_module_name(uint32_t value) INLINE { E::set32(module.fields.module_name, value);  }
+       
+       uint32_t                iextdefsym() const                              INLINE { return E::get32(module.fields.iextdefsym); }
+       void                    set_iextdefsym(uint32_t value)  INLINE { E::set32(module.fields.iextdefsym, value);  }
+       
+       uint32_t                nextdefsym() const                              INLINE { return E::get32(module.fields.nextdefsym); }
+       void                    set_nextdefsym(uint32_t value)  INLINE { E::set32(module.fields.nextdefsym, value);  }
+       
+       uint32_t                irefsym() const                                 INLINE { return E::get32(module.fields.irefsym); }
+       void                    set_irefsym(uint32_t value)             INLINE { E::set32(module.fields.irefsym, value);  }
+       
+       uint32_t                nrefsym() const                                 INLINE { return E::get32(module.fields.nrefsym); }
+       void                    set_nrefsym(uint32_t value)             INLINE { E::set32(module.fields.nrefsym, value);  }
+       
+       uint32_t                ilocalsym() const                               INLINE { return E::get32(module.fields.ilocalsym); }
+       void                    set_ilocalsym(uint32_t value)   INLINE { E::set32(module.fields.ilocalsym, value);  }
+       
+       uint32_t                nlocalsym() const                               INLINE { return E::get32(module.fields.nlocalsym); }
+       void                    set_nlocalsym(uint32_t value)   INLINE { E::set32(module.fields.nlocalsym, value);  }
+       
+       uint32_t                iextrel() const                                 INLINE { return E::get32(module.fields.iextrel); }
+       void                    set_iextrel(uint32_t value)             INLINE { E::set32(module.fields.iextrel, value);  }
+       
+       uint32_t                nextrel() const                                 INLINE { return E::get32(module.fields.nextrel); }
+       void                    set_nextrel(uint32_t value)             INLINE { E::set32(module.fields.nextrel, value);  }
+       
+       uint16_t                iinit() const                                   INLINE { return E::get32(module.fields.iinit_iterm) & 0xFFFF; }
+       uint16_t                iterm() const                                   INLINE { return E::get32(module.fields.iinit_iterm) > 16; }
+       void                    set_iinit_iterm(uint16_t init, uint16_t term)   INLINE { E::set32(module.fields.iinit_iterm, (term<<16) | (init &0xFFFF));  }
+       
+       uint16_t                ninit() const                                   INLINE { return E::get32(module.fields.ninit_nterm) & 0xFFFF; }
+       uint16_t                nterm() const                                   INLINE { return E::get32(module.fields.ninit_nterm) > 16; }
+       void                    set_ninit_nterm(uint16_t init, uint16_t term)   INLINE { E::set32(module.fields.ninit_nterm, (term<<16) | (init &0xFFFF));  }
+       
+       uint64_t                objc_module_info_addr() const                           INLINE { return P::getP(module.fields.objc_module_info_addr); }
+       void                    set_objc_module_info_addr(uint64_t value)       INLINE { P::setP(module.fields.objc_module_info_addr, value);  }
+       
+       uint32_t                objc_module_info_size() const                           INLINE { return E::get32(module.fields.objc_module_info_size); }
+       void                    set_objc_module_info_size(uint32_t value)       INLINE { E::set32(module.fields.objc_module_info_size, value);  }
+       
+       
+       typedef typename P::E           E;
+private:
+       macho_dylib_module_content<P>   module;
+};
+
+
+//
+// mach-o dylib_reference entry
+//
+template <typename P>
+class macho_dylib_reference {
+public:
+       uint32_t                isym() const                            INLINE { return E::getBits(fields, 0, 24); }
+       void                    set_isym(uint32_t value)        INLINE { E::setBits(fields, value, 0, 24); }
+       
+       uint8_t                 flags() const                           INLINE { return E::getBits(fields, 24, 8); }
+       void                    set_flags(uint8_t value)        INLINE { E::setBits(fields, value, 24, 8); }
+       
+       typedef typename P::E           E;
+private:
+       uint32_t                fields;
+};
+
+
+
+//
+// mach-o two-level hints load command
+//
+template <typename P>
+class macho_dylib_table_of_contents {
+public:
+       uint32_t                symbol_index() const                            INLINE { return E::get32(fields.symbol_index); }
+       void                    set_symbol_index(uint32_t value)        INLINE { E::set32(fields.symbol_index, value); }
+
+       uint32_t                module_index() const                            INLINE { return E::get32(fields.module_index); }
+       void                    set_module_index(uint32_t value)        INLINE { E::set32(fields.module_index, value);  }
+               
+       typedef typename P::E           E;
+private:
+       dylib_table_of_contents fields;
+};
+
+
+
 //
 // mach-o two-level hints load command
 //
@@ -603,6 +703,55 @@ private:
 };
 
 
+//
+// mach-o misc data 
+//
+template <typename P>
+class macho_linkedit_data_command {
+public:
+       uint32_t                cmd() const                                     INLINE { return E::get32(fields.cmd); }
+       void                    set_cmd(uint32_t value)         INLINE { E::set32(fields.cmd, value); }
+
+       uint32_t                cmdsize() const                         INLINE { return E::get32(fields.cmdsize); }
+       void                    set_cmdsize(uint32_t value)     INLINE { E::set32(fields.cmdsize, value); }
+
+       uint32_t                dataoff() const                         INLINE { return E::get32(fields.dataoff); }
+       void                    set_dataoff(uint32_t value)     INLINE { E::set32(fields.dataoff, value);  }
+       
+       uint32_t                datasize() const                        INLINE { return E::get32(fields.datasize); }
+       void                    set_datasize(uint32_t value)INLINE { E::set32(fields.datasize, value);  }
+       
+       
+       typedef typename P::E           E;
+private:
+       linkedit_data_command   fields;
+};
+
+
+//
+// mach-o rpath  
+//
+template <typename P>
+class macho_rpath_command {
+public:
+       uint32_t                cmd() const                                             INLINE { return E::get32(fields.cmd); }
+       void                    set_cmd(uint32_t value)                 INLINE { E::set32(fields.cmd, value); }
+
+       uint32_t                cmdsize() const                                 INLINE { return E::get32(fields.cmdsize); }
+       void                    set_cmdsize(uint32_t value)             INLINE { E::set32(fields.cmdsize, value); }
+
+       uint32_t                path_offset() const                             INLINE { return E::get32(fields.path.offset); }
+       void                    set_path_offset(uint32_t value) INLINE { E::set32(fields.path.offset, value);  }
+       
+       const char*             path() const                                    INLINE { return (const char*)&fields + path_offset(); }
+       void                    set_path_offset()                               INLINE { set_path_offset(sizeof(fields)); }
+       
+       
+       typedef typename P::E           E;
+private:
+       rpath_command   fields;
+};
+
 
 
 //
@@ -692,13 +841,16 @@ public:
        void                    set_r_type(uint8_t x)           INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 4, 4);  E::set32(other, temp); }
 
        uint32_t                r_address() const                       INLINE { return BigEndian::getBitsRaw(E::get32(other), 8, 24); }
-       void                    set_r_address(uint32_t x)       INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 8, 24);  E::set32(other, temp); }
+       void                    set_r_address(uint32_t x)                       { if ( x > 0x00FFFFFF ) throw "scattered reloc r_address too large"; 
+                                                                                                               uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 8, 24);  E::set32(other, temp); }
 
        uint32_t                r_value() const                         INLINE { return E::get32(value); }
        void                    set_r_value(uint32_t x)         INLINE { E::set32(value, x); }
 
        uint32_t                r_other() const                         INLINE { return other; }
        
+       void                    set_r_length()                          INLINE { set_r_length((sizeof(typename P::uint_t)==8) ? 3 : 2); }
+
        typedef typename P::E           E;
 private:
        uint32_t                other;
index c5c120ba5c5d5a627e6df7c056a2292c825937fe..c01a603a73fb2ce89f2e31a1b6c0cec8b9a6427a 100644 (file)
@@ -52,13 +52,13 @@ class Reader : public ObjectFile::Reader
 {
 public:
        static bool                                                                             validFile(const uint8_t* fileContent, uint64_t fileLength);
-       static Reader<A>*                                                               make(const uint8_t* fileContent, uint64_t fileLength, const char* path,
-                                                                                                               time_t modTime, const ObjectFile::ReaderOptions& options)
-                                                                                                               { return new Reader<A>(fileContent, fileLength, path, modTime, options); }
+                                                                                                       Reader(const uint8_t fileContent[], uint64_t fileLength,
+                                                                                                                       const char* path, time_t modTime, 
+                                                                                                                       const ObjectFile::ReaderOptions& options, uint32_t ordinalBase);
        virtual                                                                                 ~Reader() {}
 
        virtual const char*                                                             getPath()                       { return fPath; }
-       virtual time_t                                                                  getModificationTime(){ return 0; }
+       virtual time_t                                                                  getModificationTime(){ return fModTime; }
        virtual DebugInfoKind                                                   getDebugInfoKind()      { return ObjectFile::Reader::kDebugInfoNone; }
        virtual std::vector<class ObjectFile::Atom*>&   getAtoms();
        virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name);
@@ -89,10 +89,6 @@ private:
        typedef typename A::P                                                   P;
        typedef typename A::P::E                                                E;
 
-                                                                                                       Reader(const uint8_t fileContent[], uint64_t fileLength,
-                                                                                                                       const char* path, time_t modTime, const ObjectFile::ReaderOptions& options);
-       const struct ranlib*                                                    ranlibBinarySearch(const char* name);
-       const struct ranlib*                                                    ranlibLinearSearch(const char* name);
        const struct ranlib*                                                    ranlibHashSearch(const char* name);
        ObjectFile::Reader*                                                             makeObjectReaderForMember(const Entry* member);
        void                                                                                    dumpTableOfContents();
@@ -101,6 +97,7 @@ private:
        const char*                                                                             fPath;
        time_t                                                                                  fModTime;
        const ObjectFile::ReaderOptions&                                fOptions;
+       uint32_t                                                                                fOrdinalBase;
        const uint8_t*                                                                  fFileContent;
        uint64_t                                                                                fFileLength;
        const struct ranlib*                                                    fTableOfContents;
@@ -157,10 +154,10 @@ template <typename A>
 time_t Reader<A>::Entry::getModTime() const
 {
        char temp[14];
-       strncpy(temp, this->ar_size, 12);
+       strncpy(temp, this->ar_date, 12);
        temp[12] = '\0';
        char* endptr;
-       return (time_t)strtol(temp, &endptr, 12);
+       return (time_t)strtol(temp, &endptr, 10);
 }
 
 
@@ -220,9 +217,10 @@ bool Reader<A>::validFile(const uint8_t* fileContent, uint64_t fileLength)
 }
 
 template <typename A>
-Reader<A>::Reader(const uint8_t fileContent[], uint64_t fileLength, const char* path, time_t modTime, const ObjectFile::ReaderOptions& options)
- : fPath(NULL), fModTime(modTime), fOptions(options), fFileContent(NULL), fTableOfContents(NULL), fTableOfContentCount(0),
-   fStringPool(NULL)
+Reader<A>::Reader(const uint8_t fileContent[], uint64_t fileLength, const char* path, time_t modTime, 
+                                       const ObjectFile::ReaderOptions& options, uint32_t ordinalBase)
+ : fPath(NULL), fModTime(modTime), fOptions(options), fOrdinalBase(ordinalBase), fFileContent(NULL), 
+       fTableOfContents(NULL), fTableOfContentCount(0), fStringPool(NULL)
 {
        fPath = strdup(path);
        fFileContent = fileContent;
@@ -231,6 +229,10 @@ Reader<A>::Reader(const uint8_t fileContent[], uint64_t fileLength, const char*
        if ( strncmp((const char*)fileContent, "!<arch>\n", 8) != 0 )
                throw "not an archive";
 
+       // write out path for -whatsloaded option
+       if ( options.fLogAllFiles )
+               printf("%s\n", path);
+
        if ( !options.fFullyLoadArchives ) {
                const Entry* const firstMember = (Entry*)&fFileContent[8];
                if ( (strcmp(firstMember->getName(), SYMDEF_SORTED) == 0) || (strcmp(firstMember->getName(), SYMDEF) == 0) ) {
@@ -261,21 +263,16 @@ ObjectFile::Reader* Reader<A>::makeObjectReaderForMember(const Entry* member)
        strcat(memberPath, ")");
        //fprintf(stderr, "using %s from %s\n", memberName, fPath);
        try {
-               ObjectFile::Reader* obj = mach_o::relocatable::Reader<A>::make(member->getContent(), memberPath, fModTime, fOptions);
-               unsigned int objIndex = 0;
-               for (class std::set<const class Entry*>::iterator it=fPossibleEntries.begin(); it != fPossibleEntries.end(); it++, objIndex++) {
-                       if ( *it == member )
-                               break;
-               }
-               obj->setSortOrder((fSortOrder<<16) + objIndex);
-               //fprintf(stderr, "%s order = 0x%08X, index=%u\n", memberPath, obj->getSortOrder(), objIndex);
-               return obj;
+               // offset the ordinals in this mach-o .o file, so that atoms layout in same order as in archive
+               uint32_t ordinalBase =  fOrdinalBase + (uint8_t*)member - fFileContent;
+               return new typename mach_o::relocatable::Reader<A>::Reader(member->getContent(), memberPath, member->getModTime(), fOptions, ordinalBase);
        }
        catch (const char* msg) {
                throwf("in %s, %s", memberPath, msg);
        }
 }
 
+
 template <typename A>
 std::vector<class ObjectFile::Atom*>&  Reader<A>::getAtoms()
 {
@@ -283,18 +280,36 @@ std::vector<class ObjectFile::Atom*>&     Reader<A>::getAtoms()
                // build vector of all atoms from all .o files in this archive
                const Entry* const start = (Entry*)&fFileContent[8];
                const Entry* const end = (Entry*)&fFileContent[fFileLength];
-               unsigned int objIndex = 0;
                for (const Entry* p=start; p < end; p = p->getNext()) {
                        const char* memberName = p->getName();
                        if ( (p==start) && ((strcmp(memberName, SYMDEF_SORTED) == 0) || (strcmp(memberName, SYMDEF) == 0)) )
                                continue;
+                       if ( fOptions.fWhyLoad )
+                               printf("-all_load forced load of %s(%s)\n", this->getPath(), memberName);
                        ObjectFile::Reader* r = this->makeObjectReaderForMember(p);
-                       r->setSortOrder((fSortOrder<<16) + objIndex++);
                        std::vector<class ObjectFile::Atom*>&   atoms = r->getAtoms();
                        fAllAtoms.insert(fAllAtoms.end(), atoms.begin(), atoms.end());
                }
                return fAllAtoms;
        }
+       else if ( fOptions.fLoadAllObjcObjectsFromArchives ) {
+               // build vector of all atoms from all .o files containing objc classes in this archive
+               for(class NameToEntryMap::iterator it = fHashTable.begin(); it != fHashTable.end(); ++it) {
+                       if ( (strncmp(it->first, ".objc_c", 7) == 0) || (strncmp(it->first, "_OBJC_CLASS_$_", 14) == 0) ) {
+                               const Entry* member = (Entry*)&fFileContent[E::get32(it->second->ran_off)];
+                               if ( fInstantiatedEntries.count(member) == 0 ) {
+                                       if ( fOptions.fWhyLoad )
+                                               printf("-ObjC forced load of %s(%s)\n", this->getPath(), member->getName());
+                                       // only return these atoms once
+                                       fInstantiatedEntries.insert(member);
+                                       ObjectFile::Reader* r = makeObjectReaderForMember(member);
+                                       std::vector<class ObjectFile::Atom*>&   atoms = r->getAtoms();
+                                       fAllAtoms.insert(fAllAtoms.end(), atoms.begin(), atoms.end());
+                               }
+                       }
+               }
+               return fAllAtoms;
+       }
        else {
                // return nonthing for now, getJustInTimeAtomsFor() will return atoms as needed
                return fgEmptyList;
@@ -302,42 +317,6 @@ std::vector<class ObjectFile::Atom*>&      Reader<A>::getAtoms()
 }
 
 
-template <typename A>
-ConstRanLibPtr Reader<A>::ranlibBinarySearch(const char* key)
-{
-       const struct ranlib* base = fTableOfContents;
-       for (uint32_t n = fTableOfContentCount; n > 0; n /= 2) {
-               const struct ranlib* pivot = &base[n/2];
-               const char* pivotStr = &fStringPool[E::get32(pivot->ran_un.ran_strx)];
-               int cmp = strcmp(key, pivotStr);
-               if ( cmp == 0 )
-                       return pivot;
-               if ( cmp > 0 ) {
-                       // key > pivot
-                       // move base to symbol after pivot
-                       base = &pivot[1];
-                       --n;
-               }
-               else {
-                       // key < pivot
-                       // keep same base
-               }
-       }
-       return NULL;
-}
-
-template <typename A>
-ConstRanLibPtr Reader<A>::ranlibLinearSearch(const char* key)
-{
-       for (uint32_t i = 0; i < fTableOfContentCount; ++i) {
-               const struct ranlib* entry = &fTableOfContents[i];
-               const char* entryName = &fStringPool[E::get32(entry->ran_un.ran_strx)];
-               if ( strcmp(key, entryName) == 0 )
-                       return entry;
-       }
-       return NULL;
-}
-
 template <typename A>
 ConstRanLibPtr  Reader<A>::ranlibHashSearch(const char* name)
 {
index 055dd4fd91fc73487596a454262695520c492fd0..28d019c717265a4ac054a1b2efa89c61c9f09bf8 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -72,7 +72,7 @@ private:
 
 //
 // An ExportAtom has no content.  It exists so that the linker can track which imported
-// symbols can from which dynamic libraries.
+// symbols came from which dynamic libraries.
 //
 template <typename A>
 class ExportAtom : public ObjectFile::Atom
@@ -92,8 +92,8 @@ public:
        virtual bool                                                            mustRemainInSection() const { return false; }
        virtual const char*                                                     getSectionName() const          { return "._imports"; }
        virtual Segment&                                                        getSegment() const                      { return fgImportSegment; }
-       virtual bool                                                            requiresFollowOnAtom() const{ return false; }
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
+       virtual uint32_t                                                        getOrdinal() const                      { return fOrdinal; }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
        virtual ObjectFile::Alignment                           getAlignment() const            { return ObjectFile::Alignment(0); }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const  {}
@@ -104,12 +104,13 @@ protected:
        friend class Reader<A>;
        typedef typename A::P                                   P;
 
-                                                                                       ExportAtom(ObjectFile::Reader& owner, const char* name, bool weak)
-                                                                                               : fOwner(owner), fName(name), fWeakDefinition(weak) {}
+                                                                                       ExportAtom(ObjectFile::Reader& owner, const char* name, bool weak, uint32_t ordinal)
+                                                                                               : fOwner(owner), fName(name), fOrdinal(ordinal), fWeakDefinition(weak) {}
        virtual                                                                 ~ExportAtom() {}
 
        ObjectFile::Reader&                                             fOwner;
        const char*                                                             fName;
+       uint32_t                                                                fOrdinal;
        bool                                                                    fWeakDefinition;
 
        static std::vector<ObjectFile::Reference*>      fgEmptyReferenceList;
@@ -123,6 +124,92 @@ template <typename A>
 std::vector<ObjectFile::Reference*>    ExportAtom<A>::fgEmptyReferenceList;
 
 
+
+class ImportReference : public ObjectFile::Reference
+{
+public:
+                                                       ImportReference(const char* name)
+                                                               : fTarget(NULL), fTargetName(strdup(name))  {}
+       virtual                                 ~ImportReference() {}
+
+
+       virtual ObjectFile::Reference::TargetBinding    getTargetBinding() const        { return (fTarget==NULL) ? ObjectFile::Reference::kUnboundByName : ObjectFile::Reference::kBoundByName; }
+       virtual ObjectFile::Reference::TargetBinding    getFromTargetBinding() const{ return ObjectFile::Reference::kDontBind; }
+       virtual uint8_t                                                                 getKind() const                         { return 0; }
+       virtual uint64_t                                                                getFixUpOffset() const          { return 0; }
+       virtual const char*                                                             getTargetName() const           { return fTargetName; }
+       virtual ObjectFile::Atom&                                               getTarget() const                       { return *((ObjectFile::Atom*)fTarget); }
+       virtual uint64_t                                                                getTargetOffset() const         { return 0; }
+       virtual ObjectFile::Atom&                                               getFromTarget() const           { return *((ObjectFile::Atom*)NULL); }
+       virtual const char*                                                             getFromTargetName() const       { return NULL; }
+       virtual uint64_t                                                                getFromTargetOffset() const { return 0; }
+       virtual void                                                                    setTarget(ObjectFile::Atom& atom, uint64_t offset) { fTarget = &atom; }
+       virtual void                                                                    setFromTarget(ObjectFile::Atom&) { throw "can't set from target"; }
+       virtual const char*                                                             getDescription() const          { return "dylib import reference"; }
+
+private:
+       const ObjectFile::Atom* fTarget;
+       const char*                             fTargetName;
+};
+
+
+//
+// An ImportAtom has no content.  It exists so that when linking a main executable flat-namespace
+// the imports of all flat dylibs are checked
+//
+template <typename A>
+class ImportAtom : public ObjectFile::Atom
+{
+public:
+       virtual ObjectFile::Reader*                                     getFile() const                         { return &fOwner; }
+       virtual bool                                                            getTranslationUnitSource(const char** dir, const char** name) const { return false; }
+       virtual const char*                                                     getName() const                         { return "flat-imports"; }
+       virtual const char*                                                     getDisplayName() const          { return "flat_namespace undefines"; }
+       virtual Scope                                                           getScope() const                        { return ObjectFile::Atom::scopeTranslationUnit; }
+       virtual DefinitionKind                                          getDefinitionKind() const       { return kRegularDefinition; }
+       virtual SymbolTableInclusion                            getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
+       virtual bool                                                            dontDeadStrip() const           { return false; }
+       virtual bool                                                            isZeroFill() const                      { return false; }
+       virtual uint64_t                                                        getSize() const                         { return 0; }
+       virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
+       virtual bool                                                            mustRemainInSection() const { return false; }
+       virtual const char*                                                     getSectionName() const          { return "._imports"; }
+       virtual Segment&                                                        getSegment() const                      { return fgImportSegment; }
+       virtual ObjectFile::Atom&                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
+       virtual uint32_t                                                        getOrdinal() const                      { return fOrdinal; }
+       virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
+       virtual ObjectFile::Alignment                           getAlignment() const            { return ObjectFile::Alignment(0); }
+       virtual void                                                            copyRawContent(uint8_t buffer[]) const  {}
+
+       virtual void                                                            setScope(Scope)                         { }
+
+protected:
+       friend class Reader<A>;
+       typedef typename A::P                                   P;
+
+                                                                                       ImportAtom(ObjectFile::Reader& owner, uint32_t ordinal, std::vector<const char*>& imports)
+                                                                                               : fOwner(owner), fOrdinal(ordinal) { makeReferences(imports); }
+       virtual                                                                 ~ImportAtom() {}
+       void                                                                    makeReferences(std::vector<const char*>& imports) {
+                                                                                               for (std::vector<const char*>::iterator it=imports.begin(); it != imports.end(); ++it) {
+                                                                                                       fReferences.push_back(new ImportReference(*it));
+                                                                                               }
+                                                                                       }
+
+
+       ObjectFile::Reader&                                             fOwner;
+       uint32_t                                                                fOrdinal;
+       std::vector<ObjectFile::Reference*>             fReferences;
+       
+       static Segment                                                  fgImportSegment;
+};
+
+template <typename A>
+Segment                                                                ImportAtom<A>::fgImportSegment("__LINKEDIT");
+
+
+
+
 //
 // The reader for a dylib extracts all exported symbols names from the memory-mapped
 // dylib, builds a hash table, then unmaps the file.  This is an important memory
@@ -133,9 +220,9 @@ class Reader : public ObjectFile::Reader
 {
 public:
        static bool                                                                             validFile(const uint8_t* fileContent, bool executableOrDylib);
-       static Reader<A>*                                                               make(const uint8_t* fileContent, uint64_t fileLength, const char* path, 
-                                                                                                               bool executableOrDylib, const ObjectFile::ReaderOptions& options)
-                                                                                                               { return new Reader<A>(fileContent, fileLength, path, executableOrDylib, options); }
+                                                                                                       Reader(const uint8_t* fileContent, uint64_t fileLength, const char* path,
+                                                                                                               bool executableOrDylib, const ObjectFile::ReaderOptions& options,
+                                                                                                               uint32_t ordinalBase);
        virtual                                                                                 ~Reader() {}
 
        virtual const char*                                                             getPath()                                       { return fPath; }
@@ -144,16 +231,26 @@ public:
        virtual std::vector<class ObjectFile::Atom*>&   getAtoms();
        virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name);
        virtual std::vector<Stab>*                                              getStabs()                                      { return NULL; }
+       virtual ObjectFile::Reader::ObjcConstraint              getObjCConstraint()                     { return fObjcContraint; }
        virtual const char*                                                             getInstallPath()                        { return fDylibInstallPath; }
        virtual uint32_t                                                                getTimestamp()                          { return fDylibTimeStamp; }
        virtual uint32_t                                                                getCurrentVersion()                     { return fDylibtCurrentVersion; }
        virtual uint32_t                                                                getCompatibilityVersion()       { return fDylibCompatibilityVersion; }
-       virtual std::vector<const char*>*                               getDependentLibraryPaths();
-       virtual bool                                                                    reExports(ObjectFile::Reader*);
+       virtual void                                                                    processIndirectLibraries(DylibHander* handler);
+       virtual void                                                                    setExplicitlyLinked()           { fExplicitlyLinked = true; }
+       virtual bool                                                                    explicitlyLinked()                      { return fExplicitlyLinked; }
+       virtual bool                                                                    implicitlyLinked()                      { return fImplicitlyLinked; }
+       virtual bool                                                                    providedExportAtom()            { return fProvidedAtom; }
+       virtual const char*                                                             parentUmbrella()                        { return fParentUmbrella; }
        virtual std::vector<const char*>*                               getAllowableClients();
 
+       virtual void                                                                    setImplicitlyLinked()           { fImplicitlyLinked = true; }
+
 protected:
-               const char*                                                                     parentUmbrella()                        { return fParentUmbrella; }
+
+       struct ReExportChain { ReExportChain* prev; Reader<A>* reader; };
+
+       void                                                                                    assertNoReExportCycles(std::set<ObjectFile::Reader*>& chainedReExportReaders, ReExportChain*);
 
 private:
        typedef typename A::P                                           P;
@@ -164,14 +261,15 @@ private:
        public:
                bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
        };
-       struct AtomAndWeak { ObjectFile::Atom* atom; bool weak; };
+       struct AtomAndWeak { ObjectFile::Atom* atom; bool weak; uint32_t ordinal; };
        typedef __gnu_cxx::hash_map<const char*, AtomAndWeak, __gnu_cxx::hash<const char*>, CStringEquals> NameToAtomMap;
+       typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals>  NameSet;
        typedef typename NameToAtomMap::iterator                NameToAtomMapIterator;
 
        struct PathAndFlag { const char* path; bool reExport; };
 
-                                                                                               Reader(const uint8_t* fileContent, uint64_t fileLength, const char* path,
-                                                                                                               bool executableOrDylib, const ObjectFile::ReaderOptions& options);
+       bool                                                                            isPublicLocation(const char* path);
+       void                                                                            addSymbol(const char* name, bool weak, uint32_t ordinal);
 
        const char*                                                                     fPath;
        const char*                                                                     fParentUmbrella;
@@ -180,8 +278,21 @@ private:
        uint32_t                                                                        fDylibTimeStamp;
        uint32_t                                                                        fDylibtCurrentVersion;
        uint32_t                                                                        fDylibCompatibilityVersion;
+       uint32_t                                                                        fReExportedOrdinal;
        std::vector<PathAndFlag>                                        fDependentLibraryPaths;
        NameToAtomMap                                                           fAtoms;
+       NameSet                                                                         fIgnoreExports;
+       bool                                                                            fNoRexports;
+       const bool                                                                      fLinkingFlat;
+       const bool                                                                      fLinkingMainExecutable;
+       bool                                                                            fExplictReExportFound;
+       bool                                                                            fExplicitlyLinked;
+       bool                                                                            fImplicitlyLinked;
+       bool                                                                            fProvidedAtom;
+       ObjectFile::Reader::ObjcConstraint                      fObjcContraint;
+       std::vector<ObjectFile::Reader*>                        fReExportedChildren;
+       const ObjectFile::ReaderOptions::VersionMin     fDeploymentVersionMin;
+       std::vector<class ObjectFile::Atom*>            fFlatImports;
 
        static bool                                                                     fgLogHashtable;
        static std::vector<class ObjectFile::Atom*>     fgEmptyAtomList;
@@ -194,8 +305,13 @@ bool                                                                       Reader<A>::fgLogHashtable = false;
 
 
 template <typename A>
-Reader<A>::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* path, bool executableOrDylib, const ObjectFile::ReaderOptions& options)
-       : fParentUmbrella(NULL), fDylibInstallPath(NULL), fDylibTimeStamp(0), fDylibtCurrentVersion(0), fDylibCompatibilityVersion(0)
+Reader<A>::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* path, bool executableOrDylib, 
+               const ObjectFile::ReaderOptions& options, uint32_t ordinalBase)
+       : fParentUmbrella(NULL), fDylibInstallPath(NULL), fDylibTimeStamp(0), fDylibtCurrentVersion(0), 
+       fDylibCompatibilityVersion(0), fLinkingFlat(options.fFlatNamespace), 
+       fLinkingMainExecutable(options.fLinkingMainExecutable), fExplictReExportFound(false), 
+       fExplicitlyLinked(false), fImplicitlyLinked(false), fProvidedAtom(false), fObjcContraint(ObjectFile::Reader::kObjcNone),
+       fDeploymentVersionMin(options.fVersionMin)
 {
        // sanity check
        if ( ! validFile(fileContent, executableOrDylib) )
@@ -207,6 +323,16 @@ Reader<A>::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* p
        const uint32_t cmd_count = header->ncmds();
        const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
 
+       // write out path for -whatsloaded option
+       if ( options.fLogAllFiles )
+               printf("%s\n", path);
+
+       if ( options.fRootSafe && ((header->flags() & MH_ROOT_SAFE) == 0) )
+               fprintf(stderr, "ld: warning using -root_safe but linking against %s which is not root safe\n", path);
+
+       if ( options.fSetuidSafe && ((header->flags() & MH_SETUID_SAFE) == 0) )
+               fprintf(stderr, "ld: warning using -setuid_safe but linking against %s which is not setuid safe\n", path);
+
        // a "blank" stub has zero load commands
        if ( (header->filetype() == MH_DYLIB_STUB) && (cmd_count == 0) ) {      
                // no further processing needed
@@ -214,21 +340,31 @@ Reader<A>::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* p
                return;
        }
 
+
+       // optimize the case where we know there is no reason to look at indirect dylibs
+       fNoRexports = (header->flags() & MH_NO_REEXPORTED_DYLIBS);
+       bool trackDependentLibraries = !fNoRexports || options.fFlatNamespace;
+       
        // pass 1 builds list of all dependent libraries
        const macho_load_command<P>* cmd = cmds;
-       for (uint32_t i = 0; i < cmd_count; ++i) {
-               switch (cmd->cmd()) {
-                       case LC_LOAD_DYLIB:
-                       case LC_LOAD_WEAK_DYLIB:
-                               PathAndFlag entry;
-                               entry.path = strdup(((struct macho_dylib_command<P>*)cmd)->name());
-                               entry.reExport = false;
-                               fDependentLibraryPaths.push_back(entry);
-                               break;
+       if ( trackDependentLibraries ) {
+               for (uint32_t i = 0; i < cmd_count; ++i) {
+                       switch (cmd->cmd()) {
+                               case LC_REEXPORT_DYLIB:
+                                       fExplictReExportFound = true;
+                                       // fall into next case
+                               case LC_LOAD_DYLIB:
+                               case LC_LOAD_WEAK_DYLIB:
+                                       PathAndFlag entry;
+                                       entry.path = strdup(((struct macho_dylib_command<P>*)cmd)->name());
+                                       entry.reExport = (cmd->cmd() == LC_REEXPORT_DYLIB);
+                                       fDependentLibraryPaths.push_back(entry);
+                                       break;
+                       }
+                       cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
                }
-               cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
        }
-
+       
        // pass 2 determines re-export info
        const macho_dysymtab_command<P>* dynamicInfo = NULL;
        const macho_nlist<P>* symbolTable = NULL;
@@ -247,14 +383,16 @@ Reader<A>::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* p
                                dynamicInfo = (macho_dysymtab_command<P>*)cmd;
                                break;
                        case LC_ID_DYLIB:
+                               {
                                macho_dylib_command<P>* dylibID = (macho_dylib_command<P>*)cmd;
                                fDylibInstallPath                       = strdup(dylibID->name());
                                fDylibTimeStamp                         = dylibID->timestamp();
                                fDylibtCurrentVersion           = dylibID->current_version();
                                fDylibCompatibilityVersion      = dylibID->compatibility_version();
+                               }
                                break;
                        case LC_SUB_UMBRELLA:
-                               if ( !options.fFlatNamespace ) {
+                               if ( trackDependentLibraries ) {
                                        const char* frameworkLeafName = ((macho_sub_umbrella_command<P>*)cmd)->sub_umbrella();
                                        for (typename std::vector<PathAndFlag>::iterator it = fDependentLibraryPaths.begin(); it != fDependentLibraryPaths.end(); it++) {
                                                const char* dylibName = it->path;
@@ -265,7 +403,7 @@ Reader<A>::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* p
                                }
                                break;
                        case LC_SUB_LIBRARY:
-                               if ( !options.fFlatNamespace ) {
+                               if ( trackDependentLibraries) {
                                        const char* dylibBaseName = ((macho_sub_library_command<P>*)cmd)->sub_library();
                                        for (typename std::vector<PathAndFlag>::iterator it = fDependentLibraryPaths.begin(); it != fDependentLibraryPaths.end(); it++) {
                                                const char* dylibName = it->path;
@@ -285,21 +423,51 @@ Reader<A>::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* p
                        case LC_SUB_FRAMEWORK:
                                fParentUmbrella = strdup(((macho_sub_framework_command<P>*)cmd)->umbrella());
                                break;
+                       case macho_segment_command<P>::CMD:
+                               // check for Objective-C info
+                               if ( strcmp(((macho_segment_command<P>*)cmd)->segname(), "__OBJC") == 0 ) {
+                                       const macho_segment_command<P>* segment = (macho_segment_command<P>*)cmd;
+                                       const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
+                                       const macho_section<P>* const sectionsEnd = &sectionsStart[segment->nsects()];
+                                       for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                                       if ( strcmp(sect->sectname(), "__image_info") == 0 ) {
+                                                       //      struct objc_image_info  {
+                                                       //              uint32_t        version;        // initially 0
+                                                       //              uint32_t        flags;
+                                                       //      };
+                                                       // #define OBJC_IMAGE_SUPPORTS_GC   2
+                                                       // #define OBJC_IMAGE_GC_ONLY       4
+                                                       //
+                                                       const uint32_t* contents = (uint32_t*)(&fileContent[sect->offset()]);
+                                                       if ( (sect->size() >= 8) && (contents[0] == 0) ) {
+                                                               uint32_t flags = E::get32(contents[1]);
+                                                               if ( (flags & 4) == 4 )
+                                                                       fObjcContraint = ObjectFile::Reader::kObjcGC;
+                                                               else if ( (flags & 2) == 2 )
+                                                                       fObjcContraint = ObjectFile::Reader::kObjcRetainReleaseOrGC;
+                                                               else
+                                                                       fObjcContraint = ObjectFile::Reader::kObjcRetainRelease;
+                                                       }
+                                                       else if ( sect->size() > 0 ) {
+                                                               fprintf(stderr, "ld: warning, can't parse __OBJC/__image_info section in %s\n", fPath);
+                                                       }
+                                               }
+                                       }
+                               }
                }
 
                cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
        }
+       
        // Process the rest of the commands here.
        cmd = cmds;
        for (uint32_t i = 0; i < cmd_count; ++i) {
                switch (cmd->cmd()) {
                case LC_SUB_CLIENT:
                        const char *temp = strdup(((macho_sub_client_command<P>*)cmd)->client());
-
                        fAllowableClients.push_back(temp);
                        break;
                }
-
                cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
        }
 
@@ -311,48 +479,127 @@ Reader<A>::Reader(const uint8_t* fileContent, uint64_t fileLength, const char* p
        if ( dynamicInfo == NULL )
                throw "dylib missing LC_DYSYMTAB load command";
        
+       // if linking flat and this is a flat dylib, create one atom that references all imported symbols
+       if ( fLinkingFlat && fLinkingMainExecutable && ((header->flags() & MH_TWOLEVEL) == 0) ) {
+               std::vector<const char*> importNames;
+               importNames.reserve(dynamicInfo->nundefsym());
+               const macho_nlist<P>* start = &symbolTable[dynamicInfo->iundefsym()];
+               const macho_nlist<P>* end = &start[dynamicInfo->nundefsym()];
+               for (const macho_nlist<P>* sym=start; sym < end; ++sym) {
+                       importNames.push_back(&strings[sym->n_strx()]);
+               }
+               fFlatImports.push_back(new ImportAtom<A>(*this, ordinalBase++, importNames));
+       }
+
        // build hash table
        if ( dynamicInfo->tocoff() == 0 ) {
-               if ( fgLogHashtable ) fprintf(stderr, "ld64: building hashtable of %u toc entries for %s\n", dynamicInfo->nextdefsym(), path);
+               if ( fgLogHashtable ) fprintf(stderr, "ld: building hashtable of %u toc entries for %s\n", dynamicInfo->nextdefsym(), path);
                const macho_nlist<P>* start = &symbolTable[dynamicInfo->iextdefsym()];
                const macho_nlist<P>* end = &start[dynamicInfo->nextdefsym()];
                fAtoms.resize(dynamicInfo->nextdefsym()); // set initial bucket count
-               for (const macho_nlist<P>* sym=start; sym < end; ++sym) {
-                       AtomAndWeak bucket;
-                       bucket.atom = NULL;
-                       bucket.weak = ((sym->n_desc() & N_WEAK_DEF) != 0);
-                       const char* name = strdup(&strings[sym->n_strx()]);
-                       if ( fgLogHashtable ) fprintf(stderr, "  adding %s to hash table for %s\n", name, this->getPath());
-                       fAtoms[name] = bucket;
+               uint32_t index = ordinalBase;
+               for (const macho_nlist<P>* sym=start; sym < end; ++sym, ++index) {
+                       this->addSymbol(&strings[sym->n_strx()], (sym->n_desc() & N_WEAK_DEF) != 0, index);
                }
+               fReExportedOrdinal = index;
        }
        else {
                int32_t count = dynamicInfo->ntoc();
                fAtoms.resize(count); // set initial bucket count
-               if ( fgLogHashtable ) fprintf(stderr, "ld64: building hashtable of %u entries for %s\n", count, path);
+               if ( fgLogHashtable ) fprintf(stderr, "ld: building hashtable of %u entries for %s\n", count, path);
                const struct dylib_table_of_contents* toc = (dylib_table_of_contents*)((char*)header + dynamicInfo->tocoff());
                for (int32_t i = 0; i < count; ++i) {
                        const uint32_t index = E::get32(toc[i].symbol_index);
                        const macho_nlist<P>* sym = &symbolTable[index];
-                       AtomAndWeak bucket;
-                       bucket.atom = NULL;
-                       bucket.weak = ((sym->n_desc() & N_WEAK_DEF) != 0);
-                       const char* name = strdup(&strings[sym->n_strx()]);
-                       if ( fgLogHashtable ) fprintf(stderr, "  adding %s to hash table for %s\n", name, this->getPath());
-                       fAtoms[name] = bucket;
+                       this->addSymbol(&strings[sym->n_strx()], (sym->n_desc() & N_WEAK_DEF) != 0, ordinalBase+i);
                }
+               fReExportedOrdinal = ordinalBase + count;
        }
 
+       
        // unmap file
        munmap((caddr_t)fileContent, fileLength);
 }
 
+
+
+template <typename A>
+void Reader<A>::addSymbol(const char* name, bool weak, uint32_t ordinal)
+{
+       // symbols that start with $ld$ are meta-data to the static linker
+       // <rdar://problem/5182537> need way for ld and dyld to see different exported symbols in a dylib
+       if ( strncmp(name, "$ld$", 4) == 0 ) {  
+               //    $ld$ <action> $ <condition> $ <symbol-name>
+               const char* symAction = &name[4];
+               const char* symCond = strchr(symAction, '$');
+               if ( symCond != NULL ) {
+                       ObjectFile::ReaderOptions::VersionMin symVersionCondition = ObjectFile::ReaderOptions::kMinUnset;
+                       if ( (strncmp(symCond, "$os10.", 6) == 0) && isdigit(symCond[6]) && (symCond[7] == '$') ) {
+                               switch ( symCond[6] - '0' ) {
+                                       case 0:
+                                       case 1:
+                                               symVersionCondition = ObjectFile::ReaderOptions::k10_1;
+                                               break;
+                                       case 2:
+                                               symVersionCondition = ObjectFile::ReaderOptions::k10_2;
+                                               break;
+                                       case 3:
+                                               symVersionCondition = ObjectFile::ReaderOptions::k10_3;
+                                               break;
+                                       case 4:
+                                               symVersionCondition = ObjectFile::ReaderOptions::k10_4;
+                                               break;
+                                       case 5:
+                                               symVersionCondition = ObjectFile::ReaderOptions::k10_5;
+                                               break;
+                               }
+                               const char* symName = strchr(&symCond[1], '$');
+                               if ( symName != NULL ) {
+                                       ++symName;
+                                       if ( fDeploymentVersionMin == symVersionCondition ) {
+                                               if ( strncmp(symAction, "hide$", 5) == 0 ) {
+                                                       if ( fgLogHashtable ) fprintf(stderr, "  adding %s to ignore set for %s\n", symName, this->getPath());
+                                                       fIgnoreExports.insert(strdup(symName));
+                                                       return;
+                                               }
+                                               else if ( strncmp(symAction, "add$", 4) == 0 ) {
+                                                       this->addSymbol(symName, weak, ordinal);
+                                                       return;
+                                               }
+                                               else {
+                                                       fprintf(stderr, "ld: warning bad symbol action: %s in dylib %s\n", name, this->getPath());
+                                               }
+                                       }
+                               }
+                               else {
+                                       fprintf(stderr, "ld: warning bad symbol name: %s in dylib %s\n", name, this->getPath());
+                               }
+                       }
+                       else {
+                               fprintf(stderr, "ld: warning bad symbol version: %s in dylib %s\n", name, this->getPath());
+                       }
+               }       
+               else {
+                       fprintf(stderr, "ld: warning bad symbol condition: %s in dylib %s\n", name, this->getPath());
+               }
+       }
+       
+       // add symbol as possible export if we are not supposed to ignore it
+       if ( fIgnoreExports.count(name) == 0 ) {
+               AtomAndWeak bucket;
+               bucket.atom = NULL;
+               bucket.weak = weak;
+               bucket.ordinal = ordinal;
+               if ( fgLogHashtable ) fprintf(stderr, "  adding %s to hash table for %s\n", name, this->getPath());
+               fAtoms[strdup(name)] = bucket;
+       }
+}
+
+
 template <typename A>
 std::vector<class ObjectFile::Atom*>& Reader<A>::getAtoms()
 {
-       // TO DO:       for flat-namespace libraries, when linking flat_namespace
-       //                      we need to create an atom which references all undefines
-       return fgEmptyAtomList;
+       return fFlatImports;
 }
 
 
@@ -360,12 +607,13 @@ template <typename A>
 std::vector<class ObjectFile::Atom*>* Reader<A>::getJustInTimeAtomsFor(const char* name)
 {
        std::vector<class ObjectFile::Atom*>* atoms = NULL;
-
+       
        NameToAtomMapIterator pos = fAtoms.find(name);
        if ( pos != fAtoms.end() ) {
                if ( pos->second.atom == NULL ) {
                        // instantiate atom and update hash table
-                       pos->second.atom = new ExportAtom<A>(*this, name, pos->second.weak);
+                       pos->second.atom = new ExportAtom<A>(*this, name, pos->second.weak, pos->second.ordinal);
+                       fProvidedAtom = true;
                        if ( fgLogHashtable ) fprintf(stderr, "getJustInTimeAtomsFor: %s found in %s\n", name, this->getPath());
                }
                // return a vector of one atom
@@ -374,6 +622,25 @@ std::vector<class ObjectFile::Atom*>* Reader<A>::getJustInTimeAtomsFor(const cha
        }
        else {
                if ( fgLogHashtable ) fprintf(stderr, "getJustInTimeAtomsFor: %s NOT found in %s\n", name, this->getPath());
+                       // if not supposed to ignore this export, see if I have it
+               if ( fIgnoreExports.count(name) == 0 ) {
+                       // look in children that I re-export
+                       for (std::vector<ObjectFile::Reader*>::iterator it = fReExportedChildren.begin(); it != fReExportedChildren.end(); it++) {
+                               //fprintf(stderr, "getJustInTimeAtomsFor: %s NOT found in %s, looking in child %s\n", name, this->getPath(), (*it)->getInstallPath());
+                               std::vector<class ObjectFile::Atom*>* childAtoms = (*it)->getJustInTimeAtomsFor(name);
+                               if ( childAtoms != NULL ) {
+                                       // make a new atom that says this reader is the owner 
+                                       bool isWeakDef = (childAtoms->at(0)->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition);
+                                       // return a vector of one atom
+                                       ExportAtom<A>* newAtom = new ExportAtom<A>(*this, name, isWeakDef, fReExportedOrdinal++);
+                                       fProvidedAtom = true;
+                                       atoms = new std::vector<class ObjectFile::Atom*>;
+                                       atoms->push_back(newAtom);
+                                       delete childAtoms;
+                                       return atoms;
+                               }
+                       }
+               }
        }
        return atoms;
 }
@@ -381,48 +648,119 @@ std::vector<class ObjectFile::Atom*>* Reader<A>::getJustInTimeAtomsFor(const cha
 
 
 template <typename A>
-std::vector<const char*>* Reader<A>::getDependentLibraryPaths()
+bool Reader<A>::isPublicLocation(const char* path)
 {
-       std::vector<const char*>* result = new std::vector<const char*>;
-       for (typename std::vector<PathAndFlag>::iterator it = fDependentLibraryPaths.begin(); it != fDependentLibraryPaths.end(); it++) {
-               result->push_back(it->path);
+       // /usr/lib is a public location
+       if ( (strncmp(path, "/usr/lib/", 9) == 0) && (strchr(&path[9], '/') == NULL) )
+               return true;
+
+       // /System/Library/Frameworks/ is a public location
+       if ( strncmp(path, "/System/Library/Frameworks/", 27) == 0 ) {
+               const char* frameworkDot = strchr(&path[27], '.');
+               // but only top level framework
+               // /System/Library/Frameworks/Foo.framework/Versions/A/Foo                 ==> true
+               // /System/Library/Frameworks/Foo.framework/Resources/libBar.dylib         ==> false
+               // /System/Library/Frameworks/Foo.framework/Frameworks/Bar.framework/Bar   ==> false
+               // /System/Library/Frameworks/Foo.framework/Frameworks/Xfoo.framework/XFoo ==> false
+               if ( frameworkDot != NULL ) {
+                       int frameworkNameLen = frameworkDot - &path[27];
+                       if ( strncmp(&path[strlen(path)-frameworkNameLen-1], &path[26], frameworkNameLen+1) == 0 )
+                               return true;
+               }
        }
-       return result;
+               
+       return false;
 }
 
 template <typename A>
-std::vector<const char*>* Reader<A>::getAllowableClients()
+void Reader<A>::processIndirectLibraries(DylibHander* handler)
 {
-       std::vector<const char*>* result = new std::vector<const char*>;
-       for (typename std::vector<const char*>::iterator it = fAllowableClients.begin();
-                it != fAllowableClients.end();
-                it++) {
-               result->push_back(*it);
+       if ( fLinkingFlat ) {
+               for (typename std::vector<PathAndFlag>::iterator it = fDependentLibraryPaths.begin(); it != fDependentLibraryPaths.end(); it++) {
+                       handler->findDylib(it->path, this->getPath());
+               }
        }
-       return (fAllowableClients.size() != 0 ? result : NULL);
+       else if ( fNoRexports ) {
+               // MH_NO_REEXPORTED_DYLIBS bit set, then nothing to do
+       }
+       else {
+               // two-level, might have re-exports
+               for (typename std::vector<PathAndFlag>::iterator it = fDependentLibraryPaths.begin(); it != fDependentLibraryPaths.end(); it++) {
+                       if ( it->reExport ) {
+                               //fprintf(stderr, "processIndirectLibraries() parent=%s, child=%s\n", this->getInstallPath(), it->path);
+                               // a LC_REEXPORT_DYLIB, LC_SUB_UMBRELLA or LC_SUB_LIBRARY says we re-export this child
+                               ObjectFile::Reader* child = handler->findDylib(it->path, this->getPath());
+                               if ( isPublicLocation(child->getInstallPath()) ) {
+                                       // promote this child to be automatically added as a direct dependent if this already is
+                                       if ( this->explicitlyLinked() || this->implicitlyLinked() ) {
+                                               //fprintf(stderr, "processIndirectLibraries() implicitly linking %s\n", child->getInstallPath());
+                                               ((Reader<A>*)child)->setImplicitlyLinked();
+                                       }
+                                       else
+                                               fReExportedChildren.push_back(child);
+                               }
+                               else {
+                                       // add all child's symbols to me
+                                       fReExportedChildren.push_back(child);
+                                       //fprintf(stderr, "processIndirectLibraries() parent=%s will re-export child=%s\n", this->getInstallPath(), it->path);
+                               }
+                       }
+                       else if ( !fExplictReExportFound ) {
+                               // see if child contains LC_SUB_FRAMEWORK with my name
+                               ObjectFile::Reader* child = handler->findDylib(it->path, this->getPath());
+                               const char* parentUmbrellaName = ((Reader<A>*)child)->parentUmbrella();
+                               if ( parentUmbrellaName != NULL ) {
+                                       const char* parentName = this->getPath();
+                                       const char* lastSlash = strrchr(parentName, '/');
+                                       if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], parentUmbrellaName) == 0) ) {
+                                               // add all child's symbols to me
+                                               fReExportedChildren.push_back(child);
+                                               //fprintf(stderr, "processIndirectLibraries() umbrella=%s will re-export child=%s\n", this->getInstallPath(), it->path);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       // check for re-export cycles
+       std::set<ObjectFile::Reader*> chainedReExportReaders;
+       ReExportChain chain;
+       chain.prev = NULL;
+       chain.reader = this;
+       this->assertNoReExportCycles(chainedReExportReaders, &chain);
 }
 
 template <typename A>
-bool Reader<A>::reExports(ObjectFile::Reader* child)
+void Reader<A>::assertNoReExportCycles(std::set<ObjectFile::Reader*>& chainedReExportReaders, ReExportChain* prev)
 {
-       // A dependent dylib is re-exported under two conditions:
-       //  1) parent contains LC_SUB_UMBRELLA or LC_SUB_LIBRARY with child name
-       const char* childInstallPath = child->getInstallPath();
-       for (typename std::vector<PathAndFlag>::iterator it = fDependentLibraryPaths.begin(); it != fDependentLibraryPaths.end(); it++) {
-               if ( it->reExport && ((strcmp(it->path, child->getPath()) == 0) || ((childInstallPath!=NULL) && (strcmp(it->path, childInstallPath)==0))) )
-                       return true;
+       // check none of my re-exported dylibs are already in set
+       for (std::vector<ObjectFile::Reader*>::iterator it = fReExportedChildren.begin(); it != fReExportedChildren.end(); it++) {
+               if ( chainedReExportReaders.count(*it) != 0 ) {
+                       // we may want to print out the chain of dylibs causing the cylce...
+                       throwf("cycle in dylib re-exports with %s", this->getPath());
+               }
        }
-
-       //  2) child contains LC_SUB_FRAMEWORK with parent name
-       const char* parentUmbrellaName = ((Reader<A>*)child)->parentUmbrella();
-       if ( parentUmbrellaName != NULL ) {
-               const char* parentName = this->getPath();
-               const char* lastSlash = strrchr(parentName, '/');
-               if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], parentUmbrellaName) == 0) )
-                       return true;
+       // recursively check my re-exportted dylibs
+       chainedReExportReaders.insert(this);
+       ReExportChain chain;
+       chain.prev = prev;
+       chain.reader = this;
+       for (std::vector<ObjectFile::Reader*>::iterator it = fReExportedChildren.begin(); it != fReExportedChildren.end(); it++) {
+               ((Reader<A>*)(*it))->assertNoReExportCycles(chainedReExportReaders, &chain);
        }
+}
 
-       return false;
+
+template <typename A>
+std::vector<const char*>* Reader<A>::getAllowableClients()
+{
+       std::vector<const char*>* result = new std::vector<const char*>;
+       for (typename std::vector<const char*>::iterator it = fAllowableClients.begin();
+                it != fAllowableClients.end();
+                it++) {
+               result->push_back(*it);
+       }
+       return (fAllowableClients.size() != 0 ? result : NULL);
 }
 
 template <>
index 310b5617c2896fb37f5943ad3c83909daa0fed31..7f20ae331353eb312d979f7c5c85d011719645f8 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -78,7 +78,6 @@ public:
 
 // forward reference
 template <typename A> class Reader;
-template <typename A> class SymbolAtomSorter;
 
 struct AtomAndOffset
 {
@@ -104,14 +103,13 @@ public:
        virtual                                 ~Reference() {}
 
 
-       virtual bool                    isTargetUnbound() const                                                 { return ( fToTarget.atom == NULL ); }
-       virtual bool                    isFromTargetUnbound() const                                             { return ( fFromTarget.atom == NULL ); }
+       virtual ObjectFile::Reference::TargetBinding    getTargetBinding() const;
+       virtual ObjectFile::Reference::TargetBinding    getFromTargetBinding() const;
        virtual uint8_t                 getKind() const                                                                 { return (uint8_t)fKind; }
        virtual uint64_t                getFixUpOffset() const                                                  { return fFixUpOffsetInSrc; }
        virtual const char*             getTargetName() const                                                   { return (fToTargetName != NULL) ? fToTargetName : fToTarget.atom->getName(); }
        virtual ObjectFile::Atom& getTarget() const                                                             { return *fToTarget.atom; }
        virtual uint64_t                getTargetOffset() const                                                 { return (int64_t)((int32_t)fToTarget.offset); }
-       virtual bool                    hasFromTarget() const                                                   { return ( (fFromTarget.atom != NULL) || (fFromTargetName != NULL) ); }
        virtual ObjectFile::Atom& getFromTarget() const                                                 { return *fFromTarget.atom; }
        virtual const char*             getFromTargetName() const                                               { return (fFromTargetName != NULL) ? fFromTargetName : fFromTarget.atom->getName(); }
        virtual void                    setTarget(ObjectFile::Atom& target, uint64_t offset)    { fToTarget.atom = &target; fToTarget.offset = offset; }
@@ -122,6 +120,7 @@ public:
        virtual const char*             getDescription() const;
        virtual uint64_t                getFromTargetOffset() const                                             { return fFromTarget.offset; }
 
+       static bool                             fgForFinalLinkedImage;
 
 private:
        pint_t                                  fFixUpOffsetInSrc;
@@ -130,8 +129,10 @@ private:
        const char*                             fToTargetName;
        const char*                             fFromTargetName;
        Kinds                                   fKind;
+       
 };
 
+template <typename A> bool Reference<A>::fgForFinalLinkedImage = true;
 
 template <typename A>
 Reference<A>::Reference(Kinds kind, const AtomAndOffset& at, const AtomAndOffset& toTarget)
@@ -141,10 +142,12 @@ Reference<A>::Reference(Kinds kind, const AtomAndOffset& at, const AtomAndOffset
        // make reference a by-name unless:
        // - the reference type is only used with direct references
        // - the target is translation unit scoped
+       // - the target kind is not regular (is weak or tentative)
        if ( (kind != A::kNoFixUp) && (kind != A::kFollowOn) 
-               && (toTarget.atom->getScope() != ObjectFile::Atom::scopeTranslationUnit) ) {
-               //fprintf(stderr, "Reference(): changing to by-name %p %s, target scope=%d\n", toTarget.atom, fToTargetName, toTarget.atom->getScope());
+               && (toTarget.atom->getScope() != ObjectFile::Atom::scopeTranslationUnit) 
+               && (toTarget.atom->getDefinitionKind() != ObjectFile::Atom::kRegularDefinition) ) {
                fToTargetName = toTarget.atom->getName();
+               //fprintf(stderr, "Reference(): changing to by-name %p %s, target scope=%d, target section=%s\n", toTarget.atom, fToTargetName, toTarget.atom->getScope(), toTarget.atom->getSectionName());
                fToTarget.atom = NULL;
        }
        ((class BaseAtom*)at.atom)->addReference(this);
@@ -159,6 +162,7 @@ Reference<A>::Reference(Kinds kind, const AtomAndOffset& at, const AtomAndOffset
        // make reference a by-name where needed
        if ( (kind != A::kNoFixUp) && (kind != A::kFollowOn) 
                && (toTarget.atom->getScope() != ObjectFile::Atom::scopeTranslationUnit)
+               && (toTarget.atom->getDefinitionKind() != ObjectFile::Atom::kRegularDefinition) 
                && (toTarget.atom != at.atom) ) {
                        fToTargetName = toTarget.atom->getName();
                        fToTarget.atom = NULL;
@@ -177,6 +181,39 @@ Reference<A>::Reference(Kinds kind, const AtomAndOffset& at, const char* toName,
        ((class BaseAtom*)at.atom)->addReference(this);
 }
 
+template <typename A>
+ObjectFile::Reference::TargetBinding Reference<A>::getTargetBinding() const
+{
+       if ( fgForFinalLinkedImage ) {
+               if ( (fKind == A::kDtraceProbe) || (fKind == A::kDtraceProbeSite) || (fKind == A::kDtraceIsEnabledSite) || (fKind == A::kDtraceTypeReference) )
+                       return ObjectFile::Reference::kDontBind;
+       }
+       if ( fToTarget.atom == NULL ) 
+               return ObjectFile::Reference::kUnboundByName;
+       if ( fToTargetName == NULL ) 
+               return ObjectFile::Reference::kBoundDirectly;
+       else
+               return ObjectFile::Reference::kBoundByName;
+}
+
+template <typename A>
+ObjectFile::Reference::TargetBinding Reference<A>::getFromTargetBinding() const
+{
+       if ( fFromTarget.atom == NULL ) {
+               if ( fFromTargetName == NULL ) 
+                       return ObjectFile::Reference::kDontBind;
+               else
+                       return ObjectFile::Reference::kUnboundByName;
+       }
+       else {
+               if ( fFromTargetName == NULL ) 
+                       return ObjectFile::Reference::kBoundDirectly;
+               else
+                       return ObjectFile::Reference::kBoundByName;
+       }
+}
+
+
 
 template <typename A>
 class Segment : public ObjectFile::Segment
@@ -221,6 +258,18 @@ public:
 
 DataSegment DataSegment::fgSingleton;
 
+class LinkEditSegment : public ObjectFile::Segment
+{
+public:
+       virtual const char*                     getName() const                                         { return "__LINKEDIT"; }
+       virtual bool                            isContentReadable() const                       { return true; }
+       virtual bool                            isContentWritable() const                       { return false; }
+       virtual bool                            isContentExecutable() const                     { return false; }
+
+       static LinkEditSegment                  fgSingleton;
+};
+
+LinkEditSegment LinkEditSegment::fgSingleton;
 
 class BaseAtom : public ObjectFile::Atom
 {
@@ -231,9 +280,76 @@ public:
        virtual void                                                            addReference(ObjectFile::Reference* ref) = 0;
        virtual void                                                            sortReferences() = 0;
        virtual void                                                            addLineInfo(const ObjectFile::LineInfo& info) = 0;
+       virtual uint64_t                                                        getObjectAddress() const = 0;
+       virtual uint32_t                                                        getOrdinal() const { return fOrdinal; }
+       virtual void                                                            setOrdinal(uint32_t value) { fOrdinal = value; }
+       virtual const void*                                                     getSectionRecord() const = 0;
+       virtual bool                                                            isAlias() const { return false; }
 
        uint32_t                                                                        fStabsStartIndex;
        uint32_t                                                                        fStabsCount;
+       uint32_t                                                                        fOrdinal;
+};
+
+class BaseAtomSorter
+{
+public:
+       bool operator()(const class BaseAtom* left, const class BaseAtom* right)  {
+               if ( left == right )
+                       return false;
+               uint64_t leftAddr  =  left->getObjectAddress();
+               uint64_t rightAddr = right->getObjectAddress();
+               if ( leftAddr < rightAddr ) {
+                       return true;
+               }
+               else if ( leftAddr > rightAddr ) {
+                       return false;
+               }
+               else {
+                       // if they have same address, one might be the end of a section and the other the start of the next section
+                       const void* leftSection  =  left->getSectionRecord();
+                       const void* rightSection =  right->getSectionRecord();
+                       if ( leftSection != rightSection ) {
+                               return ( leftSection < rightSection );
+                       }
+                       // if they have same address and section, one might be an alias
+                       bool leftAlias  = left->isAlias();
+                       bool rightAlias = right->isAlias();
+                       if ( leftAlias && rightAlias ) {
+                               // sort multiple aliases for same address first by scope
+                               ObjectFile::Atom::Scope leftScope  = left->getScope();
+                               ObjectFile::Atom::Scope rightScope = right->getScope();
+                               if ( leftScope != rightScope ) {
+                                       return ( leftScope < rightScope );
+                               }
+                               // sort multiple aliases for same address then by name
+                               return ( strcmp(left->getName(), right->getName()) < 0 );
+                       }
+                       else if ( leftAlias ) {
+                               return true;
+                       }
+                       else if ( rightAlias ) {
+                               return false;
+                       }
+                       else {
+                               // they must be tentative defintions
+                               switch ( left->getDefinitionKind() ) {
+                                       case ObjectFile::Atom::kTentativeDefinition:
+                                               // sort tentative definitions by name
+                                               return ( strcmp(left->getName(), right->getName()) < 0 );
+                                       case ObjectFile::Atom::kAbsoluteSymbol:
+                                               // sort absolute symbols with same address by name
+                                               return ( strcmp(left->getName(), right->getName()) < 0 );
+                                       default:
+                                               // hack for rdar://problem/5102873
+                                               if ( !left->isZeroFill() || !right->isZeroFill() )
+                                                       fprintf(stderr, "ld: atom sorting error for %s and %s in %s\n", left->getDisplayName(), right->getDisplayName(), left->getFile()->getPath());
+                                               break;
+                               }
+                       }
+               }
+               return false;
+       }
 };
 
 
@@ -255,23 +371,24 @@ public:
        virtual ObjectFile::Atom::DefinitionKind        getDefinitionKind() const               { return ((fSymbol->n_desc() & N_WEAK_DEF) != 0)
                                                                                                                                                                                ? ObjectFile::Atom::kWeakDefinition : ObjectFile::Atom::kRegularDefinition; }
        virtual SymbolTableInclusion                            getSymbolTableInclusion() const { return fSymbolTableInclusion; }
-       virtual bool                                                            dontDeadStrip() const                   { return ((fSymbol->n_desc() & (N_NO_DEAD_STRIP|REFERENCED_DYNAMICALLY)) != 0); }
+       virtual bool                                                            dontDeadStrip() const;
        virtual bool                                                            isZeroFill() const                              { return ((fSection->flags() & SECTION_TYPE) == S_ZEROFILL); }
        virtual uint64_t                                                        getSize() const                                 { return fSize; }
        virtual std::vector<ObjectFile::Reference*>&  getReferences() const                     { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
        virtual bool                                                            mustRemainInSection() const             { return true; }
        virtual const char*                                                     getSectionName() const;
        virtual Segment<A>&                                                     getSegment() const                              { return *fSegment; }
-       virtual bool                                                            requiresFollowOnAtom() const;
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const;
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return (std::vector<ObjectFile::LineInfo>*)&fLineInfo; }
        virtual ObjectFile::Alignment                           getAlignment() const                    { return fAlignment; }
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
        virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)              { fScope = newScope; }
-       virtual void                                                            setSize(uint64_t size)                  { fSize = size; }
+       virtual void                                                            setSize(uint64_t size);
        virtual void                                                            addReference(ObjectFile::Reference* ref) { fReferences.push_back((Reference<A>*)ref); }
        virtual void                                                            sortReferences() { std::sort(fReferences.begin(), fReferences.end(), ReferenceSorter()); }
        virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  { fLineInfo.push_back(info); }
+       virtual uint64_t                                                        getObjectAddress() const                { return fAddress; }
+       virtual const void*                                                     getSectionRecord() const                { return (const void*)fSection; }
 
 protected:
        typedef typename A::P                                           P;
@@ -282,7 +399,6 @@ protected:
        typedef typename ReferenceVector::iterator                      ReferenceVectorIterator;                // seems to help C++ parser
        typedef typename ReferenceVector::const_iterator        ReferenceVectorConstIterator;   // seems to help C++ parser
        friend class Reader<A>;
-       friend class SymbolAtomSorter<A>;
 
                                                                                        SymbolAtom(Reader<A>&, const macho_nlist<P>*, const macho_section<P>*);
        virtual                                                                 ~SymbolAtom() {}
@@ -388,17 +504,40 @@ SymbolAtom<A>::SymbolAtom(Reader<A>& owner, const macho_nlist<P>* symbol, const
                // GCC_except_table* symbols don't need to exist in final linked image
                fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableNotIn;
        }
+       else if ( fOwner.fOptions.fForFinalLinkedImage && !fOwner.fOptions.fForStatic && (fOwner.fStrings[fSymbol->n_strx()] == 'l') ) {
+               // labels beginning with a lowercase ell are automatically removed in final linked images <rdar://problem/4571042>
+               // xnu code base uses a lot of asesembly labels that start with 'l', don't strip those (static executable)
+               fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableNotIn;
+       }
        else {
                fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
        }
        // compute alignment
        fAlignment = ObjectFile::Alignment(fSection->align(), fAddress % (1 << fSection->align()));
+       
+       // work around malformed icc generated .o files  <rdar://problem/5349847>
+       // if section starts with a symbol and that symbol address does not match section alignment, then force it to
+       if ( (section->addr() == fAddress) && (fAlignment.modulus != 0) )
+               fAlignment.modulus = 0;
+}
+
+template <typename A>
+bool SymbolAtom<A>::dontDeadStrip() const
+{
+       // the symbol can have a no-dead-strip bit
+       if ( (fSymbol->n_desc() & (N_NO_DEAD_STRIP|REFERENCED_DYNAMICALLY)) != 0 )
+               return true;
+       // or the section can have a no-dead-strip bit
+       return ( fSection->flags() & S_ATTR_NO_DEAD_STRIP );
 }
 
 
 template <typename A>
 const char*    SymbolAtom<A>::getSectionName() const
 {
+       if ( fOwner.fOptions.fForFinalLinkedImage && (strcmp(fSection->sectname(), "__textcoal_nt") == 0) )
+               return "__text";
+       
        if ( strlen(fSection->sectname()) > 15 ) {
                static char temp[18];
                strncpy(temp, fSection->sectname(), 16);
@@ -408,20 +547,6 @@ const char*        SymbolAtom<A>::getSectionName() const
        return fSection->sectname();
 }
 
-template <typename A>
-bool SymbolAtom<A>::requiresFollowOnAtom() const
-{
-       // requires follow-on if built with old compiler and not the last atom
-       if ( (fOwner.fHeader->flags() & MH_SUBSECTIONS_VIA_SYMBOLS) == 0) {
-               for (ReferenceVectorConstIterator it=fReferences.begin(); it != fReferences.end(); it++) {
-                       Reference<A>* ref = *it;
-                       if ( ref->getKind() == A::kFollowOn )
-                               return true;
-               }
-       }
-       return false;
-}
-
 template <typename A>
 ObjectFile::Atom& SymbolAtom<A>::getFollowOnAtom() const
 {
@@ -434,7 +559,27 @@ ObjectFile::Atom& SymbolAtom<A>::getFollowOnAtom() const
 }
 
 
+class Beyond
+{
+public:
+       Beyond(uint64_t offset) : fOffset(offset) {}
+       bool operator()(ObjectFile::Reference* ref) const {
+               return ( ref->getFixUpOffset() >= fOffset );
+       }
+private:
+       uint64_t fOffset;
+};
+
 
+template <typename A>
+void SymbolAtom<A>::setSize(uint64_t size)
+{
+       // when resizing, any references beyond the new size are tossed
+       if ( (fSize != 0) && (fReferences.size() > 0) ) 
+               fReferences.erase(std::remove_if(fReferences.begin(), fReferences.end(), Beyond(size)), fReferences.end());
+       // set new size
+       fSize = size;
+}
 
 template <typename A>
 void SymbolAtom<A>::copyRawContent(uint8_t buffer[]) const
@@ -448,36 +593,85 @@ void SymbolAtom<A>::copyRawContent(uint8_t buffer[]) const
        }
 }
 
+//
+// A SymbolAliasAtom represents an alternate name for a SymbolAtom
+//
+//
 template <typename A>
-class SymbolAtomSorter
+class SymbolAliasAtom : public BaseAtom
 {
 public:
-       SymbolAtomSorter(std::map<uint32_t, BaseAtom*>& map) : fMap(map) {}
-       
-       typedef typename A::P::uint_t pint_t;
-       
-       bool operator()(ObjectFile::Atom* left, ObjectFile::Atom* right)
-       {
-               pint_t leftAddr  = ((SymbolAtom<A>*)left)->fAddress;
-               pint_t rightAddr = ((SymbolAtom<A>*)right)->fAddress;
-               if ( leftAddr == rightAddr ) {
-                       // two atoms with same address, must have been a function with multiple labels
-                       // make sure we sort these so the one with real content (in map) is last
-                       std::map<uint32_t, BaseAtom*>::iterator pos = fMap.find(leftAddr);
-                       if ( pos != fMap.end() ) {
-                               return ( pos->second == right );
-                       }
-                       return false;
-               }
-               else {
-                       return ( leftAddr < rightAddr );
-               }
-       }
-private:
-       std::map<uint32_t, BaseAtom*>&  fMap;
+       virtual ObjectFile::Reader*                                     getFile() const                                 { return fAliasOf.getFile(); }
+       virtual bool                                                            getTranslationUnitSource(const char** dir, const char** name) const
+                                                                                                                                                               { return fAliasOf.getTranslationUnitSource(dir, name); }
+       virtual const char*                                                     getName() const                                 { return fName; }
+       virtual const char*                                                     getDisplayName() const                  { return fName; }
+       virtual ObjectFile::Atom::Scope                         getScope() const                                { return fScope; }
+       virtual ObjectFile::Atom::DefinitionKind        getDefinitionKind() const               { return fAliasOf.getDefinitionKind(); }
+       virtual SymbolTableInclusion                            getSymbolTableInclusion() const { return fAliasOf.getSymbolTableInclusion(); }
+       virtual bool                                                            dontDeadStrip() const                   { return fDontDeadStrip; }
+       virtual bool                                                            isZeroFill() const                              { return fAliasOf.isZeroFill(); }
+       virtual uint64_t                                                        getSize() const                                 { return 0; }
+       virtual std::vector<ObjectFile::Reference*>&  getReferences() const                     { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
+       virtual bool                                                            mustRemainInSection() const             { return true; }
+       virtual const char*                                                     getSectionName() const                  { return fAliasOf.getSectionName(); }
+       virtual Segment<A>&                                                     getSegment() const                              { return (Segment<A>&)fAliasOf.getSegment(); }
+       virtual ObjectFile::Atom&                                       getFollowOnAtom() const                 { return (ObjectFile::Atom&)fAliasOf; }
+       virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return NULL; }
+       virtual ObjectFile::Alignment                           getAlignment() const                    { return  fAliasOf.getAlignment(); }
+       virtual void                                                            copyRawContent(uint8_t buffer[]) const {}
+       virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)              { fScope = newScope; }
+       virtual void                                                            setSize(uint64_t size)                  {  }
+       virtual void                                                            addReference(ObjectFile::Reference* ref) { fReferences.push_back((Reference<A>*)ref); }
+       virtual void                                                            sortReferences() { std::sort(fReferences.begin(), fReferences.end(), ReferenceSorter()); }
+       virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  {  }
+       virtual uint64_t                                                        getObjectAddress() const                { return fAliasOf.getObjectAddress(); }
+       virtual const void*                                                     getSectionRecord() const                { return fAliasOf.getSectionRecord(); }
+       virtual bool                                                            isAlias() const                                 { return true; }
+
+protected:
+       typedef typename A::P                                           P;
+       typedef typename std::vector<Reference<A>*>                     ReferenceVector;
+       typedef typename ReferenceVector::iterator                      ReferenceVectorIterator;                // seems to help C++ parser
+       typedef typename ReferenceVector::const_iterator        ReferenceVectorConstIterator;   // seems to help C++ parser
+       friend class Reader<A>;
+
+                                                                                       SymbolAliasAtom(const char* name, const macho_nlist<P>*, const BaseAtom& );
+       virtual                                                                 ~SymbolAliasAtom() {}
+
+       const char*                                                                     fName;
+       const BaseAtom&                                                         fAliasOf;
+       ObjectFile::Atom::Scope                                         fScope;
+       bool                                                                            fDontDeadStrip;
+       ReferenceVector                                                         fReferences;
 };
 
 
+template <typename A>
+SymbolAliasAtom<A>::SymbolAliasAtom(const char* name, const macho_nlist<P>* symbol, const BaseAtom& aliasOf)
+ : fName(name), fAliasOf(aliasOf)
+{
+       //fprintf(stderr, "SymbolAliasAtom(%p) %s\n", this, name);
+       if ( symbol != NULL ) {
+               uint8_t type =  symbol->n_type();
+               if ( (type & N_EXT) == 0 )
+                       fScope = ObjectFile::Atom::scopeTranslationUnit;
+               else if ( (type & N_PEXT) != 0 )
+                       fScope = ObjectFile::Atom::scopeLinkageUnit;
+               else
+                       fScope = ObjectFile::Atom::scopeGlobal;
+               fDontDeadStrip = ((symbol->n_desc() & (N_NO_DEAD_STRIP|REFERENCED_DYNAMICALLY)) != 0);
+       }
+       else {
+               // aliases defined on the command line are initially global scope
+               fScope = ObjectFile::Atom::scopeGlobal;
+               fDontDeadStrip = false;
+       }
+       // add follow-on reference to real atom 
+       new Reference<A>(A::kFollowOn, AtomAndOffset(this), AtomAndOffset((ObjectFile::Atom*)&aliasOf));
+}
+
+
 //
 // A TentativeAtom represents a C "common" or "tentative" defintion of data.
 // For instance, "int foo;" is neither a declaration or a definition and
@@ -501,18 +695,19 @@ public:
        virtual uint64_t                                                        getSize() const                                 { return fSymbol->n_value(); }
        virtual std::vector<ObjectFile::Reference*>&  getReferences() const                     { return fgNoReferences; }
        virtual bool                                                            mustRemainInSection() const             { return true; }
-       virtual const char*                                                     getSectionName() const                  { return "__common"; }
+       virtual const char*                                                     getSectionName() const;
        virtual ObjectFile::Segment&                            getSegment() const                              { return DataSegment::fgSingleton; }
-       virtual bool                                                            requiresFollowOnAtom() const    { return false; }
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const                 { return *(ObjectFile::Atom*)NULL; }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return NULL; }
        virtual ObjectFile::Alignment                           getAlignment() const;
        virtual void                                                            copyRawContent(uint8_t buffer[]) const;
        virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)              { fScope = newScope; }
        virtual void                                                            setSize(uint64_t size)                  { }
-       virtual void                                                            addReference(ObjectFile::Reference* ref) { throw "ld64: can't add references"; }
+       virtual void                                                            addReference(ObjectFile::Reference* ref) { throw "ld: can't add references"; }
        virtual void                                                            sortReferences() { }
-       virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  { throw "ld64: can't add line info to tentative definition"; }
+       virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  { throw "ld: can't add line info to tentative definition"; }
+       virtual uint64_t                                                        getObjectAddress() const                { return ULLONG_MAX; }
+       virtual const void*                                                     getSectionRecord() const                { return NULL; }
 
 protected:
        typedef typename A::P                                   P;
@@ -557,17 +752,34 @@ TentativeAtom<A>::TentativeAtom(Reader<A>& owner, const macho_nlist<P>* symbol)
 template <typename A>
 ObjectFile::Alignment TentativeAtom<A>::getAlignment() const
 {
-       // common symbols align to their size
-       // that is, a 4-byte common aligns to 4-bytes
-       // to be safe, odd size commons align to the next power-of-2 size
-       uint8_t alignment = (uint8_t)ceil(log2(this->getSize()));
+       uint8_t alignment = GET_COMM_ALIGN(fSymbol->n_desc());
+       if ( alignment == 0 ) {
+               // common symbols align to their size
+               // that is, a 4-byte common aligns to 4-bytes
+               // if this size is not a power of two, 
+               // then round up to the next power of two
+               uint64_t size = this->getSize();
+               alignment = 63 - (uint8_t)__builtin_clzll(size);
+               if ( size != (1ULL << alignment) )
+                       ++alignment;
+       }
        // limit alignment of extremely large commons to 2^15 bytes (8-page)
-       if ( alignment < 15 )
+       if ( alignment < 12 )
                return ObjectFile::Alignment(alignment);
        else
-               return ObjectFile::Alignment(15);
+               return ObjectFile::Alignment(12);
+}
+
+template <typename A>
+const char* TentativeAtom<A>::getSectionName() const
+{
+       if ( fOwner.fOptions.fForFinalLinkedImage || fOwner.fOptions.fMakeTentativeDefinitionsReal )
+               return "__common"; 
+       else
+               return "._tentdef"; 
 }
 
+
 template <typename A>
 void TentativeAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
@@ -598,7 +810,6 @@ public:
        virtual bool                                                            mustRemainInSection() const             { return true; }
        virtual const char*                                                     getSectionName() const;
        virtual Segment<A>&                                                     getSegment() const                              { return *fSegment; }
-       virtual bool                                                            requiresFollowOnAtom() const;
        virtual ObjectFile::Atom&                                       getFollowOnAtom() const;
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return NULL; }
        virtual ObjectFile::Alignment                           getAlignment() const;
@@ -607,10 +818,13 @@ public:
        virtual void                                                            setSize(uint64_t size)                  { fSize = size; }
        virtual void                                                            addReference(ObjectFile::Reference* ref) { fReferences.push_back((Reference<A>*)ref); }
        virtual void                                                            sortReferences() { std::sort(fReferences.begin(), fReferences.end(), ReferenceSorter()); }
-       virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info) { fprintf(stderr, "ld64: can't add line info to anonymous symbol %s from %s\n", this->getDisplayName(), this->getFile()->getPath()); }
+       virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info) { fprintf(stderr, "ld: can't add line info to anonymous symbol %s from %s\n", this->getDisplayName(), this->getFile()->getPath()); }
+       virtual uint64_t                                                        getObjectAddress() const                { return fAddress; }
+       virtual const void*                                                     getSectionRecord() const                { return (const void*)fSection; }
        BaseAtom*                                                                       redirectTo()                                    { return fRedirect; }
        bool                                                                            isWeakImportStub()                              { return fWeakImportStub; }
-
+       void                                                                            resolveName();
+       
 protected:
        typedef typename A::P                                           P;
        typedef typename A::P::E                                        E;
@@ -623,9 +837,11 @@ protected:
 
                                                                                        AnonymousAtom(Reader<A>&, const macho_section<P>*, uint32_t addr, uint32_t size);
        virtual                                                                 ~AnonymousAtom() {}
+       static bool                                                                     cstringsHaveLabels();
 
        Reader<A>&                                                                      fOwner;
        const char*                                                                     fSynthesizedName;
+       const char*                                                                     fDisplayName;
        const macho_section<P>*                                         fSection;
        uint32_t                                                                        fAddress;
        uint32_t                                                                        fSize;
@@ -640,25 +856,27 @@ protected:
 
 template <typename A>
 AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* section, uint32_t addr, uint32_t size)
- : fOwner(owner), fSynthesizedName(NULL), fSection(section), fAddress(addr), fSize(size), fSegment(NULL), fDontDeadStrip(true),
-       fWeakImportStub(false), fSymbolTableInclusion(ObjectFile::Atom::kSymbolTableNotIn),
+ : fOwner(owner), fSynthesizedName(NULL), fDisplayName(NULL), fSection(section), fAddress(addr), fSize(size), 
+       fSegment(NULL), fDontDeadStrip(true), fWeakImportStub(false), fSymbolTableInclusion(ObjectFile::Atom::kSymbolTableNotIn),
        fScope(ObjectFile::Atom::scopeTranslationUnit)
 {
        fSegment = new Segment<A>(fSection);
        fRedirect = this;
        uint8_t type = fSection->flags() & SECTION_TYPE;
+       //fprintf(stderr, "AnonymousAtom(%p) addr=0x%X in %s from %s\n", this, addr, section->sectname(), owner.getPath());
        switch ( type ) {
                case S_ZEROFILL:
                        {
                                asprintf((char**)&fSynthesizedName, "zero-fill-at-0x%08X", addr);
                        }
                        break;
+               case S_COALESCED:
                case S_REGULAR:
                        if ( (strcmp(section->sectname(), "__class") == 0) && (strcmp(section->segname(), "__OBJC") == 0) && owner.fAppleObjc ) {
                                // special case ObjC classes to synthesize .objc_class_name_* symbols, for Apple runtime only
-                               uint32_t classNameAddr =  P::getP(*(pint_t*)(((uint8_t*)owner.fHeader) + section->offset() + addr + 2*sizeof(pint_t) - section->addr()));
-                               const char* str = (char*)(owner.fHeader) + section->offset() + classNameAddr - section->addr();
-                               asprintf((char**)&fSynthesizedName, ".objc_class_name_%s", str);
+                               fSynthesizedName = ".objc_class_name_PENDING";
+                               owner.fAtomsPendingAName.push_back(this);
+                               owner.fSectionsWithAtomsPendingAName.insert(fSection);
                                if ( fOwner.fOptions.fForFinalLinkedImage ) 
                                        fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
                                else
@@ -677,6 +895,8 @@ AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* sectio
                                asprintf((char**)&fSynthesizedName, "cstring=%s", str);
                                fScope = ObjectFile::Atom::scopeLinkageUnit;
                                fDontDeadStrip = false;
+                               if ( !fOwner.fOptions.fForFinalLinkedImage && cstringsHaveLabels() ) 
+                                       fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
                        }
                        break;
                case S_4BYTE_LITERALS:
@@ -706,10 +926,13 @@ AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* sectio
                        break;
                case S_LITERAL_POINTERS:
                        {
-                               uint32_t literalNameAddr =  P::getP(*(pint_t*)(((uint8_t*)owner.fHeader) + section->offset() + addr - section->addr()));
-                               const char* str = (char*)(owner.fHeader) + section->offset() + literalNameAddr - section->addr();
-                               asprintf((char**)&fSynthesizedName, "literal-pointer@%s@%s@%s", section->segname(), section->sectname(), str);
+                               //uint32_t literalNameAddr =  P::getP(*(pint_t*)(((uint8_t*)owner.fHeader) + section->offset() + addr - section->addr()));
+                               //const char* str = (char*)(owner.fHeader) + section->offset() + literalNameAddr - section->addr();
+                               //asprintf((char**)&fSynthesizedName, "literal-pointer@%s@%s@%s", section->segname(), section->sectname(), str);
+                               fSynthesizedName = "literal-pointer-name-PENDING";
                                fScope = ObjectFile::Atom::scopeLinkageUnit;
+                               owner.fAtomsPendingAName.push_back(this);
+                               owner.fSectionsWithAtomsPendingAName.insert(fSection);
                        }
                        break;
                case S_MOD_INIT_FUNC_POINTERS:
@@ -731,12 +954,16 @@ AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* sectio
                                fWeakImportStub = fOwner.isWeakImportSymbol(sym);
                                // sometimes the compiler gets confused and generates a stub to a static function
                                // if so, we should redirect any call to the stub to be calls to the real static function atom
-                               if ( ((sym->n_type() & N_TYPE) != N_UNDF) && ((sym->n_desc() & N_WEAK_DEF) == 0) ) {
+                               if ( ((sym->n_type() & N_TYPE) != N_UNDF) && ((sym->n_type() & N_EXT) == 0) ) {
                                        BaseAtom* staticAtom = fOwner.findAtomByName(fSynthesizedName);
-                                       if ( staticAtom != NULL )
+                                       if ( staticAtom != NULL ) 
                                                fRedirect = staticAtom;
                                }
-                               fScope = ObjectFile::Atom::scopeLinkageUnit;
+                               // might be a spurious stub for a static function, make stub static too
+                               if ( (sym->n_type() & N_EXT) == 0 ) 
+                                       fScope = ObjectFile::Atom::scopeTranslationUnit;
+                               else
+                                       fScope = ObjectFile::Atom::scopeLinkageUnit;
                        }
                        break;
                case S_LAZY_SYMBOL_POINTERS:
@@ -752,23 +979,40 @@ AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* sectio
                                        uint32_t fileOffset = fSection->offset() - fSection->addr() + fAddress;
                                        pint_t nonLazyPtrValue = P::getP(*((pint_t*)((char*)(fOwner.fHeader)+fileOffset)));
                                        // All atoms not created yet, so we need to scan symbol table
+                                       const macho_nlist<P>* closestSym = NULL; 
                                        const macho_nlist<P>* end = &fOwner.fSymbols[fOwner.fSymbolCount];
                                        for (const macho_nlist<P>* sym =  fOwner.fSymbols; sym < end; ++sym) {
                                                if ( ((sym->n_type() & N_TYPE) == N_SECT) 
-                                                && ((sym->n_type() & N_STAB) == 0) 
-                                                && (sym->n_value() == nonLazyPtrValue) ) {
-                                                       const char* name = &fOwner.fStrings[sym->n_strx()];
-                                                       char* str = new char[strlen(name)+16];
-                                                       strcpy(str, name);
-                                                       strcat(str, "$non_lazy_ptr");
-                                                       fSynthesizedName = str;
-                                                       // add direct reference to target later, because its atom may not be constructed yet
-                                                       fOwner.fLocalNonLazys.push_back(this);
-                                                       fScope = ObjectFile::Atom::scopeTranslationUnit;
-                                                       return;
+                                                && ((sym->n_type() & N_STAB) == 0) ) {
+                                                       if ( sym->n_value() == nonLazyPtrValue ) {
+                                                               const char* name = &fOwner.fStrings[sym->n_strx()];
+                                                               char* str = new char[strlen(name)+16];
+                                                               strcpy(str, name);
+                                                               strcat(str, "$non_lazy_ptr");
+                                                               fSynthesizedName = str;
+                                                               // add direct reference to target later, because its atom may not be constructed yet
+                                                               fOwner.fLocalNonLazys.push_back(this);
+                                                               fScope = ObjectFile::Atom::scopeTranslationUnit;
+                                                               return;
+                                                       }
+                                                       else if ( (sym->n_value() < nonLazyPtrValue) && ((closestSym == NULL) || (sym->n_value() > closestSym->n_value())) ) {
+                                                               closestSym = sym;
+                                                       }
                                                }
                                        }
-                                       throwf("malformed .o file: non-lazy-pointer at address 0x%08X with value 0x%0llX missing symbol", addr, (uint64_t)nonLazyPtrValue);
+                                       // add direct reference to target later, because its atom may not be constructed yet
+                                       if ( closestSym != NULL ) {
+                                               const char* name = &fOwner.fStrings[closestSym->n_strx()];
+                                               char* str;
+                                               asprintf(&str, "%s+%u$non_lazy_ptr", name, nonLazyPtrValue - closestSym->n_value());
+                                               fSynthesizedName = str;
+                                       }
+                                       else {
+                                               fSynthesizedName = "$interior$non_lazy_ptr";
+                                       }
+                                       fScope = ObjectFile::Atom::scopeTranslationUnit;
+                                       fOwner.fLocalNonLazys.push_back(this);
+                                       return;
                                }
                                const macho_nlist<P>* targetSymbol = &fOwner.fSymbols[symbolIndex];
                                const char* name = &fOwner.fStrings[targetSymbol->n_strx()];
@@ -780,6 +1024,14 @@ AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* sectio
                                        strcat(str, "$non_lazy_ptr");
                                fSynthesizedName = str;
 
+                               // optimize __IMPORT segment out of i386 dyld
+                               if ( fOwner.fOptions.fForDyld  && (strcmp(fSection->segname(),"__IMPORT") == 0) ) {
+                                       macho_section<P>* dummySection = new macho_section<P>(*fSection);
+                                       dummySection->set_segname("__DATA");
+                                       fSection = dummySection;
+                                       fSegment = new Segment<A>(fSection);
+                               }
+                               
                                if ( (targetSymbol->n_type() & N_EXT) == 0 ) {
                                        // target is translation unit scoped, so add direct reference to target
                                        //fOwner.makeReference(A::kPointer, addr, targetSymbol->n_value());
@@ -799,6 +1051,47 @@ AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* sectio
        //fprintf(stderr, "AnonymousAtom(%p) %s \n", this, this->getDisplayName());
 }
 
+// x86_64 uses L labels on cstrings to allow relocs with addends
+template <> bool AnonymousAtom<x86_64>::cstringsHaveLabels() { return true; }
+template <typename A> bool AnonymousAtom<A>::cstringsHaveLabels() { return false; }
+
+
+template <typename A>
+void AnonymousAtom<A>::resolveName()
+{
+       if ( (strcmp(fSection->sectname(), "__class") == 0) && (strcmp(fSection->segname(), "__OBJC") == 0) ) {
+               std::vector<ObjectFile::Reference*>&  references = this->getReferences();
+               // references are not yet sorted, so scan the vector
+               for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                       if ( ((*rit)->getFixUpOffset() == sizeof(pint_t)) && ((*rit)->getKind() == A::kPointer) ) {
+                               const char* superStr = (*rit)->getTargetName();
+                               if ( strncmp(superStr, "cstring=", 8) == 0 ) {
+                                       const char* superClassName;
+                                       asprintf((char**)&superClassName, ".objc_class_name_%s", &superStr[8]);
+                                       new Reference<A>(A::kNoFixUp, AtomAndOffset(this), superClassName, 0);
+                               }
+                               break;
+                       }
+               }
+               for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                       if ( ((*rit)->getFixUpOffset() == 2*sizeof(pint_t)) && ((*rit)->getKind() == A::kPointer) ) {
+                               const char* classStr = (*rit)->getTargetName();
+                               if ( strncmp(classStr, "cstring=", 8) == 0 ) {
+                                       asprintf((char**)&fSynthesizedName, ".objc_class_name_%s", &classStr[8]);
+                               }
+                               break;
+                       }
+               }
+       }
+       else if ( (fSection->flags() & SECTION_TYPE) == S_LITERAL_POINTERS) {
+               ObjectFile::Reference* ref = this->getReferences()[0];
+               const char* str = ref->getTargetName();
+               if ( strncmp(str, "cstring=", 8) == 0 ) {
+                       asprintf((char**)&fSynthesizedName, "literal-pointer@%s@%s@%s", fSection->segname(), fSection->sectname(), &str[8]);
+               }
+       }
+}
+
 
 template <typename A>
 const char* AnonymousAtom<A>::getDisplayName() const
@@ -806,17 +1099,20 @@ const char* AnonymousAtom<A>::getDisplayName() const
        if ( fSynthesizedName != NULL )
                return fSynthesizedName;
 
-       static char temp[512];
+       if ( fDisplayName != NULL )
+               return fDisplayName;
+
        if ( (fSection->flags() & SECTION_TYPE) == S_CSTRING_LITERALS ) {
                uint32_t fileOffset = fSection->offset() - fSection->addr() + fAddress;
-               sprintf(temp, "atom string literal: \"%s\"", (char*)(fOwner.fHeader)+fileOffset);
+               asprintf((char**)&fDisplayName, "atom string literal: \"%s\"", (char*)(fOwner.fHeader)+fileOffset);
        }
        else {
-               sprintf(temp, "%s@%d", fSection->sectname(), fAddress - (uint32_t)fSection->addr() );
+               asprintf((char**)&fDisplayName, "%s@%d", fSection->sectname(), fAddress - (uint32_t)fSection->addr() );
        }
-       return temp;
+       return fDisplayName;
 }
 
+
 template <typename A>
 ObjectFile::Atom::Scope AnonymousAtom<A>::getScope() const
 {
@@ -832,9 +1128,14 @@ ObjectFile::Atom::DefinitionKind AnonymousAtom<A>::getDefinitionKind() const
                case S_4BYTE_LITERALS:
                case S_8BYTE_LITERALS:
                case S_16BYTE_LITERALS:
-               case S_NON_LAZY_SYMBOL_POINTERS:
+               case S_SYMBOL_STUBS:
                case S_LITERAL_POINTERS:
                        return ObjectFile::Atom::kWeakDefinition;
+               case S_NON_LAZY_SYMBOL_POINTERS:
+                       if ( fScope == ObjectFile::Atom::scopeTranslationUnit )
+                               return ObjectFile::Atom::kRegularDefinition;
+                       else
+                               return ObjectFile::Atom::kWeakDefinition;
                default:
                        return ObjectFile::Atom::kRegularDefinition;
        }
@@ -871,24 +1172,14 @@ ObjectFile::Alignment AnonymousAtom<A>::getAlignment() const
                        return ObjectFile::Alignment(4);
                case S_NON_LAZY_SYMBOL_POINTERS:
                        return ObjectFile::Alignment((uint8_t)log2(sizeof(pint_t)));
+               case S_CSTRING_LITERALS:
+                       if ( ! fOwner.fOptions.fForFinalLinkedImage )
+                               return ObjectFile::Alignment(fSection->align());
                default:
                        return ObjectFile::Alignment(fSection->align(), fAddress % (1 << fSection->align()));
        }
 }
 
-template <typename A>
-bool AnonymousAtom<A>::requiresFollowOnAtom() const
-{
-       // requires follow-on if built with old compiler and not the last atom
-       if ( (fOwner.fHeader->flags() & MH_SUBSECTIONS_VIA_SYMBOLS) == 0) {
-               for (ReferenceVectorConstIterator it=fReferences.begin(); it != fReferences.end(); it++) {
-                       Reference<A>* ref = *it;
-                       if ( ref->getKind() == A::kFollowOn )
-                               return true;
-               }
-       }
-       return false;
-}
 
 template <typename A>
 ObjectFile::Atom& AnonymousAtom<A>::getFollowOnAtom() const
@@ -914,6 +1205,78 @@ void AnonymousAtom<A>::copyRawContent(uint8_t buffer[]) const
 }
 
 
+//
+// An AbsoluteAtom represents an N_ABS symbol which can only be created in 
+// assembly language and usable by static executables such as the kernel/
+//
+template <typename A>
+class AbsoluteAtom : public BaseAtom
+{
+public:
+       virtual ObjectFile::Reader*                                     getFile() const                                 { return &fOwner; }
+       virtual bool                                                            getTranslationUnitSource(const char** dir, const char** name) const
+                                                                                                                                                               { return fOwner.getTranslationUnitSource(dir, name); }
+       virtual const char*                                                     getName() const                                 { return &fOwner.fStrings[fSymbol->n_strx()]; }
+       virtual const char*                                                     getDisplayName() const                  { return getName(); }
+       virtual ObjectFile::Atom::Scope                         getScope() const                                { return fScope; }
+       virtual ObjectFile::Atom::DefinitionKind        getDefinitionKind() const               { return ObjectFile::Atom::kAbsoluteSymbol; }
+       virtual bool                                                            isZeroFill() const                              { return false; }
+       virtual SymbolTableInclusion                            getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableInAsAbsolute; }
+       virtual bool                                                            dontDeadStrip() const                   { return false; }
+       virtual uint64_t                                                        getSize() const                                 { return 0; }
+       virtual std::vector<ObjectFile::Reference*>&  getReferences() const                     { return fgNoReferences; }
+       virtual bool                                                            mustRemainInSection() const             { return true; }
+       virtual const char*                                                     getSectionName() const                  { return "._absolute"; } 
+       virtual ObjectFile::Segment&                            getSegment() const                              { return LinkEditSegment::fgSingleton; }
+       virtual ObjectFile::Atom&                                       getFollowOnAtom() const                 { return *(ObjectFile::Atom*)NULL; }
+       virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                             { return NULL; }
+       virtual ObjectFile::Alignment                           getAlignment() const                    { return ObjectFile::Alignment(0); }
+       virtual void                                                            copyRawContent(uint8_t buffer[]) const  { }
+       virtual void                                                            setScope(ObjectFile::Atom::Scope newScope)              { fScope = newScope; }
+       virtual void                                                            setSize(uint64_t size)                  { }
+       virtual void                                                            addReference(ObjectFile::Reference* ref) { throw "ld: can't add references"; }
+       virtual void                                                            sortReferences()                                { }
+       virtual void                                                            addLineInfo(const  ObjectFile::LineInfo& info)  { throw "ld: can't add line info to tentative definition"; }
+       virtual uint64_t                                                        getObjectAddress() const                { return fSymbol->n_value(); }
+       virtual void                                                            setSectionOffset(uint64_t offset) { /* don't let fSectionOffset be altered*/ }
+       virtual const void*                                                     getSectionRecord() const                { return NULL; }
+
+protected:
+       typedef typename A::P                                   P;
+       typedef typename A::P::E                                E;
+       typedef typename A::P::uint_t                   pint_t;
+       typedef typename A::ReferenceKinds              Kinds;
+       friend class Reader<A>;
+
+                                                                                       AbsoluteAtom(Reader<A>&, const macho_nlist<P>*);
+       virtual                                                                 ~AbsoluteAtom() {}
+
+       Reader<A>&                                                                      fOwner;
+       const macho_nlist<P>*                                           fSymbol;
+       ObjectFile::Atom::Scope                                         fScope;
+       static std::vector<ObjectFile::Reference*>      fgNoReferences;
+};
+
+template <typename A>
+std::vector<ObjectFile::Reference*> AbsoluteAtom<A>::fgNoReferences;
+
+template <typename A>
+AbsoluteAtom<A>::AbsoluteAtom(Reader<A>& owner, const macho_nlist<P>* symbol)
+ : fOwner(owner), fSymbol(symbol)
+{
+       // store absolute adress in fSectionOffset
+       fSectionOffset = symbol->n_value();
+       // compute scope
+       uint8_t type =  symbol->n_type();
+       if ( (type & N_EXT) == 0 )
+               fScope = ObjectFile::Atom::scopeTranslationUnit;
+       else if ( (type & N_PEXT) != 0 )
+               fScope = ObjectFile::Atom::scopeLinkageUnit;
+       else
+               fScope = ObjectFile::Atom::scopeGlobal;
+       //fprintf(stderr, "AbsoluteAtom(%p) %s\n", this, this->getDisplayName());
+}
+
 
 
 template <typename A>
@@ -921,9 +1284,8 @@ class Reader : public ObjectFile::Reader
 {
 public:
        static bool                                                                             validFile(const uint8_t* fileContent);
-       static Reader<A>*                                                               make(const uint8_t* fileContent, const char* path, time_t modTime,
-                                                                                                                       const ObjectFile::ReaderOptions& options)
-                                                                                                               { return new Reader<A>(fileContent, path, modTime, options); }
+                                                                                                       Reader(const uint8_t* fileContent, const char* path, time_t modTime, 
+                                                                                                               const ObjectFile::ReaderOptions& options, uint32_t ordinalBase);
        virtual                                                                                 ~Reader() {}
 
        virtual const char*                                                             getPath()                               { return fPath; }
@@ -932,6 +1294,10 @@ public:
        virtual std::vector<class ObjectFile::Atom*>&   getAtoms()                              { return (std::vector<class ObjectFile::Atom*>&)(fAtoms); }
        virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) { return NULL; }
        virtual std::vector<Stab>*                                              getStabs()                              { return &fStabs; }
+       virtual ObjectFile::Reader::ObjcConstraint              getObjCConstraint()             { return fObjConstraint; }
+       virtual ObjectFile::Reader::CpuConstraint               getCpuConstraint()              { return fCpuConstraint; }
+       virtual bool                                                                    canScatterAtoms()               { return (fHeader->flags() & MH_SUBSECTIONS_VIA_SYMBOLS); }
+       virtual bool                                                                    objcReplacementClasses(){ return fReplacementClasses; }
 
         bool                                                                                   getTranslationUnitSource(const char** dir, const char** name) const;
 
@@ -944,8 +1310,10 @@ private:
        typedef typename A::ReferenceKinds                      Kinds;
        friend class AnonymousAtom<A>;
        friend class TentativeAtom<A>;
+       friend class AbsoluteAtom<A>;
        friend class SymbolAtom<A>;
-                                                                                               Reader(const uint8_t* fileContent, const char* path, time_t modTime, const ObjectFile::ReaderOptions& options);
+
+       void                                                                            addReferencesForSection(const macho_section<P>* sect);
        bool                                                                            addRelocReference(const macho_section<P>* sect, const macho_relocation_info<P>* reloc);
        bool                                                                            addRelocReference_powerpc(const macho_section<P>* sect, const macho_relocation_info<P>* reloc);
        Kinds                                                                           pointerDiffKindForLength_powerpc(uint8_t r_length);
@@ -963,11 +1331,14 @@ private:
        Reference<A>*                                                           makeReferenceToEH(const char* ehName, pint_t ehAtomAddress, const macho_section<P>* ehSect);
        Reference<A>*                                                           makeReferenceToSymbol(Kinds kind, uint32_t atAddr, const macho_nlist<P>* toSymbol, uint32_t toOffset);
        void                                                                            validSectionType(uint8_t type);
+       void                                                                            addDtraceExtraInfos(uint32_t probeAddr, const char* providerName);
+       void                                                                            setCpuConstraint(uint32_t cpusubtype);
 
        BaseAtom*                                                                       findAtomByName(const char*);
 
        const char*                                                                     fPath;
        time_t                                                                          fModTime;
+       uint32_t                                                                        fOrdinalBase;
        const ObjectFile::ReaderOptions&                        fOptions;
        const macho_header<P>*                                          fHeader;
        const char*                                                                     fStrings;
@@ -975,9 +1346,13 @@ private:
        uint32_t                                                                        fSymbolCount;
        const macho_segment_command<P>*                         fSegment;
        const uint32_t*                                                         fIndirectTable;
-       std::vector<ObjectFile::Atom*>                          fAtoms;
+       std::vector<BaseAtom*>                                          fAtoms;
        std::map<uint32_t, BaseAtom*>                           fAddrToAtom;
+       std::map<uint32_t, BaseAtom*>                           fAddrToAbsoluteAtom;
        std::vector<class AnonymousAtom<A>*>            fLocalNonLazys;
+       std::vector<class AnonymousAtom<A>*>            fAtomsPendingAName;
+       std::set<const macho_section<P>*>                       fSectionsWithAtomsPendingAName;
+       std::vector<const char*>                                        fDtraceProviderInfo;
        ObjectFile::Reader::DebugInfoKind                       fDebugInfo;
        bool                                                                            fHasUUID;
        const macho_section<P>*                                         fDwarfDebugInfoSect;
@@ -988,21 +1363,35 @@ private:
        std::map<uint32_t,const char*>                          fDwarfIndexToFile;
        std::vector<Stab>                                                       fStabs;
        bool                                                                            fAppleObjc;
+       bool                                                                            fHasDTraceProbes;
+       bool                                                                            fHaveIndirectSymbols;
+       bool                                                                            fReplacementClasses;
+       ObjectFile::Reader::ObjcConstraint                      fObjConstraint;
+       ObjectFile::Reader::CpuConstraint                       fCpuConstraint;
 };
 
 template <typename A>
-Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime, const ObjectFile::ReaderOptions& options)
-       : fPath(strdup(path)), fModTime(modTime), fOptions(options), fHeader((const macho_header<P>*)fileContent),
+Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime, const ObjectFile::ReaderOptions& options, uint32_t ordinalBase)
+       : fPath(strdup(path)), fModTime(modTime), fOrdinalBase(ordinalBase), fOptions(options), fHeader((const macho_header<P>*)fileContent),
         fStrings(NULL), fSymbols(NULL), fSymbolCount(0), fSegment(NULL), fIndirectTable(NULL),
-        fDebugInfo(kDebugInfoNone), fHasUUID(false), fDwarfDebugInfoSect(NULL), fDwarfDebugAbbrevSect(NULL),
-         fDwarfTranslationUnitDir(NULL), fDwarfTranslationUnitFile(NULL), fAppleObjc(false)
+        fDebugInfo(kDebugInfoNone), fHasUUID(false), fDwarfDebugInfoSect(NULL), fDwarfDebugAbbrevSect(NULL), fDwarfDebugLineSect(NULL),
+         fDwarfTranslationUnitDir(NULL), fDwarfTranslationUnitFile(NULL), fAppleObjc(false), fHasDTraceProbes(false),
+         fHaveIndirectSymbols(false), fReplacementClasses(false), 
+         fObjConstraint(ObjectFile::Reader::kObjcNone), fCpuConstraint(ObjectFile::Reader::kCpuAny) 
 {
        // sanity check
        if ( ! validFile(fileContent) )
                throw "not a valid mach-o object file";
 
+       Reference<A>::fgForFinalLinkedImage = options.fForFinalLinkedImage;
+
+       // write out path for -t or -whatsloaded option
+       if ( options.fLogObjectFiles || options.fLogAllFiles )
+               printf("%s\n", path);
+
        // cache intersting pointers
        const macho_header<P>* header = (const macho_header<P>*)fileContent;
+       this->setCpuConstraint(header->cpusubtype());
        const uint32_t cmd_count = header->ncmds();
        const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
        const macho_load_command<P>* cmd = cmds;
@@ -1016,6 +1405,10 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                        fSymbolCount = symtab->nsyms();
                                        fSymbols = (const macho_nlist<P>*)((char*)header + symtab->symoff());
                                        fStrings = (char*)header + symtab->stroff();
+                                       if ( undefinedEndIndex == 0 ) {
+                                               undefinedStartIndex = 0;
+                                               undefinedEndIndex = symtab->nsyms();
+                                       }
                                }
                                break;
                        case LC_DYSYMTAB:
@@ -1046,67 +1439,90 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
 
        // add all atoms that have entries in symbol table
        const macho_section<P>* sections = (macho_section<P>*)((char*)fSegment + sizeof(macho_segment_command<P>));
-       for (uint32_t i=0; i < fSymbolCount; ++i) {
+       for (int i=fSymbolCount-1; i >= 0 ; --i) {
+               // walk backwards through symbol table so globals are see before locals, otherwise a local alias would beome the reaal name
                const macho_nlist<P>& sym = fSymbols[i];
                if ( (sym.n_type() & N_STAB) == 0 ) {
                        uint8_t type =  (sym.n_type() & N_TYPE);
                        if ( type == N_SECT ) {
                                const macho_section<P>* section = &sections[sym.n_sect()-1];
+                               pint_t sectionEndAddr = section->addr() + section->size();
                                bool suppress = false;
                                // ignore atoms in debugger sections
                                if ( (section->flags() & S_ATTR_DEBUG) == 0 ) {
-                                       // ignore labels for atoms in other sections
-                                       switch ( section->flags() & SECTION_TYPE ) {
-                                               case S_REGULAR:
-                                                       if ( (sym.n_desc() & N_WEAK_DEF) && strcmp(section->sectname(), "__picsymbolstub1__TEXT") == 0 )
-                                                               suppress = true; // ignore stubs in crt1.o built by old ld64 that was missing S_SYMBOL_STUBS
-                                               case S_ZEROFILL:
-                                               case S_COALESCED:
-                                               case S_4BYTE_LITERALS:
-                                               case S_8BYTE_LITERALS:
-                                               case S_16BYTE_LITERALS:
-                                               case S_CSTRING_LITERALS:
-                                                       {
-                                                               BaseAtom* newAtom = new SymbolAtom<A>(*this, &sym, section);
-                                                               std::map<uint32_t, BaseAtom*>::iterator pos = fAddrToAtom.find(sym.n_value());
-                                                               if ( pos != fAddrToAtom.end() ) {
-                                                                       // another label to an existing address
-                                                                       // make this one be the real one and followed by the previous 
-                                                                       BaseAtom* existingAtom = pos->second;
-                                                                       //fprintf(stderr, "new atom %s has same address as existing atom %s\n", newAtom->getDisplayName(), existingAtom->getDisplayName());
-                                                                       new Reference<A>(A::kFollowOn, AtomAndOffset(newAtom), AtomAndOffset(existingAtom));
-                                                                       newAtom->setSize(0);
-                                                               }
-                                                               else {
-                                                                       fAddrToAtom[sym.n_value()] = newAtom;
-                                                               }
-                                                               if ( ! suppress )
-                                                                       fAtoms.push_back(newAtom);
-                                                               }
-                                                       break;
-                                               case S_SYMBOL_STUBS:
-                                               case S_LAZY_SYMBOL_POINTERS:
-                                               case S_NON_LAZY_SYMBOL_POINTERS:
-                                                       // ignore symboled stubs produces by old ld64
-                                                       break;
-                                               default:
-                                                       fprintf(stderr, "ld64 warning: symbol %s found in unsupported section in %s\n",
-                                                               &fStrings[sym.n_strx()], this->getPath());
+                                       if ( strncmp(&fStrings[sym.n_strx()], "__dtrace_probe$", 15) == 0 ) {
+                                               // ignore dtrace probe labels 
+                                               fHasDTraceProbes = true;
+                                       }
+                                       else if ( fStrings[sym.n_strx()] == 'L' ) {
+                                               // ignore L labels, <rdar://problem/3962731>
+                                       }
+                                       else {
+                                               // ignore labels for atoms in other sections
+                                               switch ( section->flags() & SECTION_TYPE ) {
+                                                       case S_REGULAR:
+                                                               if ( (sym.n_desc() & N_WEAK_DEF) && strcmp(section->sectname(), "__picsymbolstub1__TEXT") == 0 )
+                                                                       suppress = true; // ignore stubs in crt1.o built by old ld64 that was missing S_SYMBOL_STUBS
+                                                       case S_ZEROFILL:
+                                                       case S_COALESCED:
+                                                       case S_4BYTE_LITERALS:
+                                                       case S_8BYTE_LITERALS:
+                                                       case S_16BYTE_LITERALS:
+                                                       case S_CSTRING_LITERALS:
+                                                               {
+                                                                       BaseAtom* newAtom;
+                                                                       std::map<uint32_t, BaseAtom*>::iterator pos = fAddrToAtom.find(sym.n_value());
+                                                                       if ( (pos != fAddrToAtom.end()) && (strcmp(pos->second->getSectionName(), section->sectname())==0) ) {
+                                                                               // another label to an existing address in the same section, make this an alias
+                                                                               newAtom = new SymbolAliasAtom<A>(&fStrings[sym.n_strx()], &sym, *pos->second);
+                                                                       }
+                                                                       else {
+                                                                               // make SymbolAtom atom for this address
+                                                                               newAtom = new SymbolAtom<A>(*this, &sym, section);
+                                                                               // don't add symbols at end of section to addr->atom map
+                                                                               if ( sym.n_value() != sectionEndAddr )
+                                                                                       fAddrToAtom[sym.n_value()] = newAtom;
+                                                                       }
+                                                                       if ( ! suppress )
+                                                                               fAtoms.push_back(newAtom);
+                                                                       }
+                                                               break;
+                                                       case S_SYMBOL_STUBS:
+                                                       case S_LAZY_SYMBOL_POINTERS:
+                                                       case S_NON_LAZY_SYMBOL_POINTERS:
+                                                               // ignore symboled stubs produces by old ld64
+                                                               break;
+                                                       default:
+                                                               fprintf(stderr, "ld: warning symbol %s found in unsupported section in %s\n",
+                                                                       &fStrings[sym.n_strx()], this->getPath());
+                                               }
                                        }
                                }
                        }
                        else if ( (type == N_UNDF) && (sym.n_value() != 0) ) {
                                fAtoms.push_back(new TentativeAtom<A>(*this, &sym));
                        }
-                       else if ( (type == N_ABS) && (strncmp(&fStrings[sym.n_strx()], ".objc_class_name_", 16) == 0) ) {
-                               fAppleObjc = true;
+                       else if ( type == N_ABS ) {
+                               const char* symName = &fStrings[sym.n_strx()];
+                               if ( strncmp(symName, ".objc_class_name_", 16) == 0 ) {
+                                       // ignore .objc_class_name_* symbols 
+                                       fAppleObjc = true;
+                               }
+                               else if ( strcmp(&symName[strlen(symName)-3], ".eh") == 0 ) {
+                                       // ignore empty *.eh symbols
+                               }
+                               else {
+                                       BaseAtom* abAtom = new AbsoluteAtom<A>(*this, &sym);
+                                       fAtoms.push_back(abAtom);
+                                       fAddrToAbsoluteAtom[sym.n_value()] = abAtom;
+                               }
+                       }
+                       else if ( type == N_INDR ) {
+                               fHaveIndirectSymbols = true;
                        }
                }
        }
 
-       // sort SymbolAtoms by address
-       std::sort(fAtoms.begin(), fAtoms.end(), SymbolAtomSorter<A>(fAddrToAtom));
-
        // add all fixed size anonymous atoms from special sections
        for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                uint32_t atomSize = 0;
@@ -1146,7 +1562,36 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                        // gcc sometimes over aligns class structure
                                        uint32_t align = 1 << sect->align();
                                        atomSize = ((12 * sizeof(pint_t)) + align-1) & (-align);
+                               }
+                               // get objc Garbage Collection info
+                               else if ( ((strcmp(sect->sectname(), "__image_info") == 0) && (strcmp(sect->segname(), "__OBJC") == 0))
+                                          || ((strncmp(sect->sectname(), "__objc_imageinfo", 16) == 0) && (strcmp(sect->segname(), "__DATA") == 0)) ) {
+                                       //      struct objc_image_info  {
+                                       //              uint32_t        version;        // initially 0
+                                       //              uint32_t        flags;
+                                       //      };
+                                       // #define OBJC_IMAGE_SUPPORTS_GC   2
+                                       // #define OBJC_IMAGE_GC_ONLY       4
+                                       //
+                                       const uint32_t* contents = (uint32_t*)(((char*)fHeader) + sect->offset());
+                                       if ( (sect->size() >= 8) && (contents[0] == 0) ) {
+                                               uint32_t flags = E::get32(contents[1]);
+                                               if ( (flags & 4) == 4 )
+                                                       fObjConstraint = ObjectFile::Reader::kObjcGC;
+                                               else if ( (flags & 2) == 2 )
+                                                       fObjConstraint = ObjectFile::Reader::kObjcRetainReleaseOrGC;
+                                               else
+                                                       fObjConstraint = ObjectFile::Reader::kObjcRetainRelease;
+                                               if ( (flags & 1) == 1 )
+                                                       fReplacementClasses = true;
+                                               // don't make atom for this section
+                                               atomSize = sect->size();
+                                               suppress = true;
                                        }
+                                       else {
+                                               fprintf(stderr, "can't parse __OBJC/__image_info section in %s\n", fPath);
+                                       }
+                               }
                                break;
                }
                if ( atomSize != 0 ) {
@@ -1168,7 +1613,9 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                if ( ((sect->flags() & SECTION_TYPE) == S_CSTRING_LITERALS) || strcmp(sect->sectname(), "__cstring") == 0 ) {
                        uint32_t stringLen;
                        uint32_t stringAddr;
-                       BaseAtom* firstEmptyString = NULL;
+                       BaseAtom* mostAlignedEmptyString = NULL;
+                       uint32_t mostAlignedEmptyStringTrailingZeros = 0;
+                       std::vector<std::pair<uint32_t,BaseAtom*> > emptyStrings;
                        for(uint32_t sectOffset=0; sectOffset < sect->size(); sectOffset += stringLen) {
                                stringAddr = sect->addr() + sectOffset;
                                stringLen  = strlen((char*)(fHeader) + sect->offset() + sectOffset) + 1;
@@ -1176,13 +1623,15 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                if ( fAddrToAtom.find(stringAddr) == fAddrToAtom.end() ) {
                                        BaseAtom* newAtom = new AnonymousAtom<A>(*this, sect, stringAddr, stringLen);
                                        if ( stringLen == 1 ) {
-                                               // because of padding it may look like there are lots of empty strings
-                                               // map them all to the first empty string
-                                               if ( firstEmptyString == NULL ) {
-                                                       firstEmptyString = newAtom;
-                                                       fAtoms.push_back(firstEmptyString);
+                                               // because of padding it may look like there are lots of empty strings, keep track of all
+                                               emptyStrings.push_back(std::make_pair<uint32_t,BaseAtom*>(stringAddr, newAtom));
+                                               // record empty string with greatest alignment requirement
+                                               uint32_t stringAddrTrailingZeros = (stringAddr==0) ? sect->align() : __builtin_ctz(stringAddr);
+                                               if ( (mostAlignedEmptyString == NULL) 
+                                                       || ( stringAddrTrailingZeros > mostAlignedEmptyStringTrailingZeros) ) {
+                                                       mostAlignedEmptyString = newAtom;
+                                                       mostAlignedEmptyStringTrailingZeros = stringAddrTrailingZeros;
                                                }
-                                               fAddrToAtom[stringAddr] = firstEmptyString;
                                        }
                                        else {
                                                fAtoms.push_back(newAtom);
@@ -1190,14 +1639,30 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                        }
                                }
                        }
+                       // map all uses of empty strings to the most aligned one
+                       if ( mostAlignedEmptyString != NULL ) {
+                               // make most aligned atom a real atom
+                               fAtoms.push_back(mostAlignedEmptyString);
+                               // map all other empty atoms to this one
+                               for (std::vector<std::pair<uint32_t,BaseAtom*> >::iterator it=emptyStrings.begin(); it != emptyStrings.end(); it++) {
+                                       fAddrToAtom[it->first] = mostAlignedEmptyString;
+                               }
+                       }
                }
        }
 
+       // sort all atoms so far by address and section
+       std::sort(fAtoms.begin(), fAtoms.end(), BaseAtomSorter());
+
+       //fprintf(stderr, "sorted atoms:\n");
+       //for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) 
+       //      fprintf(stderr, "0x%08llX %s\n", (*it)->getObjectAddress(), (*it)->getDisplayName());
+
        // create atoms to cover any non-debug ranges not handled above
        for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                pint_t sectionStartAddr = sect->addr();
                pint_t sectionEndAddr   = sect->addr() + sect->size();
-               const bool setFollowOnAtom = ((fHeader->flags() & MH_SUBSECTIONS_VIA_SYMBOLS) == 0);
+               const bool setFollowOnAtom = ! this->canScatterAtoms();
                if ( sect->size() != 0 ) {
                        // ignore dwarf sections.  If ld every supports processing dwarf, this logic will need to change
                        if ( (sect->flags() & S_ATTR_DEBUG) != 0 ) {
@@ -1223,26 +1688,26 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                                BaseAtom* previousAtom = NULL;
                                                if ( fAddrToAtom.find(sectionStartAddr) == fAddrToAtom.end() ) {
                                                        BaseAtom* newAtom = new AnonymousAtom<A>(*this, sect, sect->addr(), 0);
-                                                       fAtoms.push_back(newAtom);
                                                        fAddrToAtom[sect->addr()] = newAtom;
+                                                       fAtoms.push_back(newAtom);
                                                        previousAtomAddr = sectionStartAddr;
                                                        previousAtom = newAtom;
+                                                       std::sort(fAtoms.begin(), fAtoms.end(), BaseAtomSorter());
                                                }
                                                // calculate size of all atoms in this section and add follow-on references
-                                               for (std::map<uint32_t, BaseAtom*>::iterator it=fAddrToAtom.begin(); it != fAddrToAtom.end(); it++) {
-                                                       // note: this algorithm depends on the map iterator returning entries in address order
-                                                       if ( (it->first >= sectionStartAddr) && (it->first < sectionEndAddr) ) {
-                                                               //fprintf(stderr, "  atom %s in section\n", it->second->getDisplayName());
-                                                               if ( previousAtom != NULL ) {
-                                                                       previousAtom->setSize(it->first - previousAtomAddr);
-                                                                       // FIX FIX: this setting of followOn atoms does not work when there are multiple
-                                                                       // labels for the same atom
-                                                                       if ( setFollowOnAtom && (it->second != previousAtom) )
-                                                                               makeReference(A::kFollowOn, previousAtomAddr, it->first);
+                                               for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
+                                                       BaseAtom* atom = (BaseAtom*)(*it);
+                                                       uint32_t atomAddr = atom->getObjectAddress();
+                                                       if ( atom->getSectionRecord() == sect ) {
+                                                               //fprintf(stderr, "addr=0x%08X, atom=%s\n", atomAddr, atom->getDisplayName());
+                                                               if ( (previousAtom != NULL) && (previousAtomAddr != atomAddr) ) {
+                                                                       previousAtom->setSize(atomAddr - previousAtomAddr);
+                                                                       if ( setFollowOnAtom && (atom != previousAtom) )
+                                                                               new Reference<A>(A::kFollowOn, AtomAndOffset(previousAtom), AtomAndOffset(atom));
                                                                }
-                                                               previousAtomAddr = it->first;
-                                                               previousAtom = it->second;
-                                                       }
+                                                               previousAtomAddr = atomAddr;
+                                                               previousAtom = atom;
+                                                       } 
                                                }
                                                if ( previousAtom != NULL ) {
                                                        // set last atom in section
@@ -1254,72 +1719,62 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                }
        }
 
-       // add relocation based references
-       for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
-               // ignore dwarf sections.  If ld every supports processing dwarf, this logic will need to change
-               if ( (sect->flags() & S_ATTR_DEBUG) == 0 ) {
-                       switch ( sect->flags() & SECTION_TYPE ) {
-                               case S_SYMBOL_STUBS:
-                               case S_LAZY_SYMBOL_POINTERS:
-                                       // we ignore compiler generated stubs, so ignore those relocs too
-                                       break;
-                               default:
-                                       const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fHeader) + sect->reloff());
-                                       const uint32_t relocCount = sect->nreloc();
-                                       //fprintf(stderr, "relocCount = %d in section %s\n", relocCount, sect->sectname());
-                                       for (uint32_t r = 0; r < relocCount; ++r) {
-                                               try {
-                                                       if ( addRelocReference(sect, &relocs[r]) )
-                                                               ++r; // skip next
-                                               }
-                                               catch (const char* msg) {
-                                                       throwf("in section %s,%s reloc %u: %s\n", sect->segname(), sect->sectname(), r, msg);
+       // check for object file that defines no objc classes, but uses objc classes
+       // check for dtrace provider info
+       for (uint32_t i=undefinedStartIndex; i < undefinedEndIndex; ++i) {
+               const macho_nlist<P>& sym = fSymbols[i];
+               if ( (sym.n_type() & N_STAB) == 0 ) {
+                       if ( (sym.n_type() & N_TYPE) == N_UNDF ) {
+                               const char* undefinedName = &fStrings[sym.n_strx()];
+                               if ( !fAppleObjc && (strncmp(undefinedName, ".objc_class_name_", 16) == 0) ) {
+                                       fAppleObjc = true;
+                               }
+                               else if ( strncmp(undefinedName, "___dtrace_", 10) == 0 ) {
+                                       if ( strchr(undefinedName, '$') != NULL  ) {
+                                               if ( (strncmp(&undefinedName[10], "probe$", 6) != 0) && (strncmp(&undefinedName[10], "isenabled$", 10) != 0) ) {
+                                                       // any undefined starting with __dtrace_*$ that is not ___dtrace_probe$* or ___dtrace_isenabled$*
+                                                       // is extra provider info
+                                                       fDtraceProviderInfo.push_back(undefinedName);
                                                }
                                        }
+                               }
                        }
                }
        }
+       
+       // add relocation based references to sections that have atoms with pending names
+       for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+               if ( fSectionsWithAtomsPendingAName.count(sect) != 0 )
+                       addReferencesForSection(sect);
+       }
+       
+       // update any anonymous atoms that need references built in order to name themselves
+       for (typename std::vector<AnonymousAtom<A>*>::iterator it=fAtomsPendingAName.begin(); it != fAtomsPendingAName.end(); it++) {
+               (*it)->resolveName();
+       }
 
-       // check of object file that defines no classes, but uses classes
-       if ( !fAppleObjc ) {
-               for (uint32_t i=undefinedStartIndex; i < undefinedEndIndex; ++i) {
-                       const macho_nlist<P>& sym = fSymbols[i];
-                       if ( (sym.n_type() & N_STAB) == 0 ) {
-                               if ( ((sym.n_type() & N_TYPE) == N_UNDF) && (strncmp(&fStrings[sym.n_strx()], ".objc_class_name_", 16) == 0) ) {
-                                       fAppleObjc = true;
-                                       break;
-                               }
-                       }
-               }
+       // add relocation based references to other sections
+       for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+               if ( fSectionsWithAtomsPendingAName.count(sect) == 0 )
+                       addReferencesForSection(sect);
        }
 
+
        // add objective-c references
        if ( fAppleObjc ) {
                for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
-                       // ignore dwarf sections.  If ld every supports processing dwarf, this logic will need to change
-                       if ( (strcmp(sect->sectname(), "__class") == 0) && (strcmp(sect->segname(), "__OBJC") == 0) ) {
-                               // gcc sometimes over aligns class structure
-                               uint32_t align = 1 << sect->align();
-                               uint32_t classSize = ((12 * sizeof(pint_t)) + align-1) & (-align);
-                               for (uint32_t offset = 0; offset < sect->size(); offset += classSize) {
-                                       // add by-name reference to super class
-                                       pint_t superClassNameAddr =  P::getP(*(pint_t*)(((uint8_t*)fHeader) + sect->offset() + offset + sizeof(pint_t)));
-                                       if ( superClassNameAddr != 0 ) {
-                                               const char* superStr = (char*)(fHeader) + sect->offset() + superClassNameAddr - sect->addr();
-                                               const char* superClassName;
-                                               asprintf((char**)&superClassName, ".objc_class_name_%s", superStr);
-                                               makeByNameReference(A::kNoFixUp, sect->addr()+offset+sizeof(pint_t), superClassName, 0);
-                                       }
-                               }
-                       }
-                       else if ( (strcmp(sect->sectname(), "__cls_refs") == 0) && (strcmp(sect->segname(), "__OBJC") == 0) ) {
+                       if ( (strcmp(sect->sectname(), "__cls_refs") == 0) && (strcmp(sect->segname(), "__OBJC") == 0) ) {
                                for (uint32_t offset = 0; offset < sect->size(); offset += sizeof(pint_t)) {
-                                       // scan through __cls_refs and add by-name reference for each required class
-                                       uint32_t classNameAddr =  P::getP(*(pint_t*)(((uint8_t*)fHeader) + sect->offset() + offset));
-                                       const char* classStr = (char*)(fHeader) + sect->offset() + classNameAddr - sect->addr();
-                                       const char* className;
-                                       asprintf((char**)&className, ".objc_class_name_%s", classStr);
-                                       makeByNameReference(A::kNoFixUp, sect->addr()+offset, className, 0);
+                                       AtomAndOffset ao = this->findAtomAndOffset(sect->addr()+offset);
+                                       ObjectFile::Reference* classRef = ao.atom->getReferences()[0];
+                                       if ( classRef->getFixUpOffset() == 0 ) {
+                                               const char* classStr = classRef->getTargetName();
+                                               if ( strncmp(classStr, "cstring=", 8) == 0 ) {
+                                                       const char* className;
+                                                       asprintf((char**)&className, ".objc_class_name_%s", &classStr[8]);
+                                                       new Reference<A>(A::kNoFixUp, ao, className, 0);
+                                               }
+                                       }
                                }
                        }
                }
@@ -1332,7 +1787,7 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                pint_t nonLazyPtrValue = P::getP(*((pint_t*)((char*)(fHeader)+fileOffset)));
                makeReference(A::kPointer, localNonLazy->fAddress, nonLazyPtrValue);
        }
-
+       
        // add implicit direct reference from each C++ function to its eh info
        for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                if ( ((sect->flags() & SECTION_TYPE) == S_COALESCED) && (strcmp(sect->sectname(), "__eh_frame") == 0) ) {
@@ -1349,6 +1804,48 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                }
        }
 
+       // add command line aliases
+       for(std::vector<ObjectFile::ReaderOptions::AliasPair>::const_iterator it = fOptions.fAliases.begin(); it != fOptions.fAliases.end(); ++it) { 
+               BaseAtom* target = this->findAtomByName(it->realName);
+               if ( (target != NULL) && target->getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn )
+                       fAtoms.push_back(new SymbolAliasAtom<A>(it->alias, NULL, *target));
+       }
+
+       // add dtrace probe locations
+       if ( fHasDTraceProbes ) {
+               for (uint32_t i=0; i < fSymbolCount; ++i) {
+                       const macho_nlist<P>& sym = fSymbols[i];
+                       if ( (sym.n_type() & N_STAB) == 0 ) {
+                               if ( (sym.n_type() & N_TYPE) == N_SECT ) {
+                                       const char* symbolName = &fStrings[sym.n_strx()];
+                                       if ( strncmp(symbolName, "__dtrace_probe$", 15) == 0 ) {
+                                               //fprintf(stderr, "adding dtrace probe at 0x%08llX %s\n", sym.n_value(), symbolName);
+                                               makeByNameReference(A::kDtraceProbe, sym.n_value(), symbolName, 0);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       // turn indirect symbols int SymbolAliasAtom 
+       if ( fHaveIndirectSymbols ) {
+               for (uint32_t i=0; i < fSymbolCount; ++i) {
+                       const macho_nlist<P>& sym = fSymbols[i];
+                       if ( (sym.n_type() & N_STAB) == 0 ) {
+                               if ( (sym.n_type() & N_TYPE) == N_INDR ) {
+                                       const char* aliasName = &fStrings[sym.n_strx()];
+                                       const char* targetName = &fStrings[sym.n_value()];
+                                       //fprintf(stderr, "found alias %s for %s\n", aliasName, targetName);
+                                       BaseAtom* target = this->findAtomByName(targetName);
+                                       // only currently support N_INDR based aliases to something in the same .o file 
+                                       if ( target != NULL ) {
+                                               fAtoms.push_back(new SymbolAliasAtom<A>(aliasName, &sym, *target));
+                                               //fprintf(stderr, "creating alias %s for %s\n", aliasName, targetName);
+                                       }
+                               }
+                       }
+               }
+       }
 
        //for (std::map<uint32_t, BaseAtom*>::iterator it=fAddrToAtom.begin(); it != fAddrToAtom.end(); it++) {
        //      fprintf(stderr, "[0x%0X -> 0x%0llX) : %s\n", it->first, it->first+it->second->getSize(), it->second->getDisplayName());
@@ -1363,7 +1860,7 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                // if can't parse dwarf, warn and give up
                                fDwarfTranslationUnitFile = NULL;
                                fDwarfTranslationUnitDir = NULL;
-                               fprintf(stderr, "ld64: warning can't parse dwarf compilation unit info in %s\n", this->getPath());
+                               fprintf(stderr, "ld: warning can't parse dwarf compilation unit info in %s\n", this->getPath());
                                fDebugInfo = kDebugInfoNone;
                        }
                }
@@ -1372,7 +1869,8 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
        // add line number info to atoms from dwarf
        if ( (fDebugInfo == kDebugInfoDwarf) && (fOptions.fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone) ) {
                // file with just data will have no __debug_line info
-               if ( (fDwarfDebugLineSect != NULL) && (fDwarfDebugLineSect->size() != 0) && (fAddrToAtom.size() != 0) ) {
+               if ( (fDwarfDebugLineSect != NULL) && (fDwarfDebugLineSect->size() != 0) && (fAddrToAtom.size() != 0)
+                       && (fDwarfDebugInfoSect != NULL) && (fDwarfDebugInfoSect->size() != 0) ) {
                        // validate stmt_list
                        if ( (stmtList != (uint64_t)-1) && (stmtList < fDwarfDebugLineSect->size()) ) {
                                const uint8_t* debug_line = (uint8_t*)(fHeader) + fDwarfDebugLineSect->offset();
@@ -1385,6 +1883,8 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                        uint32_t curAtomAddress = 0;
                                        uint32_t curAtomSize = 0;
                                        while ( line_next (lines, &result, line_stop_pc) ) {
+                                               //fprintf(stderr, "curAtom=%p, result.pc=0x%llX, result.line=%llu, result.end_of_sequence=%d, curAtomAddress=0x%X, curAtomSize=0x%X\n",
+                                               //              curAtom, result.pc, result.line, result.end_of_sequence, curAtomAddress, curAtomSize);
                                                // work around weird debug line table compiler generates if no functions in __text section
                                                if ( (curAtom == NULL) && (result.pc == 0) && result.end_of_sequence && (result.file == 1))
                                                        continue;
@@ -1402,9 +1902,28 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                                        curAtom                 = ao.atom;
                                                        if ( curAtom == NULL )
                                                                break; // file has line info but no functions
-                                                       curAtomOffset   = ao.offset;
-                                                       curAtomAddress  = result.pc - ao.offset;
-                                                       curAtomSize             = curAtom->getSize();
+                                                       if ( result.end_of_sequence && (curAtomAddress+curAtomSize < result.pc) ) {     
+                                                               // a one line function can be returned by line_next() as one entry with pc at end of blob
+                                                               // look for alt atom starting at end of previous atom
+                                                               uint32_t previousEnd = curAtomAddress+curAtomSize;
+                                                               AtomAndOffset alt = this->findAtomAndOffset(previousEnd);
+                                                               if ( result.pc <= previousEnd - alt.offset + alt.atom->getSize() ) {
+                                                                       curAtom                 = alt.atom;
+                                                                       curAtomOffset   = alt.offset;
+                                                                       curAtomAddress  = previousEnd - alt.offset;
+                                                                       curAtomSize             = curAtom->getSize();
+                                                               }
+                                                               else {
+                                                                       curAtomOffset   = ao.offset;
+                                                                       curAtomAddress  = result.pc - ao.offset;
+                                                                       curAtomSize             = curAtom->getSize();
+                                                               }
+                                                       }
+                                                       else {
+                                                               curAtomOffset   = ao.offset;
+                                                               curAtomAddress  = result.pc - ao.offset;
+                                                               curAtomSize             = curAtom->getSize();
+                                                       }
                                                }
                                                const char* filename;
                                                std::map<uint32_t,const char*>::iterator pos = fDwarfIndexToFile.find(result.file);
@@ -1429,7 +1948,7 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                        line_free(lines);
                                }
                                else {
-                                       fprintf(stderr, "ld64: warning could not parse dwarf line number info in %s\n", this->getPath());
+                                       fprintf(stderr, "ld: warning could not parse dwarf line number info in %s\n", this->getPath());
                                }
                        }
                }
@@ -1480,10 +1999,13 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                                        case N_OSO:
                                                        case N_OPT:
                                                        case N_LSYM:
+                                                       case N_RSYM:
+                                                       case N_PSYM:
                                                                // not associated with an atom, just copy
                                                                stab.string = symString;
                                                                break;
                                                        case N_GSYM:
+                                                       {
                                                                // n_value field is NOT atom address ;-(
                                                                // need to find atom by name match
                                                                const char* colon = strchr(symString, ':');
@@ -1513,6 +2035,7 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                                                        useStab = false;
                                                                }
                                                                break;
+                                                       }
                                                        case N_FUN:
                                                                // old style stabs without BNSYM
                                                                state = inFun;
@@ -1551,6 +2074,7 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                                                break;
                                                        case N_LCSYM:
                                                        case N_STSYM:
+                                                       {
                                                                BaseAtom* nestedAtom = (BaseAtom*)this->findAtomAndOffset(sym->n_value()).atom;
                                                                if ( nestedAtom != NULL ) {
                                                                        stab.atom = nestedAtom;
@@ -1561,6 +2085,7 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                                                                type, (uint64_t)sym->n_value(), path);
                                                                }
                                                                break;
+                                                       }
                                                        case N_LBRAC:
                                                        case N_RBRAC:
                                                        case N_SLINE:
@@ -1620,12 +2145,6 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                }
        }
 
-       // sort references in each atom
-       for (std::vector<ObjectFile::Atom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
-               BaseAtom* atom = (BaseAtom*)(*it);
-               atom->sortReferences();
-       }
-       
 #if 0
        // special case precompiled header .o file (which has no content) to have one empty atom
        if ( fAtoms.size() == 0 ) {
@@ -1637,8 +2156,70 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                }
        }
 #endif
+
+       // sort all atoms by address
+       std::sort(fAtoms.begin(), fAtoms.end(), BaseAtomSorter());
+
+       // set ordinal and sort references in each atom
+       uint32_t index = fOrdinalBase;
+       for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
+               BaseAtom* atom = (BaseAtom*)(*it);
+               atom->setOrdinal(index++);
+               atom->sortReferences();
+       }
+       
+}
+
+
+template <>
+void Reader<ppc>::setCpuConstraint(uint32_t cpusubtype)
+{
+       switch (cpusubtype) {
+               case CPU_SUBTYPE_POWERPC_ALL:
+                       fCpuConstraint = ObjectFile::Reader::kCpuAny;
+                       break;
+               case CPU_SUBTYPE_POWERPC_750:
+                       fCpuConstraint = ObjectFile::Reader::kCpuG3;
+                       break;
+               case CPU_SUBTYPE_POWERPC_7400:
+               case CPU_SUBTYPE_POWERPC_7450:
+                       fCpuConstraint = ObjectFile::Reader::kCpuG4;
+                       break;
+               case CPU_SUBTYPE_POWERPC_970:
+                       fCpuConstraint = ObjectFile::Reader::kCpuG5;
+                       break;
+               default:
+                       fprintf(stderr, "ld: warning, unknown cpu-sub-type 0x%08X in %s\n", cpusubtype, fPath);
+       }
+}
+
+
+template <typename A>
+void Reader<A>::setCpuConstraint(uint32_t cpusubtype)
+{
+       // no cpu sub types for this architecture
+}
+
+template <typename A>
+void Reader<A>::addDtraceExtraInfos(uint32_t probeAddr, const char* providerName)
+{
+       // for every ___dtrace_stability$* and ___dtrace_typedefs$* undefine with
+       // a matching provider name, add a by-name kDtraceTypeReference at probe site
+       const char* dollar = strchr(providerName, '$');
+       if ( dollar != NULL ) {
+               int providerNameLen = dollar-providerName+1;
+               for ( std::vector<const char*>::iterator it = fDtraceProviderInfo.begin(); it != fDtraceProviderInfo.end(); ++it) {
+                       const char* typeDollar = strchr(*it, '$');
+                       if ( typeDollar != NULL ) {
+                               if ( strncmp(typeDollar+1, providerName, providerNameLen) == 0 ) {
+                                       makeByNameReference(A::kDtraceTypeReference, probeAddr, *it, 0);
+                               }
+                       }
+               }
+       }
 }
 
+
 template <>
 void Reader<x86_64>::validSectionType(uint8_t type)
 {
@@ -1663,7 +2244,7 @@ bool Reader<A>::getTranslationUnitSource(const char** dir, const char** name) co
        if ( fDebugInfo == kDebugInfoDwarf ) {
                *dir = fDwarfTranslationUnitDir;
                *name = fDwarfTranslationUnitFile;
-               return true;
+               return (fDwarfTranslationUnitFile != NULL);
        }
        return false;
 }
@@ -1679,7 +2260,7 @@ BaseAtom* Reader<A>::findAtomByName(const char* name)
                }
        }
        // try all atoms, because this might have been a tentative definition
-       for (std::vector<ObjectFile::Atom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
+       for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
                BaseAtom* atom = (BaseAtom*)(*it);
                const char* atomName = atom->getName();
                if ( (atomName != NULL) && (strcmp(atomName, name) == 0) ) {
@@ -1747,10 +2328,11 @@ Reference<x86_64>* Reader<x86_64>::makeReferenceToSymbol(Kinds kind, uint32_t at
 {
        // x86_64 uses external relocations everywhere, so external relocations do not imply by-name references
        // instead check scope of target
-       if ( ((toSymbol->n_type() & N_TYPE) == N_SECT) && ((toSymbol->n_type() & N_EXT) == 0) ) 
+       const char* symbolName = &fStrings[toSymbol->n_strx()];
+       if ( ((toSymbol->n_type() & N_TYPE) == N_SECT) && (((toSymbol->n_type() & N_EXT) == 0) || (symbolName[0] == 'L')) ) 
                return new Reference<x86_64>(kind, findAtomAndOffset(atAddr), findAtomAndOffset(toSymbol->n_value(), toSymbol->n_value()+toOffset));
        else
-               return new Reference<x86_64>(kind, findAtomAndOffset(atAddr), &fStrings[toSymbol->n_strx()], toOffset);
+               return new Reference<x86_64>(kind, findAtomAndOffset(atAddr), symbolName, toOffset);
 }
 
 
@@ -1768,7 +2350,7 @@ Reference<x86_64>* Reader<x86_64>::makeReferenceToEH(const char* ehName, pint_t
                        return makeReference(x86_64::kNoFixUp, funcAddr, ehAtomAddress);
                }
        }
-       fprintf(stderr, "ld64: warning, can't find matching function for eh symbol %s\n", ehName);
+       fprintf(stderr, "ld: warning, can't find matching function for eh symbol %s\n", ehName);
        return NULL;
 }
 
@@ -2197,7 +2779,15 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                        }
                                        if ( reloc->r_extern() ) {
                                                offsetInTarget = srcAddr + displacement;
-                                               if ( weakImport )
+                                               if ( strncmp(targetName, "___dtrace_probe$", 16) == 0 ) {
+                                                       makeByNameReference(A::kDtraceProbeSite, srcAddr, targetName, 0);
+                                                       addDtraceExtraInfos(srcAddr, &targetName[16]);
+                                               }
+                                               else if ( strncmp(targetName, "___dtrace_isenabled$", 20) == 0 ) {
+                                                       makeByNameReference(A::kDtraceIsEnabledSite, srcAddr, targetName, 0);
+                                                       addDtraceExtraInfos(srcAddr, &targetName[20]);
+                                               }
+                                               else if ( weakImport )
                                                        makeByNameReference(A::kBranch24WeakImport, srcAddr, targetName, offsetInTarget);
                                                else
                                                        makeByNameReference(A::kBranch24, srcAddr, targetName, offsetInTarget);
@@ -2206,7 +2796,16 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                                dstAddr = srcAddr + displacement;
                                                // if this is a branch to a stub, we need to see if the stub is for a weak imported symbol
                                                ObjectFile::Atom* atom = findAtomAndOffset(dstAddr).atom;
-                                               if ( (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn)
+                                               targetName = atom->getName();
+                                               if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_probe$", 16) == 0) ) {
+                                                       makeByNameReference(A::kDtraceProbeSite, srcAddr, targetName, 0);
+                                                       addDtraceExtraInfos(srcAddr, &targetName[16]);
+                                               }
+                                               else if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_isenabled$", 20) == 0) ) {
+                                                       makeByNameReference(A::kDtraceIsEnabledSite, srcAddr, targetName, 0);
+                                                       addDtraceExtraInfos(srcAddr, &targetName[20]);
+                                               }
+                                               else if ( (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn)
                                                        && ((AnonymousAtom<A>*)atom)->isWeakImportStub() )
                                                        makeReference(A::kBranch24WeakImport, srcAddr, dstAddr);
                                                else
@@ -2246,7 +2845,17 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                        }
                                        else {
                                                dstAddr = (nextReloc->r_address() << 16) + ((uint32_t)lowBits & 0x0000FFFF);
-                                               makeReference(A::kAbsLow16, srcAddr, dstAddr);
+                                               if ( reloc->r_symbolnum() == R_ABS ) {
+                                                       // find absolute symbol that corresponds to pointerValue
+                                                       std::map<uint32_t, BaseAtom*>::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
+                                                       if ( pos != fAddrToAbsoluteAtom.end() ) 
+                                                               makeByNameReference(A::kAbsLow16, srcAddr, pos->second->getName(), 0);
+                                                       else
+                                                               makeReference(A::kAbsLow16, srcAddr, dstAddr);
+                                               }
+                                               else {
+                                                       makeReference(A::kAbsLow16, srcAddr, dstAddr);
+                                               }
                                        }
                                }
                                break;
@@ -2264,7 +2873,17 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                        }
                                        else {
                                                dstAddr = (nextReloc->r_address() << 16) | ((uint32_t)lowBits & 0x0000FFFF);
-                                               makeReference(A::kAbsLow14, srcAddr, dstAddr);
+                                               if ( reloc->r_symbolnum() == R_ABS ) {
+                                                       // find absolute symbol that corresponds to pointerValue
+                                                       std::map<uint32_t, BaseAtom*>::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
+                                                       if ( pos != fAddrToAbsoluteAtom.end() ) 
+                                                               makeByNameReference(A::kAbsLow14, srcAddr, pos->second->getName(), 0);
+                                                       else
+                                                               makeReference(A::kAbsLow14, srcAddr, dstAddr);
+                                               }
+                                               else {
+                                                       makeReference(A::kAbsLow14, srcAddr, dstAddr);
+                                               }
                                        }
                                }
                                break;
@@ -2281,7 +2900,17 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                        }
                                        else {
                                                dstAddr = ((instruction & 0x0000FFFF) << 16) | (nextReloc->r_address() & 0x0000FFFF);
-                                               makeReference(A::kAbsHigh16, srcAddr, dstAddr);
+                                               if ( reloc->r_symbolnum() == R_ABS ) {
+                                                       // find absolute symbol that corresponds to pointerValue
+                                                       std::map<uint32_t, BaseAtom*>::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
+                                                       if ( pos != fAddrToAbsoluteAtom.end() ) 
+                                                               makeByNameReference(A::kAbsHigh16, srcAddr, pos->second->getName(), 0);
+                                                       else
+                                                               makeReference(A::kAbsHigh16, srcAddr, dstAddr);
+                                               }
+                                               else {
+                                                       makeReference(A::kAbsHigh16, srcAddr, dstAddr);
+                                               }
                                        }
                                }
                                break;
@@ -2299,7 +2928,17 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                        }
                                        else {
                                                dstAddr = ((instruction & 0x0000FFFF) << 16) + (int32_t)lowBits;
-                                               makeReference(A::kAbsHigh16AddLow, srcAddr, dstAddr);
+                                               if ( reloc->r_symbolnum() == R_ABS ) {
+                                                       // find absolute symbol that corresponds to pointerValue
+                                                       std::map<uint32_t, BaseAtom*>::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
+                                                       if ( pos != fAddrToAbsoluteAtom.end() ) 
+                                                               makeByNameReference(A::kAbsHigh16AddLow, srcAddr, pos->second->getName(), 0);
+                                                       else
+                                                               makeReference(A::kAbsHigh16AddLow, srcAddr, dstAddr);
+                                               }
+                                               else {
+                                                       makeReference(A::kAbsHigh16AddLow, srcAddr, dstAddr);
+                                               }
                                        }
                                }
                                break;
@@ -2318,13 +2957,24 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                }
                                break;
                        case PPC_RELOC_JBSR:
-                               // this is from -mlong-branch codegen.  We ignore the jump island
+                               // this is from -mlong-branch codegen.  We ignore the jump island and make reference to the real target
                                if ( nextReloc->r_type() != PPC_RELOC_PAIR ) {
                                        printf("PPC_RELOC_JBSR missing following pair\n");
                                        break;
                                }
                                result = true;
                                makeReference(A::kBranch24, srcAddr, nextReloc->r_address());
+                               if ( (instruction & 0x4C000000) == 0x48000000 ) {
+                                       displacement = (instruction & 0x03FFFFFC);
+                                       if ( (displacement & 0x02000000) != 0 )
+                                               displacement |= 0xFC000000;
+                               }
+                               else {
+                                       fprintf(stderr, "bad instruction for BR24 reloc");
+                               }
+                               if ( reloc->r_extern() ) {
+                                       fprintf(stderr, "PPC_RELOC_JBSR should not be using an external relocation");
+                               }
                                break;
                        default:
                                printf("unknown relocation type %d\n", reloc->r_type());
@@ -2468,6 +3118,41 @@ bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* se
                                                printf("PPC_RELOC_SECTDIFF missing following pair\n");
                                                break;
                                        }
+                                       // need to read section content to see if this has an addend, if so adjust addresses
+                                       switch ( sreloc->r_length() ) {
+                                               case 0:
+                                                       if ( (dstAddr - nextRelocValue) != *((uint8_t*)fixUpPtr) ) {
+                                                               if (findAtomAndOffset(dstAddr).atom == findAtomAndOffset(srcAddr).atom )
+                                                                       dstAddr = *((uint8_t*)fixUpPtr) + nextRelocValue;
+                                                               else
+                                                                       nextRelocValue = dstAddr - *((uint8_t*)fixUpPtr);
+                                                       }
+                                                       break;
+                                               case 1:
+                                                       if ( (dstAddr - nextRelocValue) != BigEndian::get16(*((uint16_t*)fixUpPtr)) ) {
+                                                               if (findAtomAndOffset(dstAddr).atom == findAtomAndOffset(srcAddr).atom )
+                                                                       dstAddr = BigEndian::get16(*((uint16_t*)fixUpPtr)) + nextRelocValue;
+                                                               else
+                                                                       nextRelocValue = dstAddr - BigEndian::get16(*((uint16_t*)fixUpPtr));
+                                                       }
+                                                       break;
+                                               case 2:
+                                                       if ( (dstAddr - nextRelocValue) != BigEndian::get32(*fixUpPtr) ) {
+                                                               if (findAtomAndOffset(dstAddr).atom == findAtomAndOffset(srcAddr).atom )
+                                                                       dstAddr = BigEndian::get32(*fixUpPtr) + nextRelocValue;
+                                                               else
+                                                                       nextRelocValue = dstAddr - BigEndian::get32(*fixUpPtr);
+                                                       }
+                                                       break;
+                                               case 3:
+                                                       if ( (dstAddr - nextRelocValue) != BigEndian::get64(*((uint64_t*)fixUpPtr)) ) {
+                                                               if (findAtomAndOffset(dstAddr).atom == findAtomAndOffset(srcAddr).atom )
+                                                                       dstAddr = BigEndian::get64(*((uint64_t*)fixUpPtr)) + nextRelocValue;
+                                                               else
+                                                                       nextRelocValue = dstAddr - BigEndian::get64(*((uint64_t*)fixUpPtr));
+                                                       }
+                                                       break;
+                                       }
                                        makeReference(pointerDiffKindForLength_powerpc(sreloc->r_length()), srcAddr, nextRelocValue, dstAddr);
                                }
                                break;
@@ -2488,6 +3173,8 @@ ppc::ReferenceKinds Reader<ppc>::pointerDiffKindForLength_powerpc(uint8_t r_leng
 {
        if ( r_length == 2 )
                return ppc::kPointerDiff32;
+       else if ( r_length == 1 )
+               return ppc::kPointerDiff16;
        else
                throw "bad diff relocations r_length for ppc architecture";
  }
@@ -2516,35 +3203,74 @@ bool Reader<x86>::addRelocReference(const macho_section<x86::P>* sect, const mac
                switch ( reloc->r_type() ) {
                        case GENERIC_RELOC_VANILLA:
                                {
-                                       if ( reloc->r_length() != 2 )
-                                               throw "bad vanilla relocation length";
-                                       x86::ReferenceKinds kind;
+                                       x86::ReferenceKinds kind = x86::kPointer;
                                        uint32_t pointerValue = E::get32(*fixUpPtr);
                                        if ( reloc->r_pcrel() ) {
-                                               kind = x86::kPCRel32;
-                                               pointerValue += srcAddr + sizeof(uint32_t);
+                                               switch( reloc->r_length() ) {
+                                                       case 0:
+                                                       case 3:
+                                                               throw "bad pc-rel vanilla relocation length";
+                                                       case 1:
+                                                               kind = x86::kPCRel16;
+                                                               pointerValue = srcAddr + (int16_t)E::get16(*((uint16_t*)fixUpPtr)) + sizeof(uint16_t);
+                                                               break;
+                                                       case 2:
+                                                               kind = x86::kPCRel32;
+                                                               pointerValue += srcAddr + sizeof(uint32_t);
+                                                               break;
+                                               }
                                        }
                                        else if ( strcmp(sect->segname(), "__TEXT") == 0 ) {
                                                kind = x86::kAbsolute32;
+                                               if ( reloc->r_length() != 2 )
+                                                       throw "bad vanilla relocation length";
                                        }
                                        else {
                                                kind = x86::kPointer;
+                                               if ( reloc->r_length() != 2 )
+                                                       throw "bad vanilla relocation length";
                                        }
                                        if ( reloc->r_extern() ) {
                                                const macho_nlist<P>* targetSymbol = &fSymbols[reloc->r_symbolnum()];
                                                if ( this->isWeakImportSymbol(targetSymbol) )
                                                        kind = x86::kPointerWeakImport;
                                                const char* targetName = &fStrings[targetSymbol->n_strx()];
-                                               makeByNameReference(kind, srcAddr, targetName, pointerValue);
+                                               if ( strncmp(targetName, "___dtrace_probe$", 16) == 0 ) {
+                                                       makeByNameReference(x86::kDtraceProbeSite, srcAddr, targetName, 0);
+                                                       addDtraceExtraInfos(srcAddr, &targetName[16]);
+                                               }
+                                               else if ( strncmp(targetName, "___dtrace_isenabled$", 20) == 0 ) {
+                                                       makeByNameReference(x86::kDtraceIsEnabledSite, srcAddr, targetName, 0);
+                                                       addDtraceExtraInfos(srcAddr, &targetName[20]);
+                                               }
+                                               else
+                                                       makeByNameReference(kind, srcAddr, targetName, pointerValue);
                                        }
                                        else {
                                                // if this is a branch to a stub, we need to see if the stub is for a weak imported symbol
                                                ObjectFile::Atom* atom = findAtomAndOffset(pointerValue).atom;
-                                               if ( reloc->r_pcrel() && (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn)
+                                               const char* targetName = atom->getName();
+                                               if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_probe$", 16) == 0) ) {
+                                                       makeByNameReference(x86::kDtraceProbeSite, srcAddr, targetName, 0);
+                                                       addDtraceExtraInfos(srcAddr, &targetName[16]);
+                                               }
+                                               else if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_isenabled$", 20) == 0) ) {
+                                                       makeByNameReference(x86::kDtraceIsEnabledSite, srcAddr, targetName, 0);
+                                                       addDtraceExtraInfos(srcAddr, &targetName[20]);
+                                               }
+                                               else if ( reloc->r_pcrel() && (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn)
                                                        && ((AnonymousAtom<x86>*)atom)->isWeakImportStub() )
                                                        makeReference(x86::kPCRel32WeakImport, srcAddr, pointerValue);
-                                               else
+                                               else if ( reloc->r_symbolnum() != R_ABS )
                                                        makeReference(kind, srcAddr, pointerValue);
+                                               else {
+                                                       // find absolute symbol that corresponds to pointerValue
+                                                       std::map<uint32_t, BaseAtom*>::iterator pos = fAddrToAbsoluteAtom.find(pointerValue);
+                                                       if ( pos != fAddrToAbsoluteAtom.end() ) 
+                                                               makeByNameReference(kind, srcAddr, pos->second->getName(), 0);
+                                                       else
+                                                               throwf("R_ABS reloc but no absolute symbol at target address");
+                                               }
                                        }
                                }
                                break;
@@ -2601,10 +3327,40 @@ bool Reader<x86>::addRelocReference(const macho_section<x86::P>* sect, const mac
                                                printf("GENERIC_RELOC_SECTDIFF missing following pair\n");
                                                break;
                                        }
-                                       if ( sreloc->r_length() != 2 )
-                                               throw "bad length for GENERIC_RELOC_SECTDIFF";
-                                       betterDstAddr = LittleEndian::get32(*fixUpPtr);
-                                       makeReferenceWithToBase(x86::kPointerDiff, srcAddr, nextRelocValue, betterDstAddr+nextRelocValue, dstAddr);
+                                       x86::ReferenceKinds kind = x86::kPointerDiff;
+                                       uint32_t contentAddr = 0;
+                                       switch ( sreloc->r_length() ) {
+                                               case 0:
+                                               case 3:
+                                                       throw "bad length for GENERIC_RELOC_SECTDIFF";
+                                               case 1:
+                                                       kind = x86::kPointerDiff16;
+                                                       contentAddr = LittleEndian::get16(*((uint16_t*)fixUpPtr));
+                                                       break;
+                                               case 2:
+                                                       kind = x86::kPointerDiff;
+                                                       contentAddr = LittleEndian::get32(*fixUpPtr);
+                                                       break;
+                                       }
+                                       AtomAndOffset srcao  = findAtomAndOffset(srcAddr);
+                                       AtomAndOffset fromao = findAtomAndOffset(nextRelocValue);
+                                       AtomAndOffset toao   = findAtomAndOffset(dstAddr);
+                                       // check for addend encoded in the section content
+                                       //fprintf(stderr, "addRef: dstAddr=0x%X, nextRelocValue=0x%X, contentAddr=0x%X\n",
+                                       //              dstAddr, nextRelocValue, contentAddr);
+                                       if ( (dstAddr - nextRelocValue) != contentAddr ) {
+                                               if ( toao.atom == srcao.atom )
+                                                       toao.offset += (contentAddr + nextRelocValue) - dstAddr;
+                                               else if ( fromao.atom == srcao.atom )
+                                                       toao.offset += (contentAddr + nextRelocValue) - dstAddr;
+                                               else
+                                                       fromao.offset += (dstAddr - contentAddr) - nextRelocValue;
+                                       }
+                                       //fprintf(stderr, "addRef: src=%s+0x%X, from=%s+0x%X, to=%s+0x%X\n",
+                                       //      srcao.atom->getDisplayName(), srcao.offset, 
+                                       //      fromao.atom->getDisplayName(), fromao.offset, 
+                                       //      toao.atom->getDisplayName(), toao.offset);
+                                       new Reference<x86>(kind, srcao, fromao, toao);
                                }
                                break;
                        case GENERIC_RELOC_PAIR:
@@ -2642,10 +3398,20 @@ bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, con
                        if ( reloc->r_length() != 3 ) 
                                throw "length < 3 and X86_64_RELOC_UNSIGNED not supported";
                        dstAddr = E::get64(*((uint64_t*)fixUpPtr));
-                       if ( reloc->r_extern() ) 
+                       if ( reloc->r_extern() ) {
                                makeReferenceToSymbol(x86_64::kPointer, srcAddr, targetSymbol, dstAddr);
-                       else
+                       }
+                       else {
                                makeReference(x86_64::kPointer, srcAddr, dstAddr);
+                               // verify that dstAddr is in the section being targeted
+                               int sectNum = reloc->r_symbolnum();
+                               const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)fSegment + sizeof(macho_segment_command<P>));
+                               const macho_section<P>* const targetSection = &sectionsStart[sectNum-1];
+                               if ( (dstAddr < targetSection->addr()) || (dstAddr > (targetSection->addr()+targetSection->size())) ) {
+                                       throwf("local relocation for address 0x%08llX in section %s does not target section %s", 
+                                                       srcAddr, sect->sectname(), targetSection->sectname());
+                               }
+                       }
                        break;
                case X86_64_RELOC_SIGNED:
                case X86_64_RELOC_SIGNED_1:
@@ -2711,6 +3477,14 @@ bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, con
                                                break;
                                }
                                makeReference(kind, srcAddr, dstAddr);
+                               // verify that dstAddr is in the section being targeted
+                               int sectNum = reloc->r_symbolnum();
+                               const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)fSegment + sizeof(macho_segment_command<P>));
+                               const macho_section<P>* const targetSection = &sectionsStart[sectNum-1];
+                               if ( (dstAddr < targetSection->addr()) || (dstAddr > (targetSection->addr()+targetSection->size())) ) {
+                                       throwf("local relocation for address 0x%08llX in section %s does not target section %s", 
+                                                       srcAddr, sect->sectname(), targetSection->sectname());
+                               }
                        }       
                        break;
                case X86_64_RELOC_BRANCH:
@@ -2720,7 +3494,15 @@ bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, con
                                throw "length != 2 and X86_64_RELOC_BRANCH not supported";
                        dstAddr = (int64_t)((int32_t)(E::get32(*fixUpPtr)));
                        if ( reloc->r_extern() ) {
-                               if ( isWeakImportSymbol(targetSymbol) )
+                               if ( strncmp(targetName, "___dtrace_probe$", 16) == 0 ) {
+                                       makeByNameReference(x86_64::kDtraceProbeSite, srcAddr, targetName, 0);
+                                       addDtraceExtraInfos(srcAddr, &targetName[16]);
+                               }
+                               else if ( strncmp(targetName, "___dtrace_isenabled$", 20) == 0 ) {
+                                       makeByNameReference(x86_64::kDtraceIsEnabledSite, srcAddr, targetName, 0);
+                                       addDtraceExtraInfos(srcAddr, &targetName[16]);
+                               }
+                               else if ( isWeakImportSymbol(targetSymbol) )
                                        makeReferenceToSymbol(x86_64::kBranchPCRel32WeakImport, srcAddr, targetSymbol, dstAddr);
                                else
                                        makeReferenceToSymbol(x86_64::kBranchPCRel32, srcAddr, targetSymbol, dstAddr);
@@ -2756,6 +3538,7 @@ bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, con
                                makeReferenceToSymbol(x86_64::kPCRel32GOTLoad, srcAddr, targetSymbol, addend);
                        break;
                case X86_64_RELOC_SUBTRACTOR:
+               {
                        if ( reloc->r_pcrel() )
                                throw "X86_64_RELOC_SUBTRACTOR cannot be pc-relative";
                        if ( reloc->r_length() < 2 )
@@ -2818,6 +3601,7 @@ bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, con
                        else
                                ref->setToTargetOffset(dstAddr);
                        break;
+               }
                default:
                        fprintf(stderr, "unknown relocation type %d\n", reloc->r_type());
        }
@@ -2825,6 +3609,34 @@ bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, con
 }
 
 
+template <typename A>
+void Reader<A>::addReferencesForSection(const macho_section<P>* sect)
+{
+       // ignore dwarf sections.  If ld ever supports processing dwarf, this logic will need to change
+       if ( (sect->flags() & S_ATTR_DEBUG) == 0 ) {
+               switch ( sect->flags() & SECTION_TYPE ) {
+                       case S_SYMBOL_STUBS:
+                       case S_LAZY_SYMBOL_POINTERS:
+                               // we ignore compiler generated stubs, so ignore those relocs too
+                               break;
+                       default:
+                               const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fHeader) + sect->reloff());
+                               const uint32_t relocCount = sect->nreloc();
+                               //fprintf(stderr, "relocCount = %d in section %s\n", relocCount, sect->sectname());
+                               for (uint32_t r = 0; r < relocCount; ++r) {
+                                       try {
+                                               if ( addRelocReference(sect, &relocs[r]) )
+                                                       ++r; // skip next
+                                       }
+                                       catch (const char* msg) {
+                                               throwf("in section %s,%s reloc %u: %s\n", sect->segname(), sect->sectname(), r, msg);
+                                       }
+                               }
+               }
+       }
+}
+
+
 template <>
 const char* Reference<x86>::getDescription() const
 {
@@ -2853,15 +3665,41 @@ const char* Reference<x86>::getDescription() const
                        return temp;
                        }
                        break;
+               case x86::kPointerDiff16:
+                       {
+                       // by-name references have quoted names
+                       const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
+                       const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
+                       sprintf(temp, "offset 0x%04X, 16-bit pointer difference: (&%s%s%s + 0x%08X) - (&%s%s%s + 0x%08X)",
+                               fFixUpOffsetInSrc, targetQuotes, this->getTargetName(), targetQuotes, fToTarget.offset,
+                                                          fromQuotes, this->getFromTargetName(), fromQuotes, fFromTarget.offset );
+                       return temp;
+                       }
+                       break;
                case x86::kPCRel32WeakImport:
                        sprintf(temp, "offset 0x%04X, rel32 reference to weak imported ", fFixUpOffsetInSrc);
                        break;
                case x86::kPCRel32:
                        sprintf(temp, "offset 0x%04X, rel32 reference to ", fFixUpOffsetInSrc);
                        break;
+               case x86::kPCRel16:
+                       sprintf(temp, "offset 0x%04X, rel16 reference to ", fFixUpOffsetInSrc);
+                       break;
                case x86::kAbsolute32:
                        sprintf(temp, "offset 0x%04X, absolute32 reference to ", fFixUpOffsetInSrc);
                        break;
+               case x86::kDtraceProbe:
+                       sprintf(temp, "offset 0x%04X, dtrace static probe ", fFixUpOffsetInSrc);
+                       break;
+               case x86::kDtraceProbeSite:
+                       sprintf(temp, "offset 0x%04X, dtrace static probe site", fFixUpOffsetInSrc);
+                       break;
+               case x86::kDtraceIsEnabledSite:
+                       sprintf(temp, "offset 0x%04X, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
+                       break;
+               case x86::kDtraceTypeReference:
+                       sprintf(temp, "offset 0x%04X, dtrace type/stability reference", fFixUpOffsetInSrc);
+                       break;
        }
        // always quote by-name references
        if ( fToTargetName != NULL ) {
@@ -2899,6 +3737,16 @@ const char* Reference<ppc>::getDescription() const
                case ppc::kPointer:
                        sprintf(temp, "offset 0x%04X, pointer to ", fFixUpOffsetInSrc);
                        break;
+               case ppc::kPointerDiff16:
+                       {
+                       // by-name references have quoted names
+                       const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
+                       const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
+                       sprintf(temp, "offset 0x%04X, 16-bit pointer difference: (&%s%s%s + %d) - (&%s%s%s + %d)",
+                               fFixUpOffsetInSrc, targetQuotes, this->getTargetName(), targetQuotes, fToTarget.offset,
+                                                          fromQuotes, this->getFromTargetName(), fromQuotes, fFromTarget.offset );
+                       return temp;
+                       }
                case ppc::kPointerDiff32:
                        {
                        // by-name references have quoted names
@@ -2920,13 +3768,13 @@ const char* Reference<ppc>::getDescription() const
                        sprintf(temp, "offset 0x%04X, pc-rel branch fixup to ", fFixUpOffsetInSrc);
                        break;
                case ppc::kPICBaseLow16:
-                       sprintf(temp, "offset 0x%04X, low  16 fixup from pic-base offset 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.offset);
+                       sprintf(temp, "offset 0x%04X, low  16 fixup from pic-base of %s plus 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.atom->getDisplayName(), fFromTarget.offset);
                        break;
                case ppc::kPICBaseLow14:
-                       sprintf(temp, "offset 0x%04X, low  14 fixup from pic-base offset 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.offset);
+                       sprintf(temp, "offset 0x%04X, low  14 fixup from pic-base of %s plus 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.atom->getDisplayName(), fFromTarget.offset);
                        break;
                case ppc::kPICBaseHigh16:
-                       sprintf(temp, "offset 0x%04X, high 16 fixup from pic-base offset 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.offset);
+                       sprintf(temp, "offset 0x%04X, high 16 fixup from pic-base of %s plus 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.atom->getDisplayName(), fFromTarget.offset);
                        break;
                case ppc::kAbsLow16:
                        sprintf(temp, "offset 0x%04X, low  16 fixup to absolute address of ", fFixUpOffsetInSrc);
@@ -2935,10 +3783,22 @@ const char* Reference<ppc>::getDescription() const
                        sprintf(temp, "offset 0x%04X, low  14 fixup to absolute address of ", fFixUpOffsetInSrc);
                        break;
                case ppc::kAbsHigh16:
-                       sprintf(temp, "offset 0x%04X, high 16 fixup to absolute address of ", fFixUpOffsetInSrc);
+                       sprintf(temp, "offset 0x%04X, high 16 fixup or to absolute address of ", fFixUpOffsetInSrc);
                        break;
                case ppc::kAbsHigh16AddLow:
-                       sprintf(temp, "offset 0x%04X, high 16 fixup to absolute address of ", fFixUpOffsetInSrc);
+                       sprintf(temp, "offset 0x%04X, high 16 fixup add to absolute address of ", fFixUpOffsetInSrc);
+                       break;
+               case ppc::kDtraceProbe:
+                       sprintf(temp, "offset 0x%04X, dtrace static probe ", fFixUpOffsetInSrc);
+                       break;
+               case ppc::kDtraceProbeSite:
+                       sprintf(temp, "offset 0x%04X, dtrace static probe site", fFixUpOffsetInSrc);
+                       break;
+               case ppc::kDtraceIsEnabledSite:
+                       sprintf(temp, "offset 0x%04X, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
+                       break;
+               case ppc::kDtraceTypeReference:
+                       sprintf(temp, "offset 0x%04X, dtrace type/stability reference", fFixUpOffsetInSrc);
                        break;
        }
        // always quote by-name references
@@ -2996,6 +3856,16 @@ const char* Reference<ppc64>::getDescription() const
                                                           fromQuotes, this->getFromTargetName(), fromQuotes, fFromTarget.offset );
                        return temp;
                        }
+               case ppc64::kPointerDiff16:
+                       {
+                       // by-name references have quoted names
+                       const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
+                       const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
+                       sprintf(temp, "offset 0x%04llX, 16-bit pointer difference: (&%s%s%s + %u) - (&%s%s%s + %u)",
+                               fFixUpOffsetInSrc, targetQuotes, this->getTargetName(), targetQuotes, fToTarget.offset,
+                                                          fromQuotes, this->getFromTargetName(), fromQuotes, fFromTarget.offset );
+                       return temp;
+                       }
                case ppc64::kBranch24WeakImport:
                        sprintf(temp, "offset 0x%04llX, pc-rel branch fixup to weak imported ", fFixUpOffsetInSrc);
                        break;
@@ -3019,10 +3889,22 @@ const char* Reference<ppc64>::getDescription() const
                        sprintf(temp, "offset 0x%04llX, low  14 fixup to absolute address of ", fFixUpOffsetInSrc);
                        break;
                case ppc64::kAbsHigh16:
-                       sprintf(temp, "offset 0x%04llX, high 16 fixup to absolute address of ", fFixUpOffsetInSrc);
+                       sprintf(temp, "offset 0x%04llX, high 16 fixup or to absolute address of ", fFixUpOffsetInSrc);
                        break;
                case ppc64::kAbsHigh16AddLow:
-                       sprintf(temp, "offset 0x%04llX, high 16 fixup to absolute address of ", fFixUpOffsetInSrc);
+                       sprintf(temp, "offset 0x%04llX, high 16 fixup add to absolute address of ", fFixUpOffsetInSrc);
+                       break;
+               case ppc64::kDtraceProbe:
+                       sprintf(temp, "offset 0x%04llX, dtrace static probe ", fFixUpOffsetInSrc);
+                       break;
+               case ppc64::kDtraceProbeSite:
+                       sprintf(temp, "offset 0x%04llX, dtrace static probe site", fFixUpOffsetInSrc);
+                       break;
+               case ppc64::kDtraceIsEnabledSite:
+                       sprintf(temp, "offset 0x%04llX, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
+                       break;
+               case ppc64::kDtraceTypeReference:
+                       sprintf(temp, "offset 0x%04llX, dtrace type/stability reference", fFixUpOffsetInSrc);
                        break;
        }
        // always quote by-name references
@@ -3104,6 +3986,18 @@ const char* Reference<x86_64>::getDescription() const
                case x86_64::kPCRel32GOTLoadWeakImport:
                        sprintf(temp, "offset 0x%04llX, rel32 reference to GOT entry for weak imported ", fFixUpOffsetInSrc);
                        break;
+               case x86_64::kDtraceProbe:
+                       sprintf(temp, "offset 0x%04llX, dtrace static probe ", fFixUpOffsetInSrc);
+                       break;
+               case x86_64::kDtraceProbeSite:
+                       sprintf(temp, "offset 0x%04llX, dtrace static probe site", fFixUpOffsetInSrc);
+                       break;
+               case x86_64::kDtraceIsEnabledSite:
+                       sprintf(temp, "offset 0x%04llX, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
+                       break;
+               case x86_64::kDtraceTypeReference:
+                       sprintf(temp, "offset 0x%04llX, dtrace type/stability reference", fFixUpOffsetInSrc);
+                       break;
        }
        // always quote by-name references
        if ( fToTargetName != NULL ) {
index 7ac12fe90c4c7c05cc900a0d083a4b1dfb810be2..5b05210cf756704a7bfb0022e44c09e8c311c86f 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -37,6 +37,7 @@
 #include <uuid/uuid.h>
 #include <mach/i386/thread_status.h>
 #include <mach/ppc/thread_status.h>
+#include <CommonCrypto/CommonDigest.h>
 
 #include <vector>
 #include <algorithm>
 
 #include "MachOFileAbstraction.hpp"
 
+#ifndef S_DTRACE_DOF
+  #define S_DTRACE_DOF 0xF
+#endif
+
+#ifndef MH_PIE
+       #define MH_PIE 0x200000 
+#endif
 
 //
 //
@@ -60,7 +68,7 @@
 //                     Writer<xxx>::addObjectRelocs()
 //                     Writer<xxx>::fixUpReferenceRelocatable()
 //                     Writer<xxx>::fixUpReferenceFinal()
-//                     Writer<xxx>::stubableReferenceKind()
+//                     Writer<xxx>::stubableReference()
 //                     Writer<xxx>::weakImportReferenceKind()
 //                     Writer<xxx>::GOTReferenceKind()
 //
@@ -86,13 +94,17 @@ template <typename A> class SectionRelocationsLinkEditAtom;
 template <typename A> class LocalRelocationsLinkEditAtom;
 template <typename A> class ExternalRelocationsLinkEditAtom;
 template <typename A> class SymbolTableLinkEditAtom;
+template <typename A> class SegmentSplitInfoLoadCommandsAtom;
+template <typename A> class SegmentSplitInfoContentAtom;
 template <typename A> class IndirectTableLinkEditAtom;
+template <typename A> class ModuleInfoLinkEditAtom;
 template <typename A> class StringsLinkEditAtom;
 template <typename A> class LoadCommandsPaddingAtom;
 template <typename A> class StubAtom;
 template <typename A> class StubHelperAtom;
 template <typename A> class LazyPointerAtom;
 template <typename A> class NonLazyPointerAtom;
+template <typename A> class DylibLoadCommandsAtom;
 
 
 // SectionInfo should be nested inside Writer, but I can't figure out how to make the type accessible to the Atom classes
@@ -125,7 +137,8 @@ class SegmentInfo
 {
 public:
                                                                                SegmentInfo() : fInitProtection(0), fMaxProtection(0), fFileOffset(0), fFileSize(0),
-                                                                                                               fBaseAddress(0), fSize(0), fFixedAddress(false) { fName[0] = '\0'; }
+                                                                                                               fBaseAddress(0), fSize(0), fFixedAddress(false), 
+                                                                                                               fIndependentAddress(false) { fName[0] = '\0'; }
        std::vector<class SectionInfo*>         fSections;
        char                                                            fName[20];
        uint32_t                                                        fInitProtection;
@@ -135,6 +148,7 @@ public:
        uint64_t                                                        fBaseAddress;
        uint64_t                                                        fSize;
        bool                                                            fFixedAddress;
+       bool                                                            fIndependentAddress;
 };
 
 template <typename A>
@@ -151,12 +165,16 @@ public:
        virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) { return NULL; }
        virtual std::vector<Stab>*                                              getStabs()                                                              { return NULL; }
 
+       virtual ObjectFile::Atom&                                               makeObjcInfoAtom(ObjectFile::Reader::ObjcConstraint objcContraint, 
+                                                                                                                                               bool objcReplacementClasses);
        virtual class ObjectFile::Atom*                                 getUndefinedProxyAtom(const char* name);
        virtual uint64_t                                                                write(std::vector<class ObjectFile::Atom*>& atoms,
                                                                                                                  std::vector<class ObjectFile::Reader::Stab>& stabs,
                                                                                                                  class ObjectFile::Atom* entryPointAtom,
                                                                                                                  class ObjectFile::Atom* dyldHelperAtom,
-                                                                                                                 bool createUUID);
+                                                                                                                 bool createUUID, bool canScatter,
+                                                                                                                 ObjectFile::Reader::CpuConstraint cpuConstraint,
+                                                                                                                 bool biggerThanTwoGigs);
 
 private:
        typedef typename A::P                   P;
@@ -166,6 +184,7 @@ private:
 
        void                                            assignFileOffsets();
        void                                            synthesizeStubs();
+       void                                            insertDummyStubs();
        void                                            partitionIntoSections();
        bool                                            addBranchIslands();
        bool                                            addPPCBranchIslands();
@@ -174,14 +193,23 @@ private:
        void                                            createDynamicLinkerCommand();
        void                                            createDylibCommands();
        void                                            buildLinkEdit();
+       const char*                                     getArchString();
+       void                                            writeMap();
        uint64_t                                        writeAtoms();
        void                                            writeNoOps(uint32_t from, uint32_t to);
+       void                                            copyNoOps(uint8_t* from, uint8_t* to);
+       bool                                            segmentsCanSplitApart(const ObjectFile::Atom& from, const ObjectFile::Atom& to);
+       void                                            addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref);
        void                                            collectExportedAndImportedAndLocalAtoms();
        void                                            setNlistRange(std::vector<class ObjectFile::Atom*>& atoms, uint32_t startIndex, uint32_t count);
+       void                                            addLocalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name);
+       void                                            addGlobalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name);
        void                                            buildSymbolTable();
+       const char*                                     symbolTableName(const ObjectFile::Atom* atom);
        void                                            setExportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
        void                                            setImportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
        void                                            setLocalNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
+       void                                            copyNlistRange(const std::vector<macho_nlist<P> >& entries, uint32_t startIndex);
        uint64_t                                        getAtomLoadAddress(const ObjectFile::Atom* atom);
        uint8_t                                         ordinalForLibrary(ObjectFile::Reader* file);
        bool                                            shouldExport(const ObjectFile::Atom& atom) const;
@@ -189,18 +217,21 @@ private:
        void                                            adjustLinkEditSections();
        void                                            buildObjectFileFixups();
        void                                            buildExecutableFixups();
+       bool                                            preboundLazyPointerType(uint8_t* type);
        uint64_t                                        relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom) const;
-       bool                                            referenceRequiresRuntimeFixUp(const ObjectFile::Reference* ref, bool slideable) const;
        void                                            fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const;
        void                                            fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const;
        void                                            fixUpReference_powerpc(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom,
                                                                                                                uint8_t buffer[], bool finalLinkedImage) const;
        uint32_t                                        symbolIndex(ObjectFile::Atom& atom);
+       bool                                            makesExternalRelocatableReference(ObjectFile::Atom& target) const;
        uint32_t                                        addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref);
        uint32_t                                        addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::Reference* ref);
        uint8_t                                         getRelocPointerSize();
-       bool                                            stubableReferenceKind(uint8_t kind);
+       uint64_t                                        maxAddress();
+       bool                                            stubableReference(const ObjectFile::Reference* ref);
        bool                                            GOTReferenceKind(uint8_t kind);
+       bool                                            optimizableGOTReferenceKind(uint8_t kind);
        bool                                            weakImportReferenceKind(uint8_t kind);
        unsigned int                            collectStabs();
        uint64_t                                        valueForStab(const ObjectFile::Reader::Stab& stab);
@@ -208,10 +239,12 @@ private:
        uint8_t                                         sectionIndexForStab(const ObjectFile::Reader::Stab& stab);
        void                                            addStabs(uint32_t startIndex);
        RelocKind                                       relocationNeededInFinalLinkedImage(const ObjectFile::Atom& target) const;
-       bool                                            illegalRelocInFinalLinkedImage(const ObjectFile::Reference&, bool slideable);
+       bool                                            illegalRelocInFinalLinkedImage(const ObjectFile::Reference&);
        bool                                            mightNeedPadSegment();
        void                                            scanForAbsoluteReferences();
-
+       bool                                            needsModuleTable();
+       void                                            optimizeDylibReferences();
+       bool                                            indirectSymbolIsLocal(const ObjectFile::Reference* ref) const;
 
        struct DirectLibrary {
                class ObjectFile::Reader*       fLibrary;
@@ -235,13 +268,17 @@ private:
        friend class LocalRelocationsLinkEditAtom<A>;
        friend class ExternalRelocationsLinkEditAtom<A>;
        friend class SymbolTableLinkEditAtom<A>;
+       friend class SegmentSplitInfoLoadCommandsAtom<A>;
+       friend class SegmentSplitInfoContentAtom<A>;
 //     friend class IndirectTableLinkEditAtom<A>;
+       friend class ModuleInfoLinkEditAtom<A>;
        friend class StringsLinkEditAtom<A>;
        friend class LoadCommandsPaddingAtom<A>;
        friend class StubAtom<A>;
        friend class StubHelperAtom<A>;
        friend class LazyPointerAtom<A>;
        friend class NonLazyPointerAtom<A>;
+       friend class DylibLoadCommandsAtom<A>;
 
        const char*                                                                             fFilePath;
        Options&                                                                                fOptions;
@@ -259,23 +296,28 @@ private:
        class SegmentInfo*                                                              fPadSegmentInfo;
        class ObjectFile::Atom*                                                 fEntryPoint;
        class ObjectFile::Atom*                                                 fDyldHelper;
-       std::vector<DirectLibrary>                                              fDirectLibraries;
+       std::map<class ObjectFile::Reader*, DylibLoadCommandsAtom<A>*>  fLibraryToLoadCommand;
        std::map<class ObjectFile::Reader*, uint32_t>   fLibraryToOrdinal;
+       std::map<class ObjectFile::Reader*, class ObjectFile::Reader*>  fLibraryAliases;
        std::vector<class ObjectFile::Atom*>                    fExportedAtoms;
        std::vector<class ObjectFile::Atom*>                    fImportedAtoms;
        std::vector<class ObjectFile::Atom*>                    fLocalSymbolAtoms;
+       std::vector<macho_nlist<P> >                                    fLocalExtraLabels;
+       std::vector<macho_nlist<P> >                                    fGlobalExtraLabels;
        class SectionRelocationsLinkEditAtom<A>*                fSectionRelocationsAtom;
        class LocalRelocationsLinkEditAtom<A>*                  fLocalRelocationsAtom;
        class ExternalRelocationsLinkEditAtom<A>*               fExternalRelocationsAtom;
        class SymbolTableLinkEditAtom<A>*                               fSymbolTableAtom;
+       class SegmentSplitInfoContentAtom<A>*                   fSplitCodeToDataContentAtom;
        class IndirectTableLinkEditAtom<A>*                             fIndirectTableAtom;
+       class ModuleInfoLinkEditAtom<A>*                                fModuleInfoAtom;
        class StringsLinkEditAtom<A>*                                   fStringsAtom;
        class PageZeroAtom<A>*                                                  fPageZeroAtom;
        macho_nlist<P>*                                                                 fSymbolTable;
        std::vector<macho_relocation_info<P> >                  fSectionRelocs;
        std::vector<macho_relocation_info<P> >                  fInternalRelocs;
        std::vector<macho_relocation_info<P> >                  fExternalRelocs;
-       std::map<ObjectFile::Atom*,ObjectFile::Atom*>   fStubsMap;
+       std::map<const ObjectFile::Atom*,ObjectFile::Atom*>     fStubsMap;
        std::map<ObjectFile::Atom*,ObjectFile::Atom*>   fGOTMap;
        std::vector<class StubAtom<A>*>                                 fAllSynthesizedStubs;
        std::vector<ObjectFile::Atom*>                                  fAllSynthesizedStubHelpers;
@@ -294,10 +336,15 @@ private:
        bool                                                                                    fEmitVirtualSections;
        bool                                                                                    fHasWeakExports;
        bool                                                                                    fReferencesWeakImports;
-       bool                                                                                    fSeenFollowOnReferences;
+       bool                                                                                    fCanScatter;
        bool                                                                                    fWritableSegmentPastFirst4GB;
+       bool                                                                                    fNoReExportedDylibs;
+       bool                                                                                    fBiggerThanTwoGigs;
+       bool                                                                                    fSlideable;
        std::map<const ObjectFile::Atom*,bool>                  fWeakImportMap;
        SegmentInfo*                                                                    fFirstWritableSegment;
+       ObjectFile::Reader::CpuConstraint                               fCpuConstraint;
+       uint32_t                                                                                fAnonNameIndex;
 };
 
 
@@ -311,13 +358,16 @@ public:
        virtual bool                            isContentWritable() const               { return fWritable; }
        virtual bool                            isContentExecutable() const             { return fExecutable; }
        virtual bool                            hasFixedAddress() const                 { return fFixedAddress; }
-
+       
        static Segment                                                          fgTextSegment;
        static Segment                                                          fgPageZeroSegment;
        static Segment                                                          fgLinkEditSegment;
        static Segment                                                          fgStackSegment;
        static Segment                                                          fgImportSegment;
+       static Segment                                                          fgROImportSegment;
        static Segment                                                          fgDataSegment;
+       static Segment                                                          fgObjCSegment;
+       
        
 private:
        const char*                                     fName;
@@ -332,7 +382,9 @@ Segment             Segment::fgTextSegment("__TEXT", true, false, true, false);
 Segment                Segment::fgLinkEditSegment("__LINKEDIT", true, false, false, false);
 Segment                Segment::fgStackSegment("__UNIXSTACK", true, true, false, true);
 Segment                Segment::fgImportSegment("__IMPORT", true, true, true, false);
+Segment                Segment::fgROImportSegment("__IMPORT", true, false, true, false);
 Segment                Segment::fgDataSegment("__DATA", true, true, false, false);
+Segment                Segment::fgObjCSegment("__OBJC", true, true, false, false);
 
 
 template <typename A>
@@ -354,8 +406,8 @@ public:
        virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return fgEmptyReferenceList; }
        virtual bool                                                    mustRemainInSection() const             { return true; }
        virtual ObjectFile::Segment&                    getSegment() const                              { return fSegment; }
-       virtual bool                                                    requiresFollowOnAtom() const    { return false; }
        virtual ObjectFile::Atom&                               getFollowOnAtom() const                 { return *((ObjectFile::Atom*)NULL); }
+       virtual uint32_t                                                getOrdinal() const                              { return 0; }
        virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
        virtual ObjectFile::Alignment                   getAlignment() const                    { return ObjectFile::Alignment(2); }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const { throw "don't use copyRawContent"; }
@@ -422,6 +474,7 @@ public:
        virtual uint64_t                                                                getSize() const                         { return sizeof(macho_header<typename A::P>); }
        virtual ObjectFile::Alignment                                   getAlignment() const            { return ObjectFile::Alignment(12); }
        virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
+       virtual uint32_t                                                                getOrdinal() const                      { return 1; }
        virtual void                                                                    copyRawContent(uint8_t buffer[]) const;
 private:
        using WriterAtom<A>::fWriter;
@@ -449,12 +502,17 @@ template <typename A>
 class LoadCommandAtom : public WriterAtom<A>
 {
 protected:
-                                                                                       LoadCommandAtom(Writer<A>& writer, Segment& segment) : WriterAtom<A>(writer, segment) {}
+                                                                                       LoadCommandAtom(Writer<A>& writer, Segment& segment) : WriterAtom<A>(writer, segment), fOrdinal(fgCurrentOrdinal++) {}
        virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(log2(sizeof(typename A::P::uint_t))); }
        virtual const char*                                             getSectionName() const  { return "._load_commands"; }
+       virtual uint32_t                                                getOrdinal() const              { return fOrdinal; }
        static uint64_t                                                 alignedSize(uint64_t size);
+private:
+       uint32_t                                                                fOrdinal;
+       static uint32_t                                                 fgCurrentOrdinal;
 };
 
+template <typename A> uint32_t LoadCommandAtom<A>::fgCurrentOrdinal = 0;
 
 template <typename A>
 class SegmentLoadCommandsAtom : public LoadCommandAtom<A>
@@ -487,10 +545,11 @@ public:
        virtual uint64_t                                                getSize() const;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
        unsigned int                                                    commandCount();
-
+                       void                                                    needDynamicTable();
 private:
        using WriterAtom<A>::fWriter;
        typedef typename A::P                                   P;
+       bool                                                                    fNeedsDynamicSymbolTable;
        macho_symtab_command<typename A::P>             fSymbolTable;
        macho_dysymtab_command<typename A::P>   fDynamicSymbolTable;
 };
@@ -524,6 +583,19 @@ private:
        typedef typename A::P                                   P;
 };
 
+template <typename A>
+class SegmentSplitInfoLoadCommandsAtom : public LoadCommandAtom<A>
+{
+public:
+                                                                                       SegmentSplitInfoLoadCommandsAtom(Writer<A>& writer)  : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
+       virtual const char*                                             getDisplayName() const  { return "segment split info load command"; }
+       virtual uint64_t                                                getSize() const;
+       virtual void                                                    copyRawContent(uint8_t buffer[]) const;
+private:
+       using WriterAtom<A>::fWriter;
+       typedef typename A::P                                   P;
+};
+
 template <typename A>
 class AllowableClientLoadCommandsAtom : public LoadCommandAtom<A>
 {
@@ -544,14 +616,16 @@ class DylibLoadCommandsAtom : public LoadCommandAtom<A>
 {
 public:
                                                                                        DylibLoadCommandsAtom(Writer<A>& writer, ExecutableFile::DyLibUsed& info) 
-                                                                                        : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fInfo(info) {}
+                                                                                        : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fInfo(info), fOptimizedAway(false) {}
        virtual const char*                                             getDisplayName() const  { return "dylib load command"; }
        virtual uint64_t                                                getSize() const;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
+       virtual void                                                    optimizeAway() { fOptimizedAway = true; }
 private:
        using WriterAtom<A>::fWriter;
        typedef typename A::P                                   P;
-       ExecutableFile::DyLibUsed&                              fInfo;
+       ExecutableFile::DyLibUsed                               fInfo;
+       bool                                                                    fOptimizedAway;
 };
 
 template <typename A>
@@ -630,11 +704,13 @@ class UUIDLoadCommandAtom : public LoadCommandAtom<A>
 {
 public:
                                                                                        UUIDLoadCommandAtom(Writer<A>& writer)
-                                                                                               : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fEmit(false) { ::uuid_generate_random(fUUID);}
+                                                                                               : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fEmit(false) {}
        virtual const char*                                             getDisplayName() const  { return "uuid load command"; }
        virtual uint64_t                                                getSize() const                 { return fEmit ? sizeof(macho_uuid_command<typename A::P>) : 0; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
-       virtual void                                                emit()                                      { fEmit = true; }
+       virtual void                                                generate();
+                       void                                                setContent(const uint8_t uuid[16]);
+                       const uint8_t*                                  getUUID()                               { return fUUID; }
 private:
        using WriterAtom<A>::fWriter;
        typedef typename A::P                                   P;
@@ -642,6 +718,23 @@ private:
        bool                                                                fEmit;
 };
 
+
+template <typename A>
+class RPathLoadCommandsAtom : public LoadCommandAtom<A>
+{
+public:
+                                                                                       RPathLoadCommandsAtom(Writer<A>& writer, const char* path)
+                                                                                               : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fPath(path) {}
+       virtual const char*                                             getDisplayName() const  { return "rpath load command"; }
+       virtual uint64_t                                                getSize() const;
+       virtual void                                                    copyRawContent(uint8_t buffer[]) const;
+private:
+       using WriterAtom<A>::fWriter;
+       typedef typename A::P                                   P;
+       const char*                                                             fPath;
+};
+
+
 template <typename A>
 class LoadCommandsPaddingAtom : public WriterAtom<A>
 {
@@ -664,12 +757,19 @@ template <typename A>
 class LinkEditAtom : public WriterAtom<A>
 {
 public:
-                                                                                       LinkEditAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgLinkEditSegment) {}
+                                                                                       LinkEditAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgLinkEditSegment), fOrdinal(fgCurrentOrdinal++) {}
        uint64_t                                                                getFileOffset() const;
+       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(log2(sizeof(typename A::P::uint_t))); }
+       virtual uint32_t                                                getOrdinal() const              { return fOrdinal; }
+private:
+       uint32_t                                                                fOrdinal;
+       static uint32_t                                                 fgCurrentOrdinal;
 private:
        typedef typename A::P                                   P;
 };
 
+template <typename A> uint32_t LinkEditAtom<A>::fgCurrentOrdinal = 0;
+
 template <typename A>
 class SectionRelocationsLinkEditAtom : public LinkEditAtom<A>
 {
@@ -677,7 +777,6 @@ public:
                                                                                        SectionRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "section relocations"; }
        virtual uint64_t                                                getSize() const;
-       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(3); }
        virtual const char*                                             getSectionName() const  { return "._section_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
@@ -692,7 +791,6 @@ public:
                                                                                        LocalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "local relocations"; }
        virtual uint64_t                                                getSize() const;
-       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(3); }
        virtual const char*                                             getSectionName() const  { return "._local_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
@@ -721,7 +819,6 @@ public:
                                                                                        ExternalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
        virtual const char*                                             getDisplayName() const  { return "external relocations"; }
        virtual uint64_t                                                getSize() const;
-       virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(3); }
        virtual const char*                                             getSectionName() const  { return "._extern_relocs"; }
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
@@ -734,6 +831,43 @@ struct IndirectEntry {
        uint32_t        symbolIndex;
 };
 
+
+template <typename A>
+class SegmentSplitInfoContentAtom : public LinkEditAtom<A>
+{
+public:
+                                                                                       SegmentSplitInfoContentAtom(Writer<A>& writer) : LinkEditAtom<A>(writer), fCantEncode(false) { }
+       virtual const char*                                             getDisplayName() const  { return "split segment info"; }
+       virtual uint64_t                                                getSize() const;
+       virtual const char*                                             getSectionName() const  { return "._split_info"; }
+       virtual void                                                    copyRawContent(uint8_t buffer[]) const;
+       bool                                                                    canEncode()                                             { return !fCantEncode; }
+       void                                                                    setCantEncode()                                 { fCantEncode = true; }
+       void                                                                    add32bitPointerLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind1Locations.push_back(AtomAndOffset(atom, offset)); }
+       void                                                                    add64bitPointerLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind2Locations.push_back(AtomAndOffset(atom, offset)); }
+       void                                                                    addPPCHi16Location(const ObjectFile::Atom* atom, uint32_t offset) { fKind3Locations.push_back(AtomAndOffset(atom, offset)); }
+       void                                                                    add32bitImportLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind4Locations.push_back(AtomAndOffset(atom, offset)); }
+       void                                                                    encode();
+
+private:
+       using WriterAtom<A>::fWriter;
+       typedef typename A::P                                   P;
+       typedef typename A::P::uint_t                   pint_t;
+       struct AtomAndOffset { 
+                       AtomAndOffset(const ObjectFile::Atom* a, uint32_t off) : atom(a), offset(off) {}
+                       const ObjectFile::Atom*         atom; 
+                       uint32_t                                        offset; 
+       };
+       void                                                                    uleb128EncodeAddresses(const std::vector<AtomAndOffset>& locations);
+       
+       std::vector<AtomAndOffset>                              fKind1Locations;
+       std::vector<AtomAndOffset>                              fKind2Locations;
+       std::vector<AtomAndOffset>                              fKind3Locations;
+       std::vector<AtomAndOffset>                              fKind4Locations;
+       std::vector<uint8_t>                                    fEncodedData;
+       bool                                                                    fCantEncode;
+};
+
 template <typename A>
 class IndirectTableLinkEditAtom : public LinkEditAtom<A>
 {
@@ -751,6 +885,29 @@ private:
        typedef typename A::P                                   P;
 };
 
+template <typename A>
+class ModuleInfoLinkEditAtom : public LinkEditAtom<A>
+{
+public:
+                                                                                       ModuleInfoLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer), fModuleNameOffset(0) { }
+       virtual const char*                                             getDisplayName() const  { return "modulel table"; }
+       virtual uint64_t                                                getSize() const;
+       virtual const char*                                             getSectionName() const  { return "._module_info"; }
+       virtual void                                                    copyRawContent(uint8_t buffer[]) const;
+
+                       void                                                    setName() { fModuleNameOffset = fWriter.fStringsAtom->add("single module"); }
+                       uint32_t                                                getTableOfContentsFileOffset() const;
+                       uint32_t                                                getModuleTableFileOffset() const;
+                       uint32_t                                                getReferencesFileOffset() const;
+                       uint32_t                                                getReferencesCount() const;
+
+private:
+       using WriterAtom<A>::fWriter;
+       typedef typename A::P                                   P;
+       uint32_t                                                                fModuleNameOffset;
+};
+
+
 class CStringEquals
 {
 public:
@@ -770,15 +927,12 @@ public:
        int32_t                                                                 add(const char* name);
        int32_t                                                                 addUnique(const char* name);
        int32_t                                                                 emptyString()                   { return 1; }
+       const char*                                                             stringForIndex(int32_t) const;
 
 private:
        using WriterAtom<A>::fWriter;
        typedef typename A::P                                   P;
        enum { kBufferSize = 0x01000000 };
-       class CStringComparor {
-       public:
-               bool operator()(const char* left, const char* right) const { return (strcmp(left, right) < 0); }
-       };
        typedef __gnu_cxx::hash_map<const char*, int32_t, __gnu_cxx::hash<const char*>, CStringEquals> StringToOffset;
 
        std::vector<char*>                                              fFullBuffers;
@@ -907,6 +1061,23 @@ private:
 };
 
 
+template <typename A>
+class ObjCInfoAtom : public WriterAtom<A>
+{
+public:
+                                                                                       ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcContraint,
+                                                                                                               bool objcReplacementClasses);
+       virtual const char*                                             getName() const                         { return "objc$info"; }
+       virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
+       virtual uint64_t                                                getSize() const                         { return 8; }
+       virtual const char*                                             getSectionName() const;
+       virtual void                                                    copyRawContent(uint8_t buffer[]) const;
+private:
+       Segment&                                                                getInfoSegment() const;
+       uint32_t                                                                fContent[2];
+};
+
+
 template <typename A>
 class WriterReference : public ObjectFile::Reference
 {
@@ -920,21 +1091,20 @@ public:
 
        virtual                                 ~WriterReference() {}
 
-       virtual bool                    isTargetUnbound() const                                                 { return false; }
-       virtual bool                    isFromTargetUnbound() const                                             { return false; }
+       virtual ObjectFile::Reference::TargetBinding getTargetBinding() const { return ObjectFile::Reference::kBoundDirectly; }
+       virtual ObjectFile::Reference::TargetBinding getFromTargetBinding() const { return (fFromTarget != NULL) ? ObjectFile::Reference::kBoundDirectly : ObjectFile::Reference::kDontBind; }
        virtual uint8_t                 getKind() const                                                                 { return (uint8_t)fKind; }
        virtual uint64_t                getFixUpOffset() const                                                  { return fFixUpOffsetInSrc; }
        virtual const char*             getTargetName() const                                                   { return fTarget->getName(); }
        virtual ObjectFile::Atom& getTarget() const                                                             { return *fTarget; }
        virtual uint64_t                getTargetOffset() const                                                 { return fTargetOffset; }
-       virtual bool                    hasFromTarget() const                                                   { return (fFromTarget != NULL); }
        virtual ObjectFile::Atom& getFromTarget() const                                                 { return *fFromTarget; }
        virtual const char*             getFromTargetName() const                                               { return fFromTarget->getName(); }
        virtual void                    setTarget(ObjectFile::Atom& target, uint64_t offset)    { fTarget = &target; fTargetOffset = offset; }
        virtual void                    setFromTarget(ObjectFile::Atom& target)                 { fFromTarget = &target; }
        virtual void                    setFromTargetName(const char* name)                             {  }
        virtual void                    setFromTargetOffset(uint64_t offset)                    { fFromTargetOffset = offset; }
-       virtual const char*             getDescription() const                                                  { return "writer refrence"; }
+       virtual const char*             getDescription() const                                                  { return "writer reference"; }
        virtual uint64_t                getFromTargetOffset() const                                             { return fFromTargetOffset; }
 
 private:
@@ -948,209 +1118,601 @@ private:
 
 
 
-struct ExportSorter
+template <>
+StubHelperAtom<x86_64>::StubHelperAtom(Writer<x86_64>& writer, ObjectFile::Atom& target, ObjectFile::Atom& lazyPointer)
+ : WriterAtom<x86_64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
 {
-     bool operator()(ObjectFile::Atom* left, ObjectFile::Atom* right)
-     {
-          return (strcmp(left->getName(), right->getName()) < 0);
-     }
-};
+       writer.fAllSynthesizedStubHelpers.push_back(this);
 
+       fReferences.push_back(new WriterReference<x86_64>(3, x86_64::kPCRel32, &lazyPointer));
+       fReferences.push_back(new WriterReference<x86_64>(8, x86_64::kPCRel32, writer.fDyldHelper));
+       if ( writer.fDyldHelper == NULL )
+               throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
+}
 
+template <>
+uint64_t StubHelperAtom<x86_64>::getSize() const
+{
+       return 12;
+}
 
+template <>
+void StubHelperAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
+{
+       buffer[0]  = 0x4C;              // lea foo$lazy_ptr(%rip),%r11
+       buffer[1]  = 0x8D;
+       buffer[2]  = 0x1D;
+       buffer[3]  = 0x00;
+       buffer[4]  = 0x00;
+       buffer[5]  = 0x00;
+       buffer[6]  = 0x00;
+       buffer[7]  = 0xE9;              // jmp dyld_stub_binding_helper
+       buffer[8]  = 0x00;
+       buffer[9]  = 0x00;
+       buffer[10] = 0x00;
+       buffer[11] = 0x00;
+}
 
 template <typename A>
-Writer<A>::Writer(const char* path, Options& options, std::vector<ExecutableFile::DyLibUsed>& dynamicLibraries)
-       : ExecutableFile::Writer(dynamicLibraries), fFilePath(strdup(path)), fOptions(options), fLoadCommandsSection(NULL),
-         fLoadCommandsSegment(NULL), fPadSegmentInfo(NULL), fPageZeroAtom(NULL), fSymbolTableCount(0), fLargestAtomSize(1), 
-         fEmitVirtualSections(false), fHasWeakExports(false), fReferencesWeakImports(false),
-         fSeenFollowOnReferences(false), fWritableSegmentPastFirst4GB(false), fFirstWritableSegment(NULL)
+const char* StubHelperAtom<A>::stubName(const char* name)
 {
-       int permissions = 0777;
-       if ( fOptions.outputKind() == Options::kObjectFile )
-               permissions = 0666;
-       // Calling unlink first assures the file is gone so that open creates it with correct permissions
-       // It also handles the case where fFilePath file is not writable but its directory is
-       // And it means we don't have to truncate the file when done writing (in case new is smaller than old)
-       (void)unlink(fFilePath);
-       fFileDescriptor = open(fFilePath, O_CREAT | O_WRONLY | O_TRUNC, permissions);
-       if ( fFileDescriptor == -1 ) {
-               throw "can't open file for writing";
-       }
-
-       switch ( fOptions.outputKind() ) {
-               case Options::kDynamicExecutable:
-               case Options::kStaticExecutable:
-                       fWriterSynthesizedAtoms.push_back(fPageZeroAtom = new PageZeroAtom<A>(*this));
-                       if ( fOptions.outputKind() == Options::kDynamicExecutable )
-                               fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
-                       if ( fOptions.outputKind() == Options::kDynamicExecutable )
-                               fWriterSynthesizedAtoms.push_back(new DyldLoadCommandsAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
-                       if ( fOptions.hasCustomStack() )
-                               fWriterSynthesizedAtoms.push_back(new CustomStackAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
-                       break;
-               case Options::kDynamicLibrary:
-               case Options::kDynamicBundle:
-                       fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
-                       // fall through
-               case Options::kObjectFile:
-                       fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
-                       if ( fOptions.outputKind() == Options::kDynamicLibrary ) {
-                               fWriterSynthesizedAtoms.push_back(new DylibIDLoadCommandsAtom<A>(*this));
-                               if ( fOptions.initFunctionName() != NULL )
-                                       fWriterSynthesizedAtoms.push_back(new RoutinesLoadCommandsAtom<A>(*this));
-                       }
-                       fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
-                       break;
-               case Options::kDyld:
-                       fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new DyldLoadCommandsAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
-                       fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
-                       break;
-       }
+       char* buf;
+       asprintf(&buf, "%s$stubHelper", name);
+       return buf;
+}
 
-       // add extra commmands
-       uint8_t ordinal = 1;
-       switch ( fOptions.outputKind() ) {
-               case Options::kDynamicExecutable:
-               case Options::kDynamicLibrary:
-               case Options::kDynamicBundle:
-                       {
-                               // add dylib load command atoms for all dynamic libraries
-                               const unsigned int libCount = dynamicLibraries.size();
-                               for (unsigned int i=0; i < libCount; ++i) {
-                                       ExecutableFile::DyLibUsed& dylibInfo = dynamicLibraries[i];
-                                       if ( dylibInfo.options.fBundleLoader ) {
-                                               fLibraryToOrdinal[dylibInfo.reader] = EXECUTABLE_ORDINAL;
-                                       }
-                                       else if ( dylibInfo.indirect ) {
-                                               // find ordinal of direct reader
-                                               if ( fOptions.nameSpace() == Options::kTwoLevelNameSpace ) {
-                                                       bool found = false;
-                                                       for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
-                                                               if ( it->first == dylibInfo.directReader ) {
-                                                                       //fprintf(stderr, "ordinal %d for indirect %s\n", it->second, dylibInfo.reader->getPath());
-                                                                       fLibraryToOrdinal[dylibInfo.reader] = it->second;
-                                                                       found = true;
-                                                                       break;
-                                                               }
-                                                       }
-                                                       if ( ! found )
-                                                               fprintf(stderr, "ld64 warning: ordinal not found for %s, parent %s\n", dylibInfo.reader->getPath(), dylibInfo.directReader != NULL ? dylibInfo.directReader->getPath() : NULL);
-                                               }
-                                       }
-                                       else {
-                                               // see if a DylibLoadCommandsAtom has already been created for this install path
-                                               bool newDylib = true;
-                                               const char* dylibInstallPath = dylibInfo.reader->getInstallPath();
-                                               if ( dylibInfo.options.fInstallPathOverride != NULL )
-                                                       dylibInstallPath = dylibInfo.options.fInstallPathOverride;
-                                               for (unsigned int seenLib=0; seenLib < i; ++seenLib) {
-                                                       ExecutableFile::DyLibUsed& seenDylibInfo = dynamicLibraries[seenLib];
-                                                       if ( !seenDylibInfo.indirect && !seenDylibInfo.options.fBundleLoader ) {
-                                                               const char* seenDylibInstallPath = seenDylibInfo.reader->getInstallPath();
-                                                               if ( seenDylibInfo.options.fInstallPathOverride != NULL )
-                                                                       seenDylibInstallPath = dylibInfo.options.fInstallPathOverride;
-                                                               if ( strcmp(seenDylibInstallPath, dylibInstallPath) == 0 ) {
-                                                                       fLibraryToOrdinal[dylibInfo.reader] = fLibraryToOrdinal[seenDylibInfo.reader];
-                                                                       newDylib = false;
-                                                                       break;
-                                                               }
-                                                       }
-                                               }
 
-                                               if ( newDylib ) {
-                                                       // assign new ordinal and check for other paired load commands
-                                                       fLibraryToOrdinal[dylibInfo.reader] = ordinal++;
-                                                       fWriterSynthesizedAtoms.push_back(new DylibLoadCommandsAtom<A>(*this, dylibInfo));
-                                                       if ( dylibInfo.options.fReExport ) {
-                                                               // this dylib also needs a sub_x load command
-                                                               bool isFrameworkReExport = false;
-                                                               const char* lastSlash = strrchr(dylibInstallPath, '/');
-                                                               if ( lastSlash != NULL ) {
-                                                                       char frameworkName[strlen(lastSlash)+20];
-                                                                       sprintf(frameworkName, "/%s.framework/", &lastSlash[1]);
-                                                                       isFrameworkReExport = (strstr(dylibInstallPath, frameworkName) != NULL);
-                                                               }
-                                                               if ( isFrameworkReExport ) {
-                                                                       // needs a LC_SUB_UMBRELLA command
-                                                                       fWriterSynthesizedAtoms.push_back(new SubUmbrellaLoadCommandsAtom<A>(*this, &lastSlash[1]));
-                                                               }
-                                                               else {
-                                                                       // needs a LC_SUB_LIBRARY command
-                                                                       const char* nameStart = &lastSlash[1];
-                                                                       if ( lastSlash == NULL )
-                                                                               nameStart = dylibInstallPath;
-                                                                       int len = strlen(nameStart);
-                                                                       const char* dot = strchr(nameStart, '.');
-                                                                       if ( dot != NULL )
-                                                                               len = dot - nameStart;
-                                                                       fWriterSynthesizedAtoms.push_back(new SubLibraryLoadCommandsAtom<A>(*this, nameStart, len));
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                               // add umbrella command if needed
-                               if ( fOptions.umbrellaName() != NULL ) {
-                                       fWriterSynthesizedAtoms.push_back(new UmbrellaLoadCommandsAtom<A>(*this, fOptions.umbrellaName()));
-                               }
-                               std::vector<const char*>& allowableClients = fOptions.allowableClients();
-                               if ( allowableClients.size() != 0 ) {
-                                       for (std::vector<const char*>::iterator it=allowableClients.begin();
-                                                it != allowableClients.end();
-                                                it++)
-                                               fWriterSynthesizedAtoms.push_back(new AllowableClientLoadCommandsAtom<A>(*this, *it));
-                               }
-                       }
-                       break;
-               case Options::kStaticExecutable:
-               case Options::kObjectFile:
-               case Options::kDyld:
-                       break;
-       }
+// specialize lazy pointer for x86_64 to initially pointer to stub helper
+template <>
+LazyPointerAtom<x86_64>::LazyPointerAtom(Writer<x86_64>& writer, ObjectFile::Atom& target)
+ : WriterAtom<x86_64>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target)
+{
+       writer.fAllSynthesizedLazyPointers.push_back(this);
 
-       //fprintf(stderr, "ordinals table:\n");
-       //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
-       //      fprintf(stderr, "%d <== %s\n", it->second, it->first->getPath());
-       //}
+       StubHelperAtom<x86_64>* helper = new StubHelperAtom<x86_64>(writer, target, *this);
+       fReferences.push_back(new WriterReference<x86_64>(0, x86_64::kPointer, helper));
 }
 
+
 template <typename A>
-Writer<A>::~Writer()
+LazyPointerAtom<A>::LazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target)
+ : WriterAtom<A>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target)
 {
-       if ( fFilePath != NULL )
+       writer.fAllSynthesizedLazyPointers.push_back(this);
+
+       fReferences.push_back(new WriterReference<A>(0, A::kPointer, &target));
+}
+
+
+
+template <typename A>
+const char* LazyPointerAtom<A>::lazyPointerName(const char* name)
+{
+       char* buf;
+       asprintf(&buf, "%s$lazy_pointer", name);
+       return buf;
+}
+
+template <typename A>
+void LazyPointerAtom<A>::copyRawContent(uint8_t buffer[]) const
+{
+       bzero(buffer, getSize());
+}
+
+
+template <typename A>
+NonLazyPointerAtom<A>::NonLazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target)
+ : WriterAtom<A>(writer, Segment::fgDataSegment), fName(nonlazyPointerName(target.getName())), fTarget(target)
+{
+       writer.fAllSynthesizedNonLazyPointers.push_back(this);
+
+       fReferences.push_back(new WriterReference<A>(0, A::kPointer, &target));
+}
+
+template <typename A>
+const char* NonLazyPointerAtom<A>::nonlazyPointerName(const char* name)
+{
+       char* buf;
+       asprintf(&buf, "%s$non_lazy_pointer", name);
+       return buf;
+}
+
+template <typename A>
+void NonLazyPointerAtom<A>::copyRawContent(uint8_t buffer[]) const
+{
+       bzero(buffer, getSize());
+}
+
+
+
+template <>
+bool StubAtom<ppc64>::pic() const
+{
+       // no-pic stubs for ppc64 don't work if lazy pointer is above low 2GB.
+       // Usually that only happens if page zero is very large
+       return ( fWriter.fSlideable || ((fWriter.fPageZeroAtom != NULL) && (fWriter.fPageZeroAtom->getSize() > 4096)) );
+}
+
+template <>
+bool StubAtom<ppc>::pic() const
+{
+       return fWriter.fSlideable;
+}
+
+template <>
+ObjectFile::Alignment StubAtom<ppc>::getAlignment() const
+{
+       return 2;
+}
+
+template <>
+ObjectFile::Alignment StubAtom<ppc64>::getAlignment() const
+{
+       return 2;
+}
+
+template <>
+StubAtom<ppc>::StubAtom(Writer<ppc>& writer, ObjectFile::Atom& target)
+ : WriterAtom<ppc>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
+{
+       writer.fAllSynthesizedStubs.push_back(this);
+
+       LazyPointerAtom<ppc>* lp = new LazyPointerAtom<ppc>(writer, target);
+       if ( pic() ) {
+               // picbase is 8 bytes into atom
+               fReferences.push_back(new WriterReference<ppc>(12, ppc::kPICBaseHigh16, lp, 0, this, 8));
+               fReferences.push_back(new WriterReference<ppc>(20, ppc::kPICBaseLow16, lp, 0, this, 8));
+       }
+       else {
+               fReferences.push_back(new WriterReference<ppc>(0, ppc::kAbsHigh16AddLow, lp));
+               fReferences.push_back(new WriterReference<ppc>(4, ppc::kAbsLow16, lp));
+       }
+}
+
+template <>
+StubAtom<ppc64>::StubAtom(Writer<ppc64>& writer, ObjectFile::Atom& target)
+ : WriterAtom<ppc64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
+{
+       writer.fAllSynthesizedStubs.push_back(this);
+
+       LazyPointerAtom<ppc64>* lp = new LazyPointerAtom<ppc64>(writer, target);
+       if ( pic() ) {
+               // picbase is 8 bytes into atom
+               fReferences.push_back(new WriterReference<ppc64>(12, ppc64::kPICBaseHigh16, lp, 0, this, 8));
+               fReferences.push_back(new WriterReference<ppc64>(20, ppc64::kPICBaseLow14, lp, 0, this, 8));
+       }
+       else {
+               fReferences.push_back(new WriterReference<ppc64>(0, ppc64::kAbsHigh16AddLow, lp));
+               fReferences.push_back(new WriterReference<ppc64>(4, ppc64::kAbsLow14, lp));
+       }
+}
+
+// specialize to put x86 fast stub in __IMPORT segment with no lazy pointer
+template <>
+StubAtom<x86>::StubAtom(Writer<x86>& writer, ObjectFile::Atom& target)
+ : WriterAtom<x86>(writer, writer.fOptions.readOnlyx86Stubs() ? Segment::fgROImportSegment : Segment::fgImportSegment), 
+                               fTarget(target)
+{
+       if ( &target == NULL )
+               fName = "cache-line-crossing-stub";
+       else {
+               fName = stubName(target.getName());
+               writer.fAllSynthesizedStubs.push_back(this);
+       }
+}
+
+template <>
+StubAtom<x86_64>::StubAtom(Writer<x86_64>& writer, ObjectFile::Atom& target)
+ : WriterAtom<x86_64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
+{
+       writer.fAllSynthesizedStubs.push_back(this);
+
+       LazyPointerAtom<x86_64>* lp = new LazyPointerAtom<x86_64>(writer, target);
+       fReferences.push_back(new WriterReference<x86_64>(2, x86_64::kPCRel32, lp));
+}
+
+template <typename A>
+const char* StubAtom<A>::stubName(const char* name)
+{
+       char* buf;
+       asprintf(&buf, "%s$stub", name);
+       return buf;
+}
+
+template <>
+uint64_t StubAtom<ppc>::getSize() const
+{
+       return ( pic() ? 32 : 16 );
+}
+
+template <>
+uint64_t StubAtom<ppc64>::getSize() const
+{
+       return ( pic() ? 32 : 16 );
+}
+
+template <>
+uint64_t StubAtom<x86>::getSize() const
+{
+       return 5;
+}
+
+template <>
+uint64_t StubAtom<x86_64>::getSize() const
+{
+       return 6;
+}
+
+template <>
+ObjectFile::Alignment StubAtom<x86>::getAlignment() const
+{
+       // special case x86 fast stubs to be byte aligned
+       return 0;
+}
+
+template <>
+void StubAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
+{
+       if ( pic() ) {
+               OSWriteBigInt32(&buffer [0], 0, 0x7c0802a6);    //      mflr r0
+               OSWriteBigInt32(&buffer[ 4], 0, 0x429f0005);    //  bcl 20,31,Lpicbase
+               OSWriteBigInt32(&buffer[ 8], 0, 0x7d6802a6);    // Lpicbase: mflr r11
+               OSWriteBigInt32(&buffer[12], 0, 0x3d6b0000);    //      addis r11,r11,ha16(L_fwrite$lazy_ptr-Lpicbase)
+               OSWriteBigInt32(&buffer[16], 0, 0x7c0803a6);    //      mtlr r0
+               OSWriteBigInt32(&buffer[20], 0, 0xe98b0001);    //      ldu r12,lo16(L_fwrite$lazy_ptr-Lpicbase)(r11)
+               OSWriteBigInt32(&buffer[24], 0, 0x7d8903a6);    //  mtctr r12
+               OSWriteBigInt32(&buffer[28], 0, 0x4e800420);    //  bctr
+       }
+       else {
+               OSWriteBigInt32(&buffer[ 0], 0, 0x3d600000);    // lis r11,ha16(L_fwrite$lazy_ptr)
+               OSWriteBigInt32(&buffer[ 4], 0, 0xe98b0001);    // ldu r12,lo16(L_fwrite$lazy_ptr)(r11)
+               OSWriteBigInt32(&buffer[ 8], 0, 0x7d8903a6);    // mtctr r12
+               OSWriteBigInt32(&buffer[12], 0, 0x4e800420);    // bctr
+       }
+}
+
+template <>
+void StubAtom<ppc>::copyRawContent(uint8_t buffer[]) const
+{
+       if ( pic() ) {
+               OSWriteBigInt32(&buffer[ 0], 0, 0x7c0802a6);    //      mflr r0
+               OSWriteBigInt32(&buffer[ 4], 0, 0x429f0005);    //  bcl 20,31,Lpicbase
+               OSWriteBigInt32(&buffer[ 8], 0, 0x7d6802a6);    // Lpicbase: mflr r11
+               OSWriteBigInt32(&buffer[12], 0, 0x3d6b0000);    //      addis r11,r11,ha16(L_fwrite$lazy_ptr-Lpicbase)
+               OSWriteBigInt32(&buffer[16], 0, 0x7c0803a6);    //      mtlr r0
+               OSWriteBigInt32(&buffer[20], 0, 0x858b0000);    //      lwzu r12,lo16(L_fwrite$lazy_ptr-Lpicbase)(r11)
+               OSWriteBigInt32(&buffer[24], 0, 0x7d8903a6);    //  mtctr r12
+               OSWriteBigInt32(&buffer[28], 0, 0x4e800420);    //  bctr
+       }
+       else {
+               OSWriteBigInt32(&buffer[ 0], 0, 0x3d600000);    // lis r11,ha16(L_fwrite$lazy_ptr)
+               OSWriteBigInt32(&buffer[ 4], 0, 0x858b0000);    // lwzu r12,lo16(L_fwrite$lazy_ptr)(r11)
+               OSWriteBigInt32(&buffer[ 8], 0, 0x7d8903a6);    // mtctr r12
+               OSWriteBigInt32(&buffer[12], 0, 0x4e800420);    // bctr
+       }
+}
+
+template <>
+void StubAtom<x86>::copyRawContent(uint8_t buffer[]) const
+{
+       if ( fWriter.fOptions.prebind() ) {
+               uint32_t address = this->getAddress();
+               int32_t rel32 = 0 - (address+5); 
+               buffer[0] = 0xE9;
+               buffer[1] = rel32 & 0xFF;
+               buffer[2] = (rel32 >> 8) & 0xFF;
+               buffer[3] = (rel32 >> 16) & 0xFF;
+               buffer[4] = (rel32 >> 24) & 0xFF;
+       }
+       else {
+               buffer[0] = 0xF4;
+               buffer[1] = 0xF4;
+               buffer[2] = 0xF4;
+               buffer[3] = 0xF4;
+               buffer[4] = 0xF4;
+       }
+}
+
+template <>
+void StubAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
+{
+       buffer[0] = 0xFF;               // jmp *foo$lazy_pointer(%rip)
+       buffer[1] = 0x25;
+       buffer[2] = 0x00;
+       buffer[3] = 0x00;
+       buffer[4] = 0x00;
+       buffer[5] = 0x00;
+}
+
+// x86_64 stubs are 7 bytes and need no alignment
+template <>
+ObjectFile::Alignment StubAtom<x86_64>::getAlignment() const
+{
+       return 0;
+}
+
+template <>
+const char*    StubAtom<ppc>::getSectionName() const
+{
+       return ( pic() ? "__picsymbolstub1" : "__symbol_stub1");
+}
+
+template <>
+const char*    StubAtom<ppc64>::getSectionName() const
+{
+       return ( pic() ? "__picsymbolstub1" : "__symbol_stub1");
+}
+
+template <>
+const char*    StubAtom<x86>::getSectionName() const
+{
+       return "__jump_table";
+}
+
+
+
+
+struct AtomByNameSorter
+{
+     bool operator()(ObjectFile::Atom* left, ObjectFile::Atom* right)
+     {
+          return (strcmp(left->getName(), right->getName()) < 0);
+     }
+};
+
+template <typename P>
+struct ExternalRelocSorter
+{
+     bool operator()(const macho_relocation_info<P>& left, const macho_relocation_info<P>& right)
+     {
+               // sort first by symbol number
+               if ( left.r_symbolnum() != right.r_symbolnum() )
+                       return (left.r_symbolnum() < right.r_symbolnum());
+               // then sort all uses of the same symbol by address
+               return (left.r_address() < right.r_address());
+     }
+};
+
+
+template <typename A>
+Writer<A>::Writer(const char* path, Options& options, std::vector<ExecutableFile::DyLibUsed>& dynamicLibraries)
+       : ExecutableFile::Writer(dynamicLibraries), fFilePath(strdup(path)), fOptions(options), fLoadCommandsSection(NULL),
+         fLoadCommandsSegment(NULL), fPadSegmentInfo(NULL),  fSplitCodeToDataContentAtom(NULL), fModuleInfoAtom(NULL), 
+         fPageZeroAtom(NULL),  fSymbolTableCount(0),  fLargestAtomSize(1), 
+        fEmitVirtualSections(false), fHasWeakExports(false), fReferencesWeakImports(false), 
+         fCanScatter(false), fWritableSegmentPastFirst4GB(false), fNoReExportedDylibs(false), fSlideable(false), 
+         fFirstWritableSegment(NULL), fAnonNameIndex(1000)
+{
+       // for UNIX conformance, error if file exists and is not writable
+       if ( (access(path, F_OK) == 0) && (access(path, W_OK) == -1) )
+               throwf("can't write output file: %s", path);
+
+       int permissions = 0777;
+       if ( fOptions.outputKind() == Options::kObjectFile )
+               permissions = 0666;
+       // Calling unlink first assures the file is gone so that open creates it with correct permissions
+       // It also handles the case where fFilePath file is not writable but its directory is
+       // And it means we don't have to truncate the file when done writing (in case new is smaller than old)
+       (void)unlink(fFilePath);
+       fFileDescriptor = open(fFilePath, O_CREAT | O_WRONLY | O_TRUNC, permissions);
+       if ( fFileDescriptor == -1 ) {
+               throwf("can't open output file for writing: %s", path);
+       }
+
+       switch ( fOptions.outputKind() ) {
+               case Options::kDynamicExecutable:
+               case Options::kStaticExecutable:
+                       if ( fOptions.zeroPageSize() != 0 )
+                               fWriterSynthesizedAtoms.push_back(fPageZeroAtom = new PageZeroAtom<A>(*this));
+                       if ( fOptions.outputKind() == Options::kDynamicExecutable )
+                               fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
+                       if ( fOptions.outputKind() == Options::kDynamicExecutable )
+                               fWriterSynthesizedAtoms.push_back(new DyldLoadCommandsAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
+                       if ( fOptions.hasCustomStack() )
+                               fWriterSynthesizedAtoms.push_back(new CustomStackAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
+                       break;
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+                       fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
+                       // fall through
+               case Options::kObjectFile:
+                       fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
+                       if ( fOptions.outputKind() == Options::kDynamicLibrary ) {
+                               fWriterSynthesizedAtoms.push_back(new DylibIDLoadCommandsAtom<A>(*this));
+                               if ( fOptions.initFunctionName() != NULL )
+                                       fWriterSynthesizedAtoms.push_back(new RoutinesLoadCommandsAtom<A>(*this));
+                       }
+                       fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
+                       if ( fOptions.sharedRegionEligible() )
+                               fWriterSynthesizedAtoms.push_back(new SegmentSplitInfoLoadCommandsAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
+                       if ( fOptions.sharedRegionEligible() ) {
+                               fWriterSynthesizedAtoms.push_back(fSplitCodeToDataContentAtom = new SegmentSplitInfoContentAtom<A>(*this));
+                       }
+                       fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
+                       if ( this->needsModuleTable() )
+                               fWriterSynthesizedAtoms.push_back(fModuleInfoAtom = new ModuleInfoLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
+                       break;
+               case Options::kDyld:
+                       fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new DyldLoadCommandsAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
+                       fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
+                       break;
+       }
+
+       // add extra commmands
+       bool hasReExports = false;
+       uint8_t ordinal = 1;
+       switch ( fOptions.outputKind() ) {
+               case Options::kDynamicExecutable:
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+                       {
+                               // add dylib load command atoms for all dynamic libraries
+                               const unsigned int libCount = dynamicLibraries.size();
+                               for (unsigned int i=0; i < libCount; ++i) {
+                                       ExecutableFile::DyLibUsed& dylibInfo = dynamicLibraries[i];
+                                       //fprintf(stderr, "dynamicLibraries[%d]: reader=%p, %s, install=%s\n", i, dylibInfo.reader, dylibInfo.reader->getPath(), dylibInfo.reader->getInstallPath() );
+                                       
+                                       if ( dylibInfo.options.fReExport ) {
+                                               hasReExports = true;
+                                       }
+                                       else {
+                                               const char* parentUmbrella = dylibInfo.reader->parentUmbrella();
+                                               if ( (parentUmbrella != NULL) && (fOptions.outputKind() == Options::kDynamicLibrary) ) {
+                                                       const char* thisIDLastSlash = strrchr(fOptions.installPath(), '/');
+                                                       if ( (thisIDLastSlash != NULL) && (strcmp(&thisIDLastSlash[1], parentUmbrella) == 0) )
+                                                               hasReExports = true;
+                                               }
+                                       }
+                               
+                                       if ( dylibInfo.options.fBundleLoader ) {
+                                               fLibraryToOrdinal[dylibInfo.reader] = EXECUTABLE_ORDINAL;
+                                       }
+                                       else {
+                                               // see if a DylibLoadCommandsAtom has already been created for this install path
+                                               bool newDylib = true;
+                                               const char* dylibInstallPath = dylibInfo.reader->getInstallPath();
+                                               for (unsigned int seenLib=0; seenLib < i; ++seenLib) {
+                                                       ExecutableFile::DyLibUsed& seenDylibInfo = dynamicLibraries[seenLib];
+                                                       if ( !seenDylibInfo.options.fBundleLoader ) {
+                                                               const char* seenDylibInstallPath = seenDylibInfo.reader->getInstallPath();
+                                                               if ( strcmp(seenDylibInstallPath, dylibInstallPath) == 0 ) {
+                                                                       fLibraryToOrdinal[dylibInfo.reader] = fLibraryToOrdinal[seenDylibInfo.reader];
+                                                                       fLibraryToLoadCommand[dylibInfo.reader] = fLibraryToLoadCommand[seenDylibInfo.reader]; 
+                                                                       fLibraryAliases[dylibInfo.reader] = seenDylibInfo.reader;
+                                                                       newDylib = false;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+
+                                               if ( newDylib ) {
+                                                       // assign new ordinal and check for other paired load commands
+                                                       fLibraryToOrdinal[dylibInfo.reader] = ordinal++;
+                                                       DylibLoadCommandsAtom<A>* dyliblc = new DylibLoadCommandsAtom<A>(*this, dylibInfo);
+                                                       fLibraryToLoadCommand[dylibInfo.reader] = dyliblc;
+                                                       fWriterSynthesizedAtoms.push_back(dyliblc);
+                                                       if ( dylibInfo.options.fReExport 
+                                                               && (fOptions.macosxVersionMin() < ObjectFile::ReaderOptions::k10_5)
+                                                               && (fOptions.outputKind() == Options::kDynamicLibrary) ) {
+                                                               // see if child has sub-framework that is this
+                                                               bool isSubFramework = false;
+                                                               const char* childInUmbrella = dylibInfo.reader->parentUmbrella();
+                                                               if ( childInUmbrella != NULL ) {
+                                                                       const char* myLeaf = strrchr(fOptions.installPath(), '/');
+                                                                       if ( myLeaf != NULL ) {
+                                                                               if ( strcmp(childInUmbrella, &myLeaf[1]) == 0 )
+                                                                                       isSubFramework = true;
+                                                                       }
+                                                               }
+                                                               // LC_SUB_FRAMEWORK is in child, so do nothing in parent 
+                                                               if ( ! isSubFramework ) {
+                                                                       // this dylib also needs a sub_x load command
+                                                                       bool isFrameworkReExport = false;
+                                                                       const char* lastSlash = strrchr(dylibInstallPath, '/');
+                                                                       if ( lastSlash != NULL ) {
+                                                                               char frameworkName[strlen(lastSlash)+20];
+                                                                               sprintf(frameworkName, "/%s.framework/", &lastSlash[1]);
+                                                                               isFrameworkReExport = (strstr(dylibInstallPath, frameworkName) != NULL);
+                                                                       }
+                                                                       if ( isFrameworkReExport ) {
+                                                                               // needs a LC_SUB_UMBRELLA command
+                                                                               fWriterSynthesizedAtoms.push_back(new SubUmbrellaLoadCommandsAtom<A>(*this, &lastSlash[1]));
+                                                                       }
+                                                                       else {
+                                                                               // needs a LC_SUB_LIBRARY command
+                                                                               const char* nameStart = &lastSlash[1];
+                                                                               if ( lastSlash == NULL )
+                                                                                       nameStart = dylibInstallPath;
+                                                                               int len = strlen(nameStart);
+                                                                               const char* dot = strchr(nameStart, '.');
+                                                                               if ( dot != NULL )
+                                                                                       len = dot - nameStart;
+                                                                               fWriterSynthesizedAtoms.push_back(new SubLibraryLoadCommandsAtom<A>(*this, nameStart, len));
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               // add umbrella command if needed
+                               if ( fOptions.umbrellaName() != NULL ) {
+                                       fWriterSynthesizedAtoms.push_back(new UmbrellaLoadCommandsAtom<A>(*this, fOptions.umbrellaName()));
+                               }
+                               // add allowable client commands if used
+                               std::vector<const char*>& allowableClients = fOptions.allowableClients();
+                               for (std::vector<const char*>::iterator it=allowableClients.begin(); it != allowableClients.end(); ++it)
+                                       fWriterSynthesizedAtoms.push_back(new AllowableClientLoadCommandsAtom<A>(*this, *it));
+                       }
+                       break;
+               case Options::kStaticExecutable:
+               case Options::kObjectFile:
+               case Options::kDyld:
+                       break;
+       }
+       fNoReExportedDylibs = !hasReExports;
+       
+       // add any rpath load commands
+       for(std::vector<const char*>::const_iterator it=fOptions.rpaths().begin(); it != fOptions.rpaths().end(); ++it) {
+               fWriterSynthesizedAtoms.push_back(new RPathLoadCommandsAtom<A>(*this, *it));
+       }
+       
+       // set up fSlideable
+       switch ( fOptions.outputKind() ) {
+               case Options::kObjectFile:
+               case Options::kStaticExecutable:
+                       fSlideable = false;
+                       break;
+               case Options::kDynamicExecutable:
+                       fSlideable = fOptions.positionIndependentExecutable();
+                       break;
+               case Options::kDyld:
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+                       fSlideable =    true;
+                       break;
+       }
+       
+       //fprintf(stderr, "ordinals table:\n");
+       //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
+       //      fprintf(stderr, "%d <== %s\n", it->second, it->first->getPath());
+       //}
+}
+
+template <typename A>
+Writer<A>::~Writer()
+{
+       if ( fFilePath != NULL )
                free((void*)fFilePath);
        if ( fSymbolTable != NULL )
                delete [] fSymbolTable;
@@ -1165,8 +1727,16 @@ template <typename A> bool Writer<A>::mightNeedPadSegment() { return false; }
 template <typename A>
 ObjectFile::Atom* Writer<A>::getUndefinedProxyAtom(const char* name)
 {
-       if ( (fOptions.outputKind() == Options::kObjectFile)
-               || (fOptions.undefinedTreatment() != Options::kUndefinedError) )
+       if ( fOptions.outputKind() == Options::kObjectFile ) {
+               // when doing -r -exported_symbols_list, don't creat proxy for a symbol
+               // that is supposed to be exported.  We want an error instead
+               // <rdar://problem/5062685> ld does not report error when -r is used and exported symbols are not defined.
+               if ( fOptions.hasExportRestrictList() && fOptions.shouldExport(name) )
+                       return NULL;
+               else
+                       return new UndefinedSymbolProxyAtom<A>(*this, name);
+       }
+       else if ( (fOptions.undefinedTreatment() != Options::kUndefinedError) || fOptions.allowedUndefined(name) )  
                return new UndefinedSymbolProxyAtom<A>(*this, name);
        else
                return NULL;
@@ -1191,22 +1761,35 @@ uint8_t Writer<A>::ordinalForLibrary(ObjectFile::Reader* lib)
        throw "can't find ordinal for imported symbol";
 }
 
+template <typename A>
+ObjectFile::Atom& Writer<A>::makeObjcInfoAtom(ObjectFile::Reader::ObjcConstraint objcContraint, bool objcReplacementClasses)
+{
+       return *(new ObjCInfoAtom<A>(*this, objcContraint, objcReplacementClasses));
+}
+
 
 template <typename A>
 uint64_t Writer<A>::write(std::vector<class ObjectFile::Atom*>& atoms,
                                                  std::vector<class ObjectFile::Reader::Stab>& stabs,
                                                  class ObjectFile::Atom* entryPointAtom, class ObjectFile::Atom* dyldHelperAtom,
-                                                 bool createUUID)
+                                                 bool createUUID, bool canScatter, ObjectFile::Reader::CpuConstraint cpuConstraint,
+                                                 bool biggerThanTwoGigs)
 {
        fAllAtoms =  &atoms;
        fStabs =  &stabs;
        fEntryPoint = entryPointAtom;
        fDyldHelper = dyldHelperAtom;
+       fCanScatter = canScatter;
+       fCpuConstraint = cpuConstraint;
+       fBiggerThanTwoGigs = biggerThanTwoGigs;
 
        try {
                // Set for create UUID
                if (createUUID)
-                       fUUIDAtom->emit();
+                       fUUIDAtom->generate();
+
+               // remove uneeded dylib load commands
+               optimizeDylibReferences();
 
                // check for mdynamic-no-pic codegen which force code into low 4GB
                scanForAbsoluteReferences();
@@ -1230,6 +1813,9 @@ uint64_t Writer<A>::write(std::vector<class ObjectFile::Atom*>& atoms,
                // build symbol table and relocations
                buildLinkEdit();
 
+               // write map file if requested
+               writeMap();
+
                // write everything
                return writeAtoms();
        } catch (...) {
@@ -1259,9 +1845,29 @@ uint64_t Writer<A>::getAtomLoadAddress(const ObjectFile::Atom* atom)
 //     return info->getBaseAddress() + atom->getSectionOffset();
 }
 
+
+template <>
+const char* Writer<x86_64>::symbolTableName(const ObjectFile::Atom* atom)
+{
+       static unsigned int counter = 0;
+       const char* name = atom->getName();
+       if ( strncmp(name, "cstring=", 8) == 0 )
+               asprintf((char**)&name, "LC%u", counter++);
+       return name;
+}
+
+template <typename A>
+const char* Writer<A>::symbolTableName(const ObjectFile::Atom* atom)
+{
+       return atom->getName();
+}
+
 template <typename A>
 void Writer<A>::setExportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 {
+       // set n_strx
+       entry->set_n_strx(this->fStringsAtom->add(this->symbolTableName(atom)));
+
        // set n_type
        if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAsAbsolute ) {
                entry->set_n_type(N_EXT | N_ABS);
@@ -1279,7 +1885,8 @@ void Writer<A>::setExportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* ent
        entry->set_n_sect(sectionIndex);
 
        // the __mh_execute_header is magic and must be an absolute symbol
-       if ( (fOptions.outputKind() == Options::kDynamicExecutable) && (sectionIndex==0)
+       if ( (sectionIndex==0) 
+               && (fOptions.outputKind() == Options::kDynamicExecutable)
                && (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAndNeverStrip ))
                entry->set_n_type(N_EXT | N_ABS);
 
@@ -1294,18 +1901,27 @@ void Writer<A>::setExportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* ent
        entry->set_n_desc(desc);
 
        // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
-       entry->set_n_value(this->getAtomLoadAddress(atom));
+       if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
+               entry->set_n_value(atom->getSectionOffset());
+       else
+               entry->set_n_value(this->getAtomLoadAddress(atom));
 }
 
 template <typename A>
 void Writer<A>::setImportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 {
+       // set n_strx
+       entry->set_n_strx(this->fStringsAtom->add(atom->getName()));
+
        // set n_type
-       entry->set_n_type(N_UNDF | N_EXT);
-       if ( fOptions.keepPrivateExterns()
-               && (atom->getScope() == ObjectFile::Atom::scopeLinkageUnit)
-               && (fOptions.outputKind() == Options::kObjectFile) )
+       if ( (fOptions.outputKind() == Options::kObjectFile) 
+               && (atom->getScope() == ObjectFile::Atom::scopeLinkageUnit) 
+               && (atom->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition) )
                entry->set_n_type(N_UNDF | N_EXT | N_PEXT);
+       else if ( fOptions.prebind() )
+               entry->set_n_type(N_PBUD | N_EXT);
+       else 
+               entry->set_n_type(N_UNDF | N_EXT);
 
        // set n_sect
        entry->set_n_sect(0);
@@ -1313,15 +1929,26 @@ void Writer<A>::setImportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* ent
        uint16_t desc = 0;
        if ( fOptions.outputKind() != Options::kObjectFile ) {
                // set n_desc ( high byte is library ordinal, low byte is reference type )
-               desc = REFERENCE_FLAG_UNDEFINED_LAZY; // FIXME
+               std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(atom);
+               if ( pos != fStubsMap.end() )
+                       desc = REFERENCE_FLAG_UNDEFINED_LAZY;
+               else
+                       desc = REFERENCE_FLAG_UNDEFINED_NON_LAZY;
                try {
                        uint8_t ordinal = this->ordinalForLibrary(atom->getFile());
+                       //fprintf(stderr, "ordinal=%u from reader=%p for symbol=%s\n", ordinal, atom->getFile(), atom->getName());
                        SET_LIBRARY_ORDINAL(desc, ordinal);
                }
                catch (const char* msg) {
                        throwf("%s %s from %s", msg, atom->getDisplayName(), atom->getFile()->getPath());
                }
        }
+       else if ( atom->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition ) {
+               uint8_t align = atom->getAlignment().powerOf2;
+               // if alignment does not match size, then record the custom alignment
+               if ( align != __builtin_ctz(atom->getSize()) )
+                       SET_COMM_ALIGN(desc, align);
+       }
        if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAndNeverStrip )
                desc |= REFERENCED_DYNAMICALLY;
        if ( ( fOptions.outputKind() != Options::kObjectFile) && (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
@@ -1337,11 +1964,23 @@ void Writer<A>::setImportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* ent
        entry->set_n_value(atom->getSize());
 }
 
+
 template <typename A>
 void Writer<A>::setLocalNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 {
+       // set n_strx
+       const char* symbolName = this->symbolTableName(atom);
+       char anonName[32];
+       if ( (fOptions.outputKind() == Options::kObjectFile) && !fOptions.keepLocalSymbol(symbolName) ) {
+               sprintf(anonName, "l%u", fAnonNameIndex++);
+               symbolName = anonName;
+       }
+       entry->set_n_strx(this->fStringsAtom->add(symbolName));
+
        // set n_type
        uint8_t type = N_SECT;
+       if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
+               type = N_ABS;
        if ( atom->getScope() == ObjectFile::Atom::scopeLinkageUnit )
                type |= N_PEXT;
        entry->set_n_type(type);
@@ -1362,17 +2001,69 @@ void Writer<A>::setLocalNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entr
        entry->set_n_desc(desc);
 
        // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
-       entry->set_n_value(this->getAtomLoadAddress(atom));
+       if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
+               entry->set_n_value(atom->getSectionOffset());
+       else
+               entry->set_n_value(this->getAtomLoadAddress(atom));
+}
+
+
+template <typename A>
+void Writer<A>::addLocalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name)
+{
+       macho_nlist<P> entry;
+       
+       // set n_strx
+       entry.set_n_strx(fStringsAtom->add(name));
+
+       // set n_type
+       entry.set_n_type(N_SECT);
+
+       // set n_sect (section number of implementation )
+       entry.set_n_sect(atom.getSection()->getIndex());
+
+       // set n_desc
+       entry.set_n_desc(0);
+
+       // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
+       entry.set_n_value(this->getAtomLoadAddress(&atom) + offsetInAtom);
+       
+       // add
+       fLocalExtraLabels.push_back(entry);
 }
 
 
+
+template <typename A>
+void Writer<A>::addGlobalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name)
+{
+       macho_nlist<P> entry;
+       
+       // set n_strx
+       entry.set_n_strx(fStringsAtom->add(name));
+
+       // set n_type
+       entry.set_n_type(N_SECT|N_EXT);
+
+       // set n_sect (section number of implementation )
+       entry.set_n_sect(atom.getSection()->getIndex());
+
+       // set n_desc
+       entry.set_n_desc(0);
+
+       // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
+       entry.set_n_value(this->getAtomLoadAddress(&atom) + offsetInAtom);
+       
+       // add
+       fGlobalExtraLabels.push_back(entry);
+}
+
 template <typename A>
 void Writer<A>::setNlistRange(std::vector<class ObjectFile::Atom*>& atoms, uint32_t startIndex, uint32_t count)
 {
        macho_nlist<P>* entry = &fSymbolTable[startIndex];
        for (uint32_t i=0; i < count; ++i, ++entry) {
                ObjectFile::Atom* atom = atoms[i];
-               entry->set_n_strx(this->fStringsAtom->add(atom->getName()));
                if ( &atoms == &fExportedAtoms ) {
                        this->setExportNlist(atom, entry);
                }
@@ -1385,15 +2076,37 @@ void Writer<A>::setNlistRange(std::vector<class ObjectFile::Atom*>& atoms, uint3
        }
 }
 
+template <typename A>
+void Writer<A>::copyNlistRange(const std::vector<macho_nlist<P> >& entries, uint32_t startIndex)
+{
+       for ( typename std::vector<macho_nlist<P> >::const_iterator it = entries.begin(); it != entries.end(); ++it) 
+               fSymbolTable[startIndex++] = *it;
+}
+
+
+template <typename A>
+struct NListNameSorter
+{
+       NListNameSorter(StringsLinkEditAtom<A>* pool) : fStringPool(pool) {}
+       
+     bool operator()(const macho_nlist<typename A::P>& left, const macho_nlist<typename A::P>& right)
+     {
+          return (strcmp(fStringPool->stringForIndex(left.n_strx()), fStringPool->stringForIndex(right.n_strx())) < 0);
+     }
+private:
+       StringsLinkEditAtom<A>*         fStringPool;
+};
+
+
 template <typename A>
 void Writer<A>::buildSymbolTable()
 {
        fSymbolTableStabsStartIndex             = 0;
        fSymbolTableStabsCount                  = fStabs->size();
        fSymbolTableLocalStartIndex             = fSymbolTableStabsStartIndex + fSymbolTableStabsCount;
-       fSymbolTableLocalCount                  = fLocalSymbolAtoms.size();
+       fSymbolTableLocalCount                  = fLocalSymbolAtoms.size() + fLocalExtraLabels.size();
        fSymbolTableExportStartIndex    = fSymbolTableLocalStartIndex + fSymbolTableLocalCount;
-       fSymbolTableExportCount                 = fExportedAtoms.size();
+       fSymbolTableExportCount                 = fExportedAtoms.size() + fGlobalExtraLabels.size();
        fSymbolTableImportStartIndex    = fSymbolTableExportStartIndex + fSymbolTableExportCount;
        fSymbolTableImportCount                 = fImportedAtoms.size();
 
@@ -1402,10 +2115,23 @@ void Writer<A>::buildSymbolTable()
        fSymbolTable = new macho_nlist<P>[fSymbolTableCount];
 
        // fill in symbol table and string pool (do stabs last so strings are at end of pool)
-       setNlistRange(fLocalSymbolAtoms, fSymbolTableLocalStartIndex,  fSymbolTableLocalCount);
-       setNlistRange(fExportedAtoms,    fSymbolTableExportStartIndex, fSymbolTableExportCount);
+       setNlistRange(fLocalSymbolAtoms, fSymbolTableLocalStartIndex,  fLocalSymbolAtoms.size());
+       if ( fLocalExtraLabels.size() != 0 )
+               copyNlistRange(fLocalExtraLabels, fSymbolTableLocalStartIndex+fLocalSymbolAtoms.size());
+       setNlistRange(fExportedAtoms,    fSymbolTableExportStartIndex, fExportedAtoms.size());
+       if ( fGlobalExtraLabels.size() != 0 ) {
+               copyNlistRange(fGlobalExtraLabels, fSymbolTableExportStartIndex+fExportedAtoms.size());
+               // re-sort combined range
+               std::sort(  &fSymbolTable[fSymbolTableExportStartIndex], 
+                                       &fSymbolTable[fSymbolTableExportStartIndex+fSymbolTableExportCount], 
+                                       NListNameSorter<A>(fStringsAtom) );
+       }
        setNlistRange(fImportedAtoms,    fSymbolTableImportStartIndex, fSymbolTableImportCount);
        addStabs(fSymbolTableStabsStartIndex);
+       
+       // set up module table
+       if ( fModuleInfoAtom != NULL )
+               fModuleInfoAtom->setName();
 }
 
 
@@ -1413,16 +2139,24 @@ void Writer<A>::buildSymbolTable()
 template <typename A>
 bool Writer<A>::shouldExport(const ObjectFile::Atom& atom) const
 {
-       if ( atom.getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn )
-               return false;
-       switch ( atom.getScope() ) {
-               case ObjectFile::Atom::scopeGlobal:
-                       return true;
-               case ObjectFile::Atom::scopeLinkageUnit:
-                       return ( (fOptions.outputKind() == Options::kObjectFile) && fOptions.keepPrivateExterns() );
-               default:
+       switch ( atom.getSymbolTableInclusion() ) {
+               case ObjectFile::Atom::kSymbolTableNotIn:
                        return false;
+               case ObjectFile::Atom::kSymbolTableInAndNeverStrip:
+                       return true;
+               case ObjectFile::Atom::kSymbolTableInAsAbsolute:
+               case ObjectFile::Atom::kSymbolTableIn:
+                       switch ( atom.getScope() ) {
+                               case ObjectFile::Atom::scopeGlobal:
+                                       return true;
+                               case ObjectFile::Atom::scopeLinkageUnit:
+                                       return ( (fOptions.outputKind() == Options::kObjectFile) && fOptions.keepPrivateExterns() );
+                               default:
+                                       return false;
+                       }
+                       break;
        }
+       return false;
 }
 
 template <typename A>
@@ -1433,39 +2167,62 @@ void Writer<A>::collectExportedAndImportedAndLocalAtoms()
        fImportedAtoms.reserve(100);
        fExportedAtoms.reserve(atomCount/2);
        fLocalSymbolAtoms.reserve(atomCount);
-       for (int i=0; i < atomCount; ++i) {
-               ObjectFile::Atom* atom = (*fAllAtoms)[i];
+       for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
+               ObjectFile::Atom* atom = *it;
                // only named atoms go in symbol table
                if ( atom->getName() != NULL ) {
                        // put atom into correct bucket: imports, exports, locals
-                       //printf("collectExportedAndImportedAndLocalAtoms() name=%s\n", atom->getDisplayName());
+                       //fprintf(stderr, "collectExportedAndImportedAndLocalAtoms() name=%s\n", atom->getDisplayName());
                        switch ( atom->getDefinitionKind() ) {
                                case ObjectFile::Atom::kExternalDefinition:
                                case ObjectFile::Atom::kExternalWeakDefinition:
                                        fImportedAtoms.push_back(atom);
                                        break;
                                case ObjectFile::Atom::kTentativeDefinition:
-                                       if ( (fOptions.outputKind() == Options::kObjectFile) && !fOptions.makeTentativeDefinitionsReal() ) {
+                                       if ( (fOptions.outputKind() == Options::kObjectFile) && !fOptions.readerOptions().fMakeTentativeDefinitionsReal ) {
                                                fImportedAtoms.push_back(atom);
                                                break;
                                        }
                                        // else fall into
                                case ObjectFile::Atom::kRegularDefinition:
                                case ObjectFile::Atom::kWeakDefinition:
+                               case ObjectFile::Atom::kAbsoluteSymbol:
                                        if ( this->shouldExport(*atom) )
                                                fExportedAtoms.push_back(atom);
-                                       else if ( !fOptions.stripLocalSymbols()
-                                               && (atom->getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn) )
+                                       else if ( (atom->getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn)
+                                               && ((fOptions.outputKind() == Options::kObjectFile) || fOptions.keepLocalSymbol(atom->getName())) )
                                                fLocalSymbolAtoms.push_back(atom);
                                        break;
                        }
                }
+               // when geneating a .o file, dtrace static probes become local labels
+               if ( fOptions.outputKind() == Options::kObjectFile) {
+                       std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
+                       for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                               ObjectFile::Reference* ref = *rit;
+                               if ( ref->getKind() == A::kDtraceProbe ) {
+                                       // dtrace probe points to be add back into generated .o file
+                                       this->addLocalLabel(*atom, ref->getFixUpOffset(), ref->getTargetName());
+                               }
+                       }
+               }
+               // when linking kernel, old style dtrace static probes become global labels
+               else if ( fOptions.outputKind() == Options::kStaticExecutable ) {
+                       std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
+                       for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                               ObjectFile::Reference* ref = *rit;
+                               if ( ref->getKind() == A::kDtraceProbe ) {
+                                       // dtrace probe points to be add back into generated .o file
+                                       this->addGlobalLabel(*atom, ref->getFixUpOffset(), ref->getTargetName());
+                               }
+                       }
+               }
        }
 
        // sort exported atoms by name
-       std::sort(fExportedAtoms.begin(), fExportedAtoms.end(), ExportSorter());
+       std::sort(fExportedAtoms.begin(), fExportedAtoms.end(), AtomByNameSorter());
        // sort imported atoms by name (not required by runtime, but helps make generated files binary diffable)
-       std::sort(fImportedAtoms.begin(), fImportedAtoms.end(), ExportSorter());
+       std::sort(fImportedAtoms.begin(), fImportedAtoms.end(), AtomByNameSorter());
 }
 
 
@@ -1603,6 +2360,37 @@ uint32_t Writer<A>::symbolIndex(ObjectFile::Atom& atom)
 }
 
 
+template <>
+bool Writer<x86_64>::makesExternalRelocatableReference(ObjectFile::Atom& target) const
+{
+       switch ( target.getSymbolTableInclusion() )      {
+               case ObjectFile::Atom::kSymbolTableNotIn:
+                       return false;
+               case ObjectFile::Atom::kSymbolTableInAsAbsolute:
+               case ObjectFile::Atom::kSymbolTableIn:
+               case ObjectFile::Atom::kSymbolTableInAndNeverStrip:
+                       return true;
+       };
+       return false;
+}
+
+template <typename A>
+bool Writer<A>::makesExternalRelocatableReference(ObjectFile::Atom& target) const
+{
+       switch ( target.getDefinitionKind() ) {
+               case ObjectFile::Atom::kRegularDefinition:
+               case ObjectFile::Atom::kWeakDefinition:
+               case ObjectFile::Atom::kAbsoluteSymbol:
+                       return false;
+               case ObjectFile::Atom::kTentativeDefinition:
+                       return (target.getScope() != ObjectFile::Atom::scopeTranslationUnit);
+               case ObjectFile::Atom::kExternalDefinition:
+               case ObjectFile::Atom::kExternalWeakDefinition:
+                       return shouldExport(target);
+       }
+       return false;
+}
+
 template <typename A>
 void Writer<A>::buildFixups()
 {
@@ -1620,7 +2408,7 @@ template <>
 uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 {
        ObjectFile::Atom& target = ref->getTarget();
-       bool external = (target.getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn);
+       bool external = this->makesExternalRelocatableReference(target);
        uint32_t symbolIndex = external ? this->symbolIndex(target) : target.getSection()->getIndex();
        uint32_t address = atom->getSectionOffset()+ref->getFixUpOffset();
        macho_relocation_info<P> reloc1;
@@ -1640,7 +2428,7 @@ uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Ref
                        reloc1.set_r_length(3);
                        reloc1.set_r_extern(external);
                        reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case x86_64::kPointerDiff32:
@@ -1661,20 +2449,22 @@ uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Ref
                        reloc2.set_r_length(kind==x86_64::kPointerDiff32 ? 2 : 3);
                        reloc2.set_r_extern(fromExternal);
                        reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc2);
+                       fSectionRelocs.push_back(reloc1);
+                       fSectionRelocs.push_back(reloc2);
                        return 2;
                        }
 
                case x86_64::kBranchPCRel32:
                case x86_64::kBranchPCRel32WeakImport:
+               case x86_64::kDtraceProbeSite:
+               case x86_64::kDtraceIsEnabledSite:
                        reloc1.set_r_address(address);
                        reloc1.set_r_symbolnum(symbolIndex);
                        reloc1.set_r_pcrel(true);
                        reloc1.set_r_length(2);
                        reloc1.set_r_extern(external);
                        reloc1.set_r_type(X86_64_RELOC_BRANCH);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case x86_64::kPCRel32:
@@ -1684,7 +2474,7 @@ uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Ref
                        reloc1.set_r_length(2);
                        reloc1.set_r_extern(external);
                        reloc1.set_r_type(X86_64_RELOC_SIGNED);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case x86_64::kPCRel32_1:
@@ -1694,7 +2484,7 @@ uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Ref
                        reloc1.set_r_length(2);
                        reloc1.set_r_extern(external);
                        reloc1.set_r_type(X86_64_RELOC_SIGNED_1);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case x86_64::kPCRel32_2:
@@ -1704,7 +2494,7 @@ uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Ref
                        reloc1.set_r_length(2);
                        reloc1.set_r_extern(external);
                        reloc1.set_r_type(X86_64_RELOC_SIGNED_2);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case x86_64::kPCRel32_4:
@@ -1714,7 +2504,7 @@ uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Ref
                        reloc1.set_r_length(2);
                        reloc1.set_r_extern(external);
                        reloc1.set_r_type(X86_64_RELOC_SIGNED_4);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case x86_64::kPCRel32GOT:
@@ -1725,7 +2515,7 @@ uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Ref
                        reloc1.set_r_length(2);
                        reloc1.set_r_extern(external);
                        reloc1.set_r_type(X86_64_RELOC_GOT);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case x86_64::kPCRel32GOTLoad:
@@ -1736,8 +2526,13 @@ uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Ref
                        reloc1.set_r_length(2);
                        reloc1.set_r_extern(external);
                        reloc1.set_r_type(X86_64_RELOC_GOT_LOAD);
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
+                       
+               case x86_64::kDtraceTypeReference:
+               case x86_64::kDtraceProbe:
+                       // generates no relocs
+                       return 0;
        }
        return 0;
 }
@@ -1747,18 +2542,7 @@ template <>
 uint32_t Writer<x86>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 {
        ObjectFile::Atom& target = ref->getTarget();
-       bool isExtern = false;
-       switch ( target.getDefinitionKind() ) {
-               case ObjectFile::Atom::kRegularDefinition:
-                       isExtern = false;
-                       break;
-               case ObjectFile::Atom::kWeakDefinition:
-               case ObjectFile::Atom::kTentativeDefinition:
-               case ObjectFile::Atom::kExternalDefinition:
-               case ObjectFile::Atom::kExternalWeakDefinition:
-                       isExtern = shouldExport(target);
-                       break;
-       }
+       bool isExtern = this->makesExternalRelocatableReference(target);
        uint32_t symbolIndex = 0;
        if ( isExtern )
                symbolIndex = this->symbolIndex(target);
@@ -1769,6 +2553,11 @@ uint32_t Writer<x86>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Refere
        macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
        macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
        x86::ReferenceKinds kind = (x86::ReferenceKinds)ref->getKind();
+       
+       if ( !isExtern && (sectionNum == 0) && (target.getDefinitionKind() != ObjectFile::Atom::kAbsoluteSymbol) )
+               fprintf(stderr, "ld: warning section index == 0 for %s (kind=%d, scope=%d, inclusion=%d) in %s\n",
+                target.getDisplayName(), target.getDefinitionKind(), target.getScope(), target.getSymbolTableInclusion(), target.getFile()->getPath());
+
 
        switch ( kind ) {
                case x86::kNoFixUp:
@@ -1795,15 +2584,19 @@ uint32_t Writer<x86>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Refere
                                reloc1.set_r_extern(isExtern);
                                reloc1.set_r_type(GENERIC_RELOC_VANILLA);
                        }
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
+               case x86::kPointerDiff16:
                case x86::kPointerDiff:
                        {
-                               pint_t fromAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
+                               //pint_t fromAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
+                               //fprintf(stderr, "addObjectRelocs(): refFromTarget=%s, refTarget=%s, refFromTargetAddr=0x%llX, refFromTargetOffset=0x%llX\n",
+                               //                      ref->getFromTarget().getDisplayName(), ref->getTarget().getDisplayName(), 
+                               //                      ref->getFromTarget().getAddress(), ref->getFromTargetOffset());
                                sreloc1->set_r_scattered(true);
                                sreloc1->set_r_pcrel(false);
-                               sreloc1->set_r_length(2);
+                               sreloc1->set_r_length( (kind==x86::kPointerDiff) ? 2 : 1 );
                                if ( ref->getTarget().getScope() == ObjectFile::Atom::scopeTranslationUnit )
                                        sreloc1->set_r_type(GENERIC_RELOC_LOCAL_SECTDIFF);
                                else
@@ -1812,22 +2605,28 @@ uint32_t Writer<x86>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Refere
                                sreloc1->set_r_value(target.getAddress());
                                sreloc2->set_r_scattered(true);
                                sreloc2->set_r_pcrel(false);
-                               sreloc2->set_r_length(2);
-                               sreloc2->set_r_type(PPC_RELOC_PAIR);
+                               sreloc2->set_r_length( (kind==x86::kPointerDiff) ? 2 : 1 );
+                               sreloc2->set_r_type(GENERIC_RELOC_PAIR);
                                sreloc2->set_r_address(0);
-                               sreloc2->set_r_value(fromAddr);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc2);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                               //if ( &ref->getFromTarget() == &ref->getTarget() )
+                                       sreloc2->set_r_value(ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
+                               //else
+                               //      sreloc2->set_r_value(ref->getFromTarget().getAddress());
+                               fSectionRelocs.push_back(reloc2);
+                               fSectionRelocs.push_back(reloc1);
                                return 2;
                        }
 
                case x86::kPCRel32WeakImport:
                case x86::kPCRel32:
+               case x86::kPCRel16:
+               case x86::kDtraceProbeSite:
+               case x86::kDtraceIsEnabledSite:
                        if ( !isExtern && (ref->getTargetOffset() != 0) ) {
                                // use scattered reloc is target offset is non-zero
                                sreloc1->set_r_scattered(true);
                                sreloc1->set_r_pcrel(true);
-                               sreloc1->set_r_length(2);
+                               sreloc1->set_r_length( (kind==x86::kPCRel16) ? 1 : 2);
                                sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
                                sreloc1->set_r_address(address);
                                sreloc1->set_r_value(target.getAddress());
@@ -1836,12 +2635,17 @@ uint32_t Writer<x86>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Refere
                                reloc1.set_r_address(address);
                                reloc1.set_r_symbolnum(isExtern ? symbolIndex : sectionNum);
                                reloc1.set_r_pcrel(true);
-                               reloc1.set_r_length(2);
+                               reloc1.set_r_length( (kind==x86::kPCRel16) ? 1 : 2);
                                reloc1.set_r_extern(isExtern);
                                reloc1.set_r_type(GENERIC_RELOC_VANILLA);
                        }
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
+                       
+               case x86::kDtraceTypeReference:
+               case x86::kDtraceProbe:
+                       // generates no relocs
+                       return 0;
 
        }
        return 0;
@@ -1849,6 +2653,13 @@ uint32_t Writer<x86>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Refere
 
 
 
+
+template <> uint64_t    Writer<ppc>::maxAddress() { return 0xFFFFFFFFULL; }
+template <> uint64_t  Writer<ppc64>::maxAddress() { return 0xFFFFFFFFFFFFFFFFULL; }
+template <> uint64_t    Writer<x86>::maxAddress() { return 0xFFFFFFFFULL; }
+template <> uint64_t Writer<x86_64>::maxAddress() { return 0xFFFFFFFFFFFFFFFFULL; }
+
+
 template <>
 uint8_t Writer<ppc>::getRelocPointerSize()
 {
@@ -1881,19 +2692,7 @@ template <typename A>
 uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 {
        ObjectFile::Atom& target = ref->getTarget();
-       bool isExtern = false;
-       switch ( target.getDefinitionKind() ) {
-               case ObjectFile::Atom::kRegularDefinition:
-                       isExtern = false;
-                       break;
-               case ObjectFile::Atom::kWeakDefinition:
-               case ObjectFile::Atom::kTentativeDefinition:
-               case ObjectFile::Atom::kExternalDefinition:
-               case ObjectFile::Atom::kExternalWeakDefinition:
-                       isExtern = shouldExport(target);
-                       break;
-       }
-       
+       bool isExtern = this->makesExternalRelocatableReference(target);        
        uint32_t symbolIndex = 0;
        if ( isExtern )
                symbolIndex = this->symbolIndex(target);
@@ -1932,9 +2731,10 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                reloc1.set_r_extern(isExtern);
                                reloc1.set_r_type(GENERIC_RELOC_VANILLA);
                        }
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
+               case A::kPointerDiff16:
                case A::kPointerDiff32:
                case A::kPointerDiff64:
                        {
@@ -1942,23 +2742,25 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                pint_t fromAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
                                sreloc1->set_r_scattered(true);
                                sreloc1->set_r_pcrel(false);
-                               sreloc1->set_r_length( (kind == A::kPointerDiff32) ? 2 : 3);
+                               sreloc1->set_r_length( (kind == A::kPointerDiff32) ? 2 : ((kind == A::kPointerDiff64) ? 3 : 1));
                                sreloc1->set_r_type(ref->getTargetOffset() != 0 ? PPC_RELOC_LOCAL_SECTDIFF : PPC_RELOC_SECTDIFF);
                                sreloc1->set_r_address(address);
                                sreloc1->set_r_value(toAddr);
                                sreloc2->set_r_scattered(true);
                                sreloc2->set_r_pcrel(false);
-                               sreloc2->set_r_length( (kind == A::kPointerDiff32) ? 2 : 3);
+                               sreloc1->set_r_length( (kind == A::kPointerDiff32) ? 2 : ((kind == A::kPointerDiff64) ? 3 : 1));
                                sreloc2->set_r_type(PPC_RELOC_PAIR);
                                sreloc2->set_r_address(0);
                                sreloc2->set_r_value(fromAddr);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc2);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                               fSectionRelocs.push_back(reloc2);
+                               fSectionRelocs.push_back(reloc1);
                                return 2;
                        }
 
                case A::kBranch24WeakImport:
                case A::kBranch24:
+               case A::kDtraceProbeSite:
+               case A::kDtraceIsEnabledSite:
                        if ( (ref->getTargetOffset() == 0) || isExtern ) {
                                reloc1.set_r_address(address);
                                if ( isExtern )
@@ -1978,7 +2780,7 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                sreloc1->set_r_address(address);
                                sreloc1->set_r_value(target.getAddress());
                        }
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case A::kBranch14:
@@ -2001,7 +2803,7 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                sreloc1->set_r_address(address);
                                sreloc1->set_r_value(target.getAddress());
                        }
-                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                       fSectionRelocs.push_back(reloc1);
                        return 1;
 
                case A::kPICBaseLow16:
@@ -2019,10 +2821,10 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                sreloc2->set_r_pcrel(false);
                                sreloc2->set_r_length(2);
                                sreloc2->set_r_type(PPC_RELOC_PAIR);
-                               sreloc2->set_r_address(((toAddr-fromAddr) >> 16));
+                               sreloc2->set_r_address(((toAddr-fromAddr) >> 16) & 0xFFFF);
                                sreloc2->set_r_value(fromAddr);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc2);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                               fSectionRelocs.push_back(reloc2);
+                               fSectionRelocs.push_back(reloc1);
                                return 2;
                        }
 
@@ -2042,8 +2844,8 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                sreloc2->set_r_type(PPC_RELOC_PAIR);
                                sreloc2->set_r_address((toAddr-fromAddr) & 0xFFFF);
                                sreloc2->set_r_value(fromAddr);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc2);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                               fSectionRelocs.push_back(reloc2);
+                               fSectionRelocs.push_back(reloc1);
                                return 2;
                        }
 
@@ -2079,8 +2881,8 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                reloc2.set_r_length(2);
                                reloc2.set_r_extern(false);
                                reloc2.set_r_type(PPC_RELOC_PAIR);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc2);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                               fSectionRelocs.push_back(reloc2);
+                               fSectionRelocs.push_back(reloc1);
                                return 2;
                        }
 
@@ -2115,8 +2917,8 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                reloc2.set_r_length(2);
                                reloc2.set_r_extern(false);
                                reloc2.set_r_type(PPC_RELOC_PAIR);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc2);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                               fSectionRelocs.push_back(reloc2);
+                               fSectionRelocs.push_back(reloc1);
                                return 2;
                        }
 
@@ -2154,16 +2956,35 @@ uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::
                                reloc2.set_r_length(2);
                                reloc2.set_r_extern(false);
                                reloc2.set_r_type(PPC_RELOC_PAIR);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc2);
-                               fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                               fSectionRelocs.push_back(reloc2);
+                               fSectionRelocs.push_back(reloc1);
                                return 2;
                        }
 
+               case A::kDtraceTypeReference:
+               case A::kDtraceProbe:
+                       // generates no relocs
+                       return 0;
        }
        return 0;
 }
 
 
+
+//
+// There are cases when an entry in the indirect symbol table is the magic value
+// INDIRECT_SYMBOL_LOCAL instead of being a symbol index.  When that happens
+// the content of the corresponding part of the __nl_symbol_pointer section
+// must also change. 
+//
+template <typename A>
+bool Writer<A>::indirectSymbolIsLocal(const ObjectFile::Reference* ref) const
+{
+       //  use INDIRECT_SYMBOL_LOCAL in non-lazy-pointers for atoms that won't be in symbol table or have an addend
+       return ( !this->shouldExport(ref->getTarget()) || (ref->getTargetOffset() != 0) );
+}
+
+
 template <typename A>
 void Writer<A>::buildObjectFileFixups()
 {
@@ -2190,8 +3011,6 @@ void Writer<A>::buildObjectFileFixups()
                                        const int refCount = refs.size();
                                        for (int l=0; l < refCount; ++l) {
                                                ObjectFile::Reference* ref = refs[l];
-                                               if ( ref->getKind() == A::kFollowOn )
-                                                       fSeenFollowOnReferences = true;
                                                if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers || curSection->fAllStubs ) {
                                                        uint32_t offsetInSection = atom->getSectionOffset();
                                                        uint32_t indexInSection = offsetInSection / atom->getSize();
@@ -2202,13 +3021,17 @@ void Writer<A>::buildObjectFileFixups()
                                                                undefinedSymbolIndex = this->symbolIndex(stubTargetTarget);
                                                                //fprintf(stderr, "stub %s ==> %s ==> %s ==> index:%u\n", atom->getDisplayName(), stubTarget.getDisplayName(), stubTargetTarget.getDisplayName(), undefinedSymbolIndex);
                                                        }
-                                                       else {
-                                                               // only use INDIRECT_SYMBOL_LOCAL in non-lazy-pointers for atoms that won't be in symbol table
-                                                               if ( curSection->fAllNonLazyPointers && (ref->getTarget().getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn) )
+                                                       else if ( curSection->fAllNonLazyPointers) {
+                                                               // only use INDIRECT_SYMBOL_LOCAL in non-lazy-pointers for atoms that won't be in symbol table or have an addend
+                                                               if ( this->indirectSymbolIsLocal(ref) )
                                                                        undefinedSymbolIndex = INDIRECT_SYMBOL_LOCAL;
                                                                else
                                                                        undefinedSymbolIndex = this->symbolIndex(ref->getTarget());
                                                        }
+                                                       else {
+                                                               // should never get here, fAllLazyPointers not used in generated .o files
+                                                               undefinedSymbolIndex = INDIRECT_SYMBOL_LOCAL;
+                                                       }
                                                        uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
                                                        IndirectEntry entry = { indirectTableIndex, undefinedSymbolIndex };
                                                        //printf("fIndirectTableAtom->fTable.add(sectionIndex=%u, indirectTableIndex=%u => %u), size=%lld\n", indexInSection, indirectTableIndex, undefinedSymbolIndex, atom->getSize());
@@ -2230,7 +3053,7 @@ void Writer<A>::buildObjectFileFixups()
                                                                        reloc1.set_r_length();
                                                                        reloc1.set_r_extern(isExtern);
                                                                        reloc1.set_r_type(GENERIC_RELOC_VANILLA);
-                                                                       fSectionRelocs.insert(fSectionRelocs.begin(), reloc1);
+                                                                       fSectionRelocs.push_back(reloc1);
                                                                        ++relocIndex;
                                                                }
                                                        }
@@ -2238,7 +3061,7 @@ void Writer<A>::buildObjectFileFixups()
                                                                relocIndex += this->addObjectRelocs(atom, ref);
                                                        }
                                                }
-                                               else if ( ref->getKind() != A::kNoFixUp ) {
+                                               else if ( (ref->getKind() != A::kNoFixUp) && (ref->getTargetBinding() != ObjectFile::Reference::kDontBind) ) {
                                                        relocIndex += this->addObjectRelocs(atom, ref);
                                                }
                                        }
@@ -2248,7 +3071,10 @@ void Writer<A>::buildObjectFileFixups()
                }
        }
 
-       // now reverse reloc entries
+       // reverse the relocs
+       std::reverse(fSectionRelocs.begin(), fSectionRelocs.end());
+       
+       // now reverse section reloc offsets
        for(int i=0; i < segCount; ++i) {
                SegmentInfo* curSegment = segmentInfos[i];
                std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
@@ -2262,14 +3088,14 @@ void Writer<A>::buildObjectFileFixups()
 }
 
 template <>
-bool Writer<ppc>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref, bool slideable)
+bool Writer<ppc>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 {
        switch ( ref.getKind() ) {
                case ppc::kAbsLow16:
                case ppc::kAbsLow14:
                case ppc::kAbsHigh16:
                case ppc::kAbsHigh16AddLow:
-                       if ( slideable )
+                       if ( fSlideable )
                                return true;
        }
        return false;
@@ -2277,42 +3103,43 @@ bool Writer<ppc>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& re
 
 
 template <>
-bool Writer<ppc64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref, bool slideable)
+bool Writer<ppc64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 {
        switch ( ref.getKind() ) {
                case ppc::kAbsLow16:
                case ppc::kAbsLow14:
                case ppc::kAbsHigh16:
                case ppc::kAbsHigh16AddLow:
-                       if ( slideable )
+                       if ( fSlideable )
                                return true;
        }
        return false;
 }
 
 template <>
-bool Writer<x86>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref, bool slideable)
+bool Writer<x86>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 {
        if ( ref.getKind() == x86::kAbsolute32 ) {
                switch ( ref.getTarget().getDefinitionKind() ) {
                        case ObjectFile::Atom::kTentativeDefinition:
                        case ObjectFile::Atom::kRegularDefinition:
-                               // illegal in dylibs/bundles, until we support TEXT relocs 
-                               return slideable;
                        case ObjectFile::Atom::kWeakDefinition:
-                               // illegal if an exported weak symbol, until we support TEXT relocs
-                               return this->shouldExport(ref.getTarget());
+                               // illegal in dylibs/bundles, until we support TEXT relocs 
+                               return fSlideable;
                        case ObjectFile::Atom::kExternalDefinition:
                        case ObjectFile::Atom::kExternalWeakDefinition:
                                // illegal until we support TEXT relocs
                                return true;
+                       case ObjectFile::Atom::kAbsoluteSymbol:
+                               // absolute symbbols only allowed in static executables
+                               return ( fOptions.outputKind() != Options::kStaticExecutable);
                }
        }
        return false;
 }
 
 template <>
-bool Writer<x86_64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref, bool slideable)
+bool Writer<x86_64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 {
        return false;
 }
@@ -2321,19 +3148,28 @@ bool Writer<x86_64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference&
 template <typename A>
 typename Writer<A>::RelocKind Writer<A>::relocationNeededInFinalLinkedImage(const ObjectFile::Atom& target) const
 {
-       const bool slideable = (fOptions.outputKind() != Options::kDynamicExecutable) && (fOptions.outputKind() != Options::kStaticExecutable);
-
        switch ( target.getDefinitionKind() ) {
                case ObjectFile::Atom::kTentativeDefinition:
                case ObjectFile::Atom::kRegularDefinition:
+                       // in main executables, the only way regular symbols are indirected is if -interposable is used
+                       if ( fOptions.outputKind() == Options::kDynamicExecutable ) {
+                               if ( this->shouldExport(target) && fOptions.interposable() )
+                                       return kRelocExternal;
+                               else if ( fSlideable )
+                                       return kRelocInternal;
+                               else
+                                       return kRelocNone;
+                       }
                        // for flat-namespace or interposable two-level-namespace
                        // all references to exported symbols get indirected
-                       if ( this->shouldExport(target) &&
-                               ((fOptions.nameSpace() == Options::kFlatNameSpace)
+                       else if ( this->shouldExport(target) &&
+                          ((fOptions.nameSpace() == Options::kFlatNameSpace)
                          || (fOptions.nameSpace() == Options::kForceFlatNameSpace)
-                         || fOptions.interposable()) )
+                         || fOptions.interposable()) 
+                         && (target.getName() != NULL) 
+                         && (strncmp(target.getName(), ".objc_class_", 12) != 0) ) // <rdar://problem/5254468>
                                return kRelocExternal;
-                       else if ( slideable )
+                       else if ( fSlideable )
                                return kRelocInternal;
                        else
                                return kRelocNone;
@@ -2341,13 +3177,15 @@ typename Writer<A>::RelocKind Writer<A>::relocationNeededInFinalLinkedImage(cons
                        // all calls to global weak definitions get indirected
                        if ( this->shouldExport(target) )
                                return kRelocExternal;
-                       else if ( slideable )
+                       else if ( fSlideable )
                                return kRelocInternal;
                        else
                                return kRelocNone;
                case ObjectFile::Atom::kExternalDefinition:
                case ObjectFile::Atom::kExternalWeakDefinition:
                        return kRelocExternal;
+               case ObjectFile::Atom::kAbsoluteSymbol:
+                       return kRelocNone;
        }
        return kRelocNone;
 }
@@ -2356,8 +3194,11 @@ template <typename A>
 uint64_t Writer<A>::relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom) const
 {
        // for 32-bit architectures, the r_address field in relocs
-       // for final linked images is the offset from the base address
-       uint64_t result = address - fOptions.baseAddress();
+       // for final linked images is the offset from the first segment
+       uint64_t result = address - fSegmentInfos[0]->fBaseAddress;
+       // or the offset from the first writable segment if built split-seg
+       if ( fOptions.splitSeg() )
+               result = address - fFirstWritableSegment->fBaseAddress;
        if ( result > 0x7FFFFFFF ) {
                throwf("image too large: address can't fit in 31-bit r_address field in %s from %s",
                        atom->getDisplayName(), atom->getFile()->getPath());
@@ -2389,7 +3230,7 @@ uint64_t Writer<ppc64>::relocAddressInFinalLinkedImage(uint64_t address, const O
        uint64_t result;
        bool badFor10_4 = false;
        if ( fWritableSegmentPastFirst4GB ) {
-               if ( fOptions.macosxVersionMin() < Options::k10_5 )
+               if ( fOptions.macosxVersionMin() < ObjectFile::ReaderOptions::k10_5 )
                        badFor10_4 = true;
                result = address - fFirstWritableSegment->fBaseAddress;
                if ( result > 0xFFFFFFFF ) {
@@ -2398,8 +3239,8 @@ uint64_t Writer<ppc64>::relocAddressInFinalLinkedImage(uint64_t address, const O
                }
        }
        else {
-               result = address - fOptions.baseAddress();
-               if ( (fOptions.macosxVersionMin() < Options::k10_5) && (result > 0x7FFFFFFF) )
+               result = address - fSegmentInfos[0]->fBaseAddress;
+               if ( (fOptions.macosxVersionMin() < ObjectFile::ReaderOptions::k10_5) && (result > 0x7FFFFFFF) )
                        badFor10_4 = true;
        }
        if ( badFor10_4 ) {
@@ -2410,10 +3251,15 @@ uint64_t Writer<ppc64>::relocAddressInFinalLinkedImage(uint64_t address, const O
 }
 
 
+template <> bool    Writer<ppc>::preboundLazyPointerType(uint8_t* type) { *type = PPC_RELOC_PB_LA_PTR; return true; }
+template <> bool  Writer<ppc64>::preboundLazyPointerType(uint8_t* type) { throw "prebinding not supported"; }
+template <> bool    Writer<x86>::preboundLazyPointerType(uint8_t* type) { *type = GENERIC_RELOC_PB_LA_PTR; return true; }
+template <> bool Writer<x86_64>::preboundLazyPointerType(uint8_t* type) { throw "prebinding not supported"; }
+
+
 template <typename A>
 void Writer<A>::buildExecutableFixups()
 {
-       const bool slideable = (fOptions.outputKind() != Options::kDynamicExecutable) && (fOptions.outputKind() != Options::kStaticExecutable);
        fIndirectTableAtom->fTable.reserve(50);  // minimize reallocations
        std::vector<SegmentInfo*>& segmentInfos = fSegmentInfos;
        const int segCount = segmentInfos.size();
@@ -2423,7 +3269,7 @@ void Writer<A>::buildExecutableFixups()
                const int sectionCount = sectionInfos.size();
                for(int j=0; j < sectionCount; ++j) {
                        SectionInfo* curSection = sectionInfos[j];
-                       //fprintf(stderr, "starting section %p\n", curSection->fSectionName);
+                       //fprintf(stderr, "starting section %s\n", curSection->fSectionName);
                        std::vector<ObjectFile::Atom*>& sectionAtoms = curSection->fAtoms;
                        if ( ! curSection->fAllZeroFill ) {
                                if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers || curSection->fAllStubs || curSection->fAllSelfModifyingStubs )
@@ -2454,24 +3300,38 @@ void Writer<A>::buildExecutableFixups()
                                                        IndirectEntry entry = { indirectTableIndex, undefinedSymbolIndex };
                                                        //fprintf(stderr,"fIndirectTableAtom->fTable.add(%d-%d => 0x%X-%s), size=%lld\n", indexInSection, indirectTableIndex, undefinedSymbolIndex, ref->getTarget().getName(), atom->getSize());
                                                        fIndirectTableAtom->fTable.push_back(entry);
-                                                       if ( slideable && curSection->fAllLazyPointers ) {
-                                                               // if this is a dylib/bundle, need vanilla internal relocation to fix up binding handler if image slides
-                                                               macho_relocation_info<P> pblaReloc;
-                                                               uint32_t sectionNum = 1;
-                                                               if ( fDyldHelper != NULL )
-                                                                       sectionNum = ((SectionInfo*)(fDyldHelper->getSection()))->getIndex();
-                                                               //fprintf(stderr, "lazy pointer reloc, section index=%u, section name=%s\n", sectionNum, curSection->fSectionName);
-                                                               pblaReloc.set_r_address(relocAddressInFinalLinkedImage(atom->getAddress(), atom));
-                                                               pblaReloc.set_r_symbolnum(sectionNum);
-                                                               pblaReloc.set_r_pcrel(false);
-                                                               pblaReloc.set_r_length();
-                                                               pblaReloc.set_r_extern(false);
-                                                               pblaReloc.set_r_type(GENERIC_RELOC_VANILLA);
-                                                               fInternalRelocs.push_back(pblaReloc);
+                                                       if ( curSection->fAllLazyPointers ) {
+                                                               uint8_t preboundLazyType;
+                                                               if ( fOptions.prebind() && (fDyldHelper != NULL) && preboundLazyPointerType(&preboundLazyType) ) {
+                                                                       // this is a prebound image, need special relocs for dyld to reset lazy pointers if prebinding is invalid
+                                                                       macho_scattered_relocation_info<P> pblaReloc;
+                                                                       pblaReloc.set_r_scattered(true);
+                                                                       pblaReloc.set_r_pcrel(false);
+                                                                       pblaReloc.set_r_length();
+                                                                       pblaReloc.set_r_type(preboundLazyType);
+                                                                       pblaReloc.set_r_address(relocAddressInFinalLinkedImage(atom->getAddress(), atom));
+                                                                       pblaReloc.set_r_value(fDyldHelper->getAddress());
+                                                                       fInternalRelocs.push_back(*((macho_relocation_info<P>*)&pblaReloc));
+                                                               }
+                                                               else if ( fSlideable ) {
+                                                                       // this is a non-prebound dylib/bundle, need vanilla internal relocation to fix up binding handler if image slides
+                                                                       macho_relocation_info<P> dyldHelperReloc;
+                                                                       uint32_t sectionNum = 1;
+                                                                       if ( fDyldHelper != NULL )
+                                                                               sectionNum = ((SectionInfo*)(fDyldHelper->getSection()))->getIndex();
+                                                                       //fprintf(stderr, "lazy pointer reloc, section index=%u, section name=%s\n", sectionNum, curSection->fSectionName);
+                                                                       dyldHelperReloc.set_r_address(relocAddressInFinalLinkedImage(atom->getAddress(), atom));
+                                                                       dyldHelperReloc.set_r_symbolnum(sectionNum);
+                                                                       dyldHelperReloc.set_r_pcrel(false);
+                                                                       dyldHelperReloc.set_r_length();
+                                                                       dyldHelperReloc.set_r_extern(false);
+                                                                       dyldHelperReloc.set_r_type(GENERIC_RELOC_VANILLA);
+                                                                       fInternalRelocs.push_back(dyldHelperReloc);
+                                                               }
                                                        }
                                                }
-                                               else if ( ref->getKind() == A::kPointer ) {
-                                                       if ( slideable && ((curSegment->fInitProtection & VM_PROT_WRITE) == 0) ) {
+                                               else if ( (ref->getKind() == A::kPointer) || (ref->getKind() == A::kPointerWeakImport) ) {
+                                                       if ( fSlideable && ((curSegment->fInitProtection & VM_PROT_WRITE) == 0) ) {
                                                                throwf("pointer in read-only segment not allowed in slidable image, used in %s from %s",
                                                                                atom->getDisplayName(), atom->getFile()->getPath());
                                                        }
@@ -2510,13 +3370,13 @@ void Writer<A>::buildExecutableFixups()
                                                                        break;
                                                        }
                                                }
-                                               else if ( this->illegalRelocInFinalLinkedImage(*ref, slideable) ) {
+                                               else if ( this->illegalRelocInFinalLinkedImage(*ref) ) {
                                                        throwf("absolute addressing (perhaps -mdynamic-no-pic) used in %s from %s not allowed in slidable image", atom->getDisplayName(), atom->getFile()->getPath());
                                                }
                                        }
                                        if ( curSection->fAllSelfModifyingStubs || curSection->fAllStubs ) {
                                                ObjectFile::Atom* stubTarget = ((StubAtom<A>*)atom)->getTarget();
-                                               uint32_t undefinedSymbolIndex = this->symbolIndex(*stubTarget);
+                                               uint32_t undefinedSymbolIndex = (stubTarget != NULL) ? this->symbolIndex(*stubTarget) : INDIRECT_SYMBOL_ABS;
                                                uint32_t offsetInSection = atom->getSectionOffset();
                                                uint32_t indexInSection = offsetInSection / atom->getSize();
                                                uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
@@ -2528,6 +3388,137 @@ void Writer<A>::buildExecutableFixups()
                        }
                }
        }
+       if ( fSplitCodeToDataContentAtom != NULL )
+               fSplitCodeToDataContentAtom->encode();
+}
+
+
+template <>
+void Writer<ppc>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
+{
+       switch ( (ppc::ReferenceKinds)ref->getKind() ) {
+               case ppc::kPICBaseHigh16:
+                       fSplitCodeToDataContentAtom->addPPCHi16Location(atom, ref->getFixUpOffset());
+                       break;
+               case ppc::kPointerDiff32:
+                       fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
+                       break;
+               case ppc::kPointerDiff64:
+                       fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
+                       break;
+               case ppc::kNoFixUp:
+               case ppc::kPointer:
+               case ppc::kPointerWeakImport:
+               case ppc::kPICBaseLow16:
+               case ppc::kPICBaseLow14:
+                       // ignore
+                       break;
+               default:
+                       fprintf(stderr, "ld: warning codegen with reference kind %d in %s prevents image from loading in dyld shared cache\n", ref->getKind(), atom->getDisplayName());
+                       fSplitCodeToDataContentAtom->setCantEncode();
+       }
+}
+
+template <>
+void Writer<ppc64>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
+{
+       switch ( (ppc64::ReferenceKinds)ref->getKind()  ) {
+               case ppc64::kPICBaseHigh16:
+                       fSplitCodeToDataContentAtom->addPPCHi16Location(atom, ref->getFixUpOffset());
+                       break;
+               case ppc64::kPointerDiff32:
+                       fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
+                       break;
+               case ppc64::kPointerDiff64:
+                       fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
+                       break;
+               case ppc64::kNoFixUp:
+               case ppc64::kPointer:
+               case ppc64::kPointerWeakImport:
+               case ppc64::kPICBaseLow16:
+               case ppc64::kPICBaseLow14:
+                       // ignore
+                       break;
+               default:
+                       fprintf(stderr, "ld: warning codegen with reference kind %d in %s prevents image from loading in dyld shared cache\n", ref->getKind(), atom->getDisplayName());
+                       fSplitCodeToDataContentAtom->setCantEncode();
+       }
+}
+
+template <>
+void Writer<x86>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
+{
+       switch ( (x86::ReferenceKinds)ref->getKind()  ) {
+               case x86::kPointerDiff:
+                       if ( strcmp(ref->getTarget().getSegment().getName(), "__IMPORT") == 0 ) 
+                               fSplitCodeToDataContentAtom->add32bitImportLocation(atom, ref->getFixUpOffset());
+                       else
+                               fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
+                       break;
+               case x86::kNoFixUp:
+               case x86::kPointer:
+               case x86::kPointerWeakImport:
+                       // ignore
+                       break;
+               case x86::kPCRel32:
+               case x86::kPCRel32WeakImport:
+                       if (    (&(ref->getTarget().getSegment()) == &Segment::fgImportSegment)
+                               ||  (&(ref->getTarget().getSegment()) == &Segment::fgROImportSegment) ) {
+                               fSplitCodeToDataContentAtom->add32bitImportLocation(atom, ref->getFixUpOffset());
+                               break;
+                       }
+                       // fall into warning case
+               default:
+                       fprintf(stderr, "ld: warning codegen in %s (offset 0x%08llX) prevents image from loading in dyld shared cache\n", atom->getDisplayName(), ref->getFixUpOffset());
+                       fSplitCodeToDataContentAtom->setCantEncode();
+       }
+}
+
+template <>
+void Writer<x86_64>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
+{
+       switch ( (x86_64::ReferenceKinds)ref->getKind()  ) {
+               case x86_64::kPCRel32:
+               case x86_64::kPCRel32_1:
+               case x86_64::kPCRel32_2:
+               case x86_64::kPCRel32_4:
+               case x86_64::kPCRel32GOTLoad:
+               case x86_64::kPCRel32GOTLoadWeakImport:
+               case x86_64::kPCRel32GOT:
+               case x86_64::kPCRel32GOTWeakImport:
+               case x86_64::kPointerDiff32:
+                       fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
+                       break;
+               case x86_64::kPointerDiff:
+                       fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
+                       break;
+               case x86_64::kNoFixUp:
+               case x86_64::kPointer:
+                       // ignore
+                       break;
+               default:
+                       fprintf(stderr, "ld: warning codegen in %s with kind %d prevents image from loading in dyld shared cache\n", atom->getDisplayName(), ref->getKind());
+                       fSplitCodeToDataContentAtom->setCantEncode();
+       }
+}
+
+
+template <typename A>
+bool Writer<A>::segmentsCanSplitApart(const ObjectFile::Atom& from, const ObjectFile::Atom& to)
+{
+       switch ( to.getDefinitionKind() ) {
+               case ObjectFile::Atom::kExternalDefinition:
+               case ObjectFile::Atom::kExternalWeakDefinition:
+               case ObjectFile::Atom::kAbsoluteSymbol:
+                       return false;
+               case ObjectFile::Atom::kRegularDefinition:
+               case ObjectFile::Atom::kWeakDefinition:
+               case ObjectFile::Atom::kTentativeDefinition:
+                       // segments with same permissions slide together
+                       return ( (from.getSegment().isContentExecutable() != to.getSegment().isContentExecutable())
+                                       || (from.getSegment().isContentWritable() != to.getSegment().isContentWritable()) );
+       }
+       throw "ld64 internal error";
 }
 
 
@@ -2565,56 +3556,233 @@ void Writer<x86_64>::writeNoOps(uint32_t from, uint32_t to)
                ::pwrite(fFileDescriptor, &x86Nop, 1, p);
 }
 
+
+template <>
+void Writer<ppc>::copyNoOps(uint8_t* from, uint8_t* to)
+{
+       for (uint8_t* p=from; p < to; p += 4)
+               OSWriteBigInt32((uint32_t*)p, 0, 0x60000000);
+}
+
+template <>
+void Writer<ppc64>::copyNoOps(uint8_t* from, uint8_t* to)
+{
+       for (uint8_t* p=from; p < to; p += 4)
+               OSWriteBigInt32((uint32_t*)p, 0, 0x60000000);
+}
+
+template <>
+void Writer<x86>::copyNoOps(uint8_t* from, uint8_t* to)
+{
+       for (uint8_t* p=from; p < to; ++p)
+               *p = 0x90;
+}
+
+template <>
+void Writer<x86_64>::copyNoOps(uint8_t* from, uint8_t* to)
+{
+       for (uint8_t* p=from; p < to; ++p)
+               *p = 0x90;
+}
+
+
+static const char* stringName(const char* str)
+{
+       if ( strncmp(str, "cstring=", 8) == 0)  {
+               static char buffer[1024];
+               char* t = buffer;
+               *t++ = '\"';
+               for(const char*s = &str[8]; *s != '\0'; ++s) {
+                       switch(*s) {
+                               case '\n':
+                                       *t++ = '\\';
+                                       *t++ = 'n';
+                                       break;
+                               case '\t':
+                                       *t++ = '\\';
+                                       *t++ = 't';
+                                       break;
+                               default:
+                                       *t++ = *s;
+                                       break;
+                       }
+                       if ( t > &buffer[1020] ) {
+                               *t++= '\"';
+                               *t++= '.';
+                               *t++= '.';
+                               *t++= '.';
+                               *t++= '\0';
+                               return buffer;
+                       }
+               }
+               *t++= '\"';
+               *t++= '\0';
+               return buffer;
+       }
+       else {
+               return str;
+       }
+}
+
+
+template <> const char* Writer<ppc>::getArchString()    { return "ppc"; }
+template <> const char* Writer<ppc64>::getArchString()  { return "ppc64"; }
+template <> const char* Writer<x86>::getArchString()    { return "i386"; }
+template <> const char* Writer<x86_64>::getArchString() { return "x86_64"; }
+
+template <typename A>
+void Writer<A>::writeMap()
+{
+       if ( fOptions.generatedMapPath() != NULL ) {
+               FILE* mapFile = fopen(fOptions.generatedMapPath(), "w"); 
+               if ( mapFile != NULL ) {
+                       // write output path
+                       fprintf(mapFile, "# Path: %s\n", fFilePath);
+                       // write output architecure
+                       fprintf(mapFile, "# Arch: %s\n", getArchString());
+                       // write UUID
+                       if ( fUUIDAtom != NULL ) {
+                               const uint8_t* uuid = fUUIDAtom->getUUID();
+                               fprintf(mapFile, "# UUID: %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X \n",
+                                       uuid[0], uuid[1], uuid[2],  uuid[3],  uuid[4],  uuid[5],  uuid[6],  uuid[7],
+                                       uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
+                       }
+                       // write table of object files
+                       std::map<ObjectFile::Reader*, uint32_t> readerToOrdinal;
+                       std::map<uint32_t, ObjectFile::Reader*> ordinalToReader;
+                       std::map<ObjectFile::Reader*, uint32_t> readerToFileOrdinal;
+                       for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
+                               std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
+                               for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
+                                       if ( ! (*secit)->fVirtualSection ) {
+                                               std::vector<ObjectFile::Atom*>& sectionAtoms = (*secit)->fAtoms;
+                                               for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
+                                                       ObjectFile::Reader* reader = (*ait)->getFile();
+                                                       uint32_t readerOrdinal = (*ait)->getOrdinal();
+                                                       std::map<ObjectFile::Reader*, uint32_t>::iterator pos = readerToOrdinal.find(reader);
+                                                       if ( pos == readerToOrdinal.end() ) {
+                                                               readerToOrdinal[reader] = readerOrdinal;
+                                                               ordinalToReader[readerOrdinal] = reader;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       fprintf(mapFile, "# Object files:\n");
+                       fprintf(mapFile, "[%3u] %s\n", 0, "linker synthesized");
+                       uint32_t fileIndex = 0;
+                       readerToFileOrdinal[this] = fileIndex++;
+                       for(std::map<uint32_t, ObjectFile::Reader*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
+                               if ( it->first != 0 ) {
+                                       fprintf(mapFile, "[%3u] %s\n", fileIndex, it->second->getPath());
+                                       readerToFileOrdinal[it->second] = fileIndex++;
+                               }
+                       }
+                       // write table of sections
+                       fprintf(mapFile, "# Sections:\n");
+                       fprintf(mapFile, "# Address\tSize    \tSegment\tSection\n"); 
+                       for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
+                               std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
+                               for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
+                                       if ( ! (*secit)->fVirtualSection ) {
+                                               SectionInfo* sect = *secit;
+                                               fprintf(mapFile, "0x%08llX\t0x%08llX\t%s\t%s\n", sect->getBaseAddress(), sect->fSize, 
+                                                       (*segit)->fName, sect->fSectionName);
+                                       }
+                               }
+                       }
+                       // write table of symbols
+                       fprintf(mapFile, "# Symbols:\n");
+                       fprintf(mapFile, "# Address\tSize    \tFile  Name\n"); 
+                       for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
+                               std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
+                               for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
+                                       if ( ! (*secit)->fVirtualSection ) {
+                                               std::vector<ObjectFile::Atom*>& sectionAtoms = (*secit)->fAtoms;
+                                               bool isCstring = (strcmp((*secit)->fSectionName, "__cstring") == 0);
+                                               for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
+                                                       ObjectFile::Atom* atom = *ait;
+                                                       fprintf(mapFile, "0x%08llX\t0x%08llX\t[%3u] %s\n", atom->getAddress(), atom->getSize(), 
+                                                               readerToFileOrdinal[atom->getFile()], isCstring ? stringName(atom->getDisplayName()): atom->getDisplayName());
+                                               }
+                                       }
+                               }
+                       }
+                       fclose(mapFile);
+               }
+               else {
+                       fprintf(stderr, "ld: warning could not write map file: %s\n", fOptions.generatedMapPath());
+               }
+       }
+}
+
 template <typename A>
 uint64_t Writer<A>::writeAtoms()
 {
+       // try to allocate buffer for entire output file content
+       SectionInfo* lastSection = fSegmentInfos.back()->fSections.back();
+       uint64_t fileBufferSize = (lastSection->fFileOffset + lastSection->fSize + 4095) & (-4096);
+       uint8_t* wholeBuffer = (uint8_t*)calloc(fileBufferSize, 1);
+       uint8_t* atomBuffer = NULL;
+       bool streaming = false;
+       if ( wholeBuffer == NULL ) {
+               atomBuffer = new uint8_t[(fLargestAtomSize+4095) & (-4096)];
+               streaming = true;
+       }
+       uint32_t size = 0;
        uint32_t end = 0;
-       uint8_t* buffer = new uint8_t[(fLargestAtomSize+4095) & (-4096)];
-       std::vector<SegmentInfo*>& segmentInfos = fSegmentInfos;
-       const int segCount = segmentInfos.size();
-       for(int i=0; i < segCount; ++i) {
-               SegmentInfo* curSegment = segmentInfos[i];
-               bool isTextSeg = ((curSegment->fInitProtection & VM_PROT_EXECUTE) != 0);
+       for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
+               SegmentInfo* curSegment = *segit;
+               bool isTextSeg = (strcmp(curSegment->fName, "__TEXT") == 0);
                std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
-               const int sectionCount = sectionInfos.size();
-               for(int j=0; j < sectionCount; ++j) {
-                       SectionInfo* curSection = sectionInfos[j];
+               for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
+                       SectionInfo* curSection = *secit;
                        std::vector<ObjectFile::Atom*>& sectionAtoms = curSection->fAtoms;
                        //printf("writing with max atom size 0x%X\n", fLargestAtomSize);
                        //fprintf(stderr, "writing %d atoms for section %s\n", (int)sectionAtoms.size(), curSection->fSectionName);
                        if ( ! curSection->fAllZeroFill ) {
-                               const int atomCount = sectionAtoms.size();
                                end = curSection->fFileOffset;
                                bool needsNops = isTextSeg && (strcmp(curSection->fSectionName, "__cstring") != 0);
-                               for (int k=0; k < atomCount; ++k) {
-                                       ObjectFile::Atom* atom = sectionAtoms[k];
+                               for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
+                                       ObjectFile::Atom* atom = *ait;
                                        if ( (atom->getDefinitionKind() != ObjectFile::Atom::kExternalDefinition)
-                                         && (atom->getDefinitionKind() != ObjectFile::Atom::kExternalWeakDefinition) ) {
-                                               uint32_t offset = curSection->fFileOffset + atom->getSectionOffset();
-                                               if ( offset != end ) {
+                                         && (atom->getDefinitionKind() != ObjectFile::Atom::kExternalWeakDefinition)
+                                         && (atom->getDefinitionKind() != ObjectFile::Atom::kAbsoluteSymbol) ) {
+                                               uint32_t fileOffset = curSection->fFileOffset + atom->getSectionOffset();
+                                               if ( fileOffset != end ) {
                                                        if ( needsNops ) {
                                                                // fill gaps with no-ops
-                                                               writeNoOps(end, offset);
+                                                               if ( streaming )
+                                                                       writeNoOps(end, fileOffset);
+                                                               else
+                                                                       copyNoOps(&wholeBuffer[end], &wholeBuffer[fileOffset]);
                                                        }
-                                                       else {
+                                                       else if ( streaming ) {
                                                                // zero fill gaps
-                                                               if ( (offset-end) == 4 ) {
+                                                               if ( (fileOffset-end) == 4 ) {
                                                                        uint32_t zero = 0;
                                                                        ::pwrite(fFileDescriptor, &zero, 4, end);
                                                                }
                                                                else {
                                                                        uint8_t zero = 0x00;
-                                                                       for (uint32_t p=end; p < offset; ++p)
+                                                                       for (uint32_t p=end; p < fileOffset; ++p)
                                                                                ::pwrite(fFileDescriptor, &zero, 1, p);
                                                                }
                                                        }
                                                }
                                                uint64_t atomSize = atom->getSize();
-                                               if ( atomSize > fLargestAtomSize ) {
-                                                       throwf("ld64 internal error: atom \"%s\"is larger than expected 0x%X > 0x%llX", 
-                                                               atom->getDisplayName(), atomSize, fLargestAtomSize);
+                                               if ( streaming ) {
+                                                       if ( atomSize > fLargestAtomSize ) 
+                                                               throwf("ld64 internal error: atom \"%s\"is larger than expected 0x%X > 0x%llX", 
+                                                                                       atom->getDisplayName(), atomSize, fLargestAtomSize);
+                                               }
+                                               else {
+                                                       if ( fileOffset > fileBufferSize )
+                                                               throwf("ld64 internal error: atom \"%s\" has file offset greater thatn expceted 0x%X > 0x%llX", 
+                                                                                       atom->getDisplayName(), fileOffset, fileBufferSize);
                                                }
-                                               end = offset+atomSize;
+                                               uint8_t* buffer = streaming ? atomBuffer : &wholeBuffer[fileOffset];
+                                               end = fileOffset+atomSize;
                                                // copy raw bytes
                                                atom->copyRawContent(buffer);
                                                // apply any fix-ups
@@ -2638,15 +3806,66 @@ uint64_t Writer<A>::writeAtoms()
                                                        throwf("%s in %s from %s", msg, atom->getDisplayName(), atom->getFile()->getPath());
                                                }
                                                //fprintf(stderr, "writing 0x%08X -> 0x%08X (addr=0x%llX, size=0x%llX), atom %s from %s\n", 
-                                               //      offset, end, atom->getAddress(), atom->getSize(), atom->getDisplayName(), atom->getFile()->getPath());
-                                               // write out
-                                               ::pwrite(fFileDescriptor, buffer, atom->getSize(), offset);
+                                               //      fileOffset, end, atom->getAddress(), atom->getSize(), atom->getDisplayName(), atom->getFile()->getPath());
+                                               if ( streaming ) {
+                                                       // write out
+                                                       ::pwrite(fFileDescriptor, buffer, atomSize, fileOffset);
+                                               }
+                                               else {
+                                                       if ( (fileOffset + atomSize) > size )
+                                                               size = fileOffset + atomSize;
+                                               }
                                        }
                                }
                        }
                }
        }
-       delete [] buffer;
+       
+       // update content based UUID
+       if ( fOptions.getUUIDMode() == Options::kUUIDContent ) {
+               uint8_t digest[CC_MD5_DIGEST_LENGTH];
+               if ( streaming ) {
+                       // if output file file did not fit in memory, re-read file to generate md5 hash
+                       uint32_t kMD5BufferSize = 16*1024;
+                       uint8_t* md5Buffer = (uint8_t*)::malloc(kMD5BufferSize);
+                       if ( md5Buffer != NULL ) {
+                               CC_MD5_CTX md5State;
+                               CC_MD5_Init(&md5State);
+                               ::lseek(fFileDescriptor, 0, SEEK_SET);
+                               ssize_t len;
+                               while ( (len = ::read(fFileDescriptor, md5Buffer, kMD5BufferSize)) > 0 ) 
+                                       CC_MD5_Update(&md5State, md5Buffer, len);
+                               CC_MD5_Final(digest, &md5State);
+                               ::free(md5Buffer);
+                       }
+                       else {
+                               // if malloc fails, fall back to random uuid
+                               ::uuid_generate_random(digest);
+                       }
+                       fUUIDAtom->setContent(digest);
+                       uint32_t uuidOffset = ((SectionInfo*)fUUIDAtom->getSection())->fFileOffset + fUUIDAtom->getSectionOffset();
+                       fUUIDAtom->copyRawContent(atomBuffer);
+                       ::pwrite(fFileDescriptor, atomBuffer, fUUIDAtom->getSize(), uuidOffset);
+               }
+               else {
+                       // if output file fit in memory, just genrate an md5 hash in memory
+                       CC_MD5(wholeBuffer, size, digest);
+                       fUUIDAtom->setContent(digest);
+                       uint32_t uuidOffset = ((SectionInfo*)fUUIDAtom->getSection())->fFileOffset + fUUIDAtom->getSectionOffset();
+                       fUUIDAtom->copyRawContent(&wholeBuffer[uuidOffset]);
+               }
+       }
+       
+       // finish up
+       if ( streaming ) {
+               delete [] atomBuffer;
+       }
+       else {
+               // write whole output file in one chunk
+               ::pwrite(fFileDescriptor, wholeBuffer, size, 0);
+               delete [] wholeBuffer;
+       }
+       
        close(fFileDescriptor);
        return end;
 }
@@ -2656,9 +3875,12 @@ template <>
 void Writer<x86>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 {
        uint32_t* fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
-       const int64_t bl_twoGigLimit = 0x7FFFFFFF;
+       uint8_t*  dtraceProbeSite;
+       const int64_t kTwoGigLimit = 0x7FFFFFFF;
+       const int64_t kSixtyFourKiloLimit = 0x7FFF;
        int64_t displacement;
-       switch ( (x86::ReferenceKinds)(ref->getKind()) ) {
+       x86::ReferenceKinds kind = (x86::ReferenceKinds)(ref->getKind());
+       switch ( kind ) {
                case x86::kNoFixUp:
                case x86::kFollowOn:
                        // do nothing
@@ -2667,8 +3889,27 @@ void Writer<x86>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const Ob
                case x86::kPointer:
                        {
                                if ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal ) {
-                                       // external realocation ==> pointer contains addend
-                                       LittleEndian::set32(*fixUp, ref->getTargetOffset());
+                                       if ( fOptions.prebind() ) {
+                                               switch (ref->getTarget().getDefinitionKind()) {
+                                                       case ObjectFile::Atom::kExternalDefinition:
+                                                       case ObjectFile::Atom::kExternalWeakDefinition:
+                                                               // prebound external relocation ==> pointer contains addend
+                                                               LittleEndian::set32(*fixUp, ref->getTargetOffset());
+                                                               break;
+                                                       case ObjectFile::Atom::kTentativeDefinition:
+                                                       case ObjectFile::Atom::kRegularDefinition:
+                                                       case ObjectFile::Atom::kWeakDefinition:
+                                                               // prebound external relocation to internal atom ==> pointer contains target address + addend
+                                                               LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
+                                                               break;
+                                                       case ObjectFile::Atom::kAbsoluteSymbol:
+                                                               break;
+                                               }
+                                       } 
+                                       else {
+                                               // external realocation ==> pointer contains addend
+                                               LittleEndian::set32(*fixUp, ref->getTargetOffset());
+                                       }
                                }
                                else {
                                        // pointer contains target address
@@ -2678,11 +3919,36 @@ void Writer<x86>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const Ob
                        }
                        break;
                case x86::kPointerDiff:
-                               LittleEndian::set32(*fixUp,
-                                       (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
+                       displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
+                       LittleEndian::set32(*fixUp, (uint32_t)displacement);
+                       break;
+               case x86::kPointerDiff16:
+                       displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
+                       if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) 
+                               throwf("16-bit pointer diff out of range in %s", inAtom->getDisplayName());
+                       LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
+                       break;
+               case x86::kDtraceProbeSite:
+                       // change call site to a NOP
+                       dtraceProbeSite = (uint8_t*)fixUp;
+                       dtraceProbeSite[-1] = 0x90;     // 1-byte nop
+                       dtraceProbeSite[0] = 0x0F;      // 4-byte nop 
+                       dtraceProbeSite[1] = 0x1F;
+                       dtraceProbeSite[2] = 0x40;
+                       dtraceProbeSite[3] = 0x00;
+                       break;
+               case x86::kDtraceIsEnabledSite:
+                       // change call site to a clear eax
+                       dtraceProbeSite = (uint8_t*)fixUp;
+                       dtraceProbeSite[-1] = 0x33;             // xorl eax,eax
+                       dtraceProbeSite[0] = 0xC0;
+                       dtraceProbeSite[1] = 0x90;              // 1-byte nop
+                       dtraceProbeSite[2] = 0x90;              // 1-byte nop
+                       dtraceProbeSite[3] = 0x90;              // 1-byte nop
                        break;
                case x86::kPCRel32WeakImport:
                case x86::kPCRel32:
+               case x86::kPCRel16:
                        displacement = 0;
                        switch ( ref->getTarget().getDefinitionKind() ) {
                                case ObjectFile::Atom::kRegularDefinition:
@@ -2695,12 +3961,24 @@ void Writer<x86>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const Ob
                                case ObjectFile::Atom::kTentativeDefinition:
                                        displacement = 0;
                                        break;
+                               case ObjectFile::Atom::kAbsoluteSymbol:
+                                       displacement = (ref->getTarget().getSectionOffset() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
+                                       break;
                        }
-                       if ( (displacement > bl_twoGigLimit) || (displacement < (-bl_twoGigLimit)) ) {
-                               //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
-                               throw "rel32 out of range";
+                       if ( kind == x86::kPCRel16 ) {
+                               if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) {
+                                       //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
+                                       throwf("rel16 out of range in %s", inAtom->getDisplayName());
+                               }
+                               LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
+                       }
+                       else {
+                               if ( (displacement > kTwoGigLimit) || (displacement < (-kTwoGigLimit)) ) {
+                                       //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
+                                       throwf("rel32 out of range in %s", inAtom->getDisplayName());
+                               }
+                               LittleEndian::set32(*fixUp, (int32_t)displacement);
                        }
-                       LittleEndian::set32(*fixUp, (int32_t)displacement);
                        break;
                case x86::kAbsolute32:
                        switch ( ref->getTarget().getDefinitionKind() ) {
@@ -2715,18 +3993,31 @@ void Writer<x86>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const Ob
                                        // external realocation ==> pointer contains addend
                                        LittleEndian::set32(*fixUp, ref->getTargetOffset());
                                        break;
+                               case ObjectFile::Atom::kAbsoluteSymbol:
+                                       // pointer contains target address
+                                       LittleEndian::set32(*fixUp, ref->getTarget().getSectionOffset() + ref->getTargetOffset());
+                                       break;
                        }
                        break;
+               case x86::kDtraceTypeReference:
+               case x86::kDtraceProbe:
+                       // nothing to fix up
+                       break;
        }
 }
 
+
+
 template <>
 void Writer<x86>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 {
+       const int64_t kTwoGigLimit = 0x7FFFFFFF;
+       const int64_t kSixtyFourKiloLimit = 0x7FFF;
        uint32_t* fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
-       bool isExternal = ( (ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kRegularDefinition)
-                                               && shouldExport(ref->getTarget()) );
-       switch ( (x86::ReferenceKinds)(ref->getKind()) ) {
+       bool isExtern = this->makesExternalRelocatableReference(ref->getTarget());      
+       int64_t displacement;
+       x86::ReferenceKinds kind = (x86::ReferenceKinds)(ref->getKind());
+       switch ( kind ) {
                case x86::kNoFixUp:
                case x86::kFollowOn:
                        // do nothing
@@ -2735,40 +4026,68 @@ void Writer<x86>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, co
                case x86::kPointerWeakImport:
                case x86::kAbsolute32:
                        {
-                               if ( isExternal ) {
+                               if ( isExtern ) {
                                        // external realocation ==> pointer contains addend
                                        LittleEndian::set32(*fixUp, ref->getTargetOffset());
                                }
-                               else {
-                                       // internal relocation
-                                       if ( ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition ) {
-                                               // pointer contains target address
+                               else if ( ((SectionInfo*)inAtom->getSection())->fAllNonLazyPointers ) {
+                                       // if INDIRECT_SYMBOL_LOCAL the content is pointer, else it is zero
+                                       if ( this->indirectSymbolIsLocal(ref) ) 
                                                LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
-                                       }
-                                       else {
-                                               // pointer contains addend
-                                               LittleEndian::set32(*fixUp, ref->getTargetOffset());
-                                       }
+                                       else
+                                               LittleEndian::set32(*fixUp, 0);
+                               } 
+                               else if ( ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition ) {
+                                       // internal relocation => pointer contains target address
+                                       LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
+                               }
+                               else {
+                                       // internal relocation to tentative ==> pointer contains addend
+                                       LittleEndian::set32(*fixUp, ref->getTargetOffset());
                                }
                        }
                        break;
                case x86::kPointerDiff:
-                               LittleEndian::set32(*fixUp,
-                                       (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
+                               displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
+                               LittleEndian::set32(*fixUp, (uint32_t)displacement);
+                       break;
+               case x86::kPointerDiff16:
+                               displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
+                               if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) 
+                                       throwf("16-bit pointer diff out of range in %s", inAtom->getDisplayName());
+                               LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
                        break;
+               case x86::kPCRel16:
                case x86::kPCRel32:
                case x86::kPCRel32WeakImport:
-                       int64_t displacement = 0;
-                       if ( isExternal )
-                               displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
-                       else
-                               displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
-                       const int64_t bl_twoGigLimit = 0x7FFFFFFF;
-                       if ( (displacement > bl_twoGigLimit) || (displacement < (-bl_twoGigLimit)) ) {
-                               //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
-                               throw "rel32 out of range";
+               case x86::kDtraceProbeSite:
+               case x86::kDtraceIsEnabledSite:
+                       {
+                               if ( isExtern )
+                                       displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
+                               else
+                                       displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
+                               if ( kind == x86::kPCRel16 ) {
+                                       displacement += 2;
+                                       if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) {
+                                               //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
+                                               throwf("rel16 out of range in %s", inAtom->getDisplayName());
+                                       }
+                                       int16_t word = (int16_t)displacement;
+                                       LittleEndian::set16(*((uint16_t*)fixUp), word);
+                               }
+                               else {
+                                       if ( (displacement > kTwoGigLimit) || (displacement < (-kTwoGigLimit)) ) {
+                                               //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
+                                               throwf("rel32 out of range in %s", inAtom->getDisplayName());
+                                       }
+                                       LittleEndian::set32(*fixUp, (int32_t)displacement);
+                               }
                        }
-                       LittleEndian::set32(*fixUp, (int32_t)displacement);
+                       break;
+               case x86::kDtraceProbe:
+               case x86::kDtraceTypeReference:
+                       // nothing to fix up
                        break;
        }
 }
@@ -2778,6 +4097,7 @@ void Writer<x86_64>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const
 {
        const int64_t twoGigLimit                 = 0x7FFFFFFF;
        uint64_t* fixUp = (uint64_t*)&buffer[ref->getFixUpOffset()];
+       uint8_t*  dtraceProbeSite;
        int64_t displacement = 0;
        switch ( (x86_64::ReferenceKinds)(ref->getKind()) ) {
                case x86_64::kNoFixUp:
@@ -2810,6 +4130,17 @@ void Writer<x86_64>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const
                                LittleEndian::set64(*fixUp,
                                        (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
                                break;
+               case x86_64::kPCRel32GOTLoad:
+               case x86_64::kPCRel32GOTLoadWeakImport:
+                       // if GOT entry was optimized away, change movq instruction to a leaq
+                       if ( std::find(fAllSynthesizedNonLazyPointers.begin(), fAllSynthesizedNonLazyPointers.end(), &(ref->getTarget())) == fAllSynthesizedNonLazyPointers.end() ) {
+                               //fprintf(stderr, "GOT for %s optimized away\n", ref->getTarget().getDisplayName());
+                               uint8_t* opcodes = (uint8_t*)fixUp;
+                               if ( opcodes[-2] != 0x8B )
+                                       throw "GOT load reloc does not point to a movq instruction";
+                               opcodes[-2] = 0x8D;
+                       }
+                       // fall into general rel32 case
                case x86_64::kBranchPCRel32WeakImport:
                case x86_64::kBranchPCRel32:
                case x86_64::kPCRel32:
@@ -2818,14 +4149,15 @@ void Writer<x86_64>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const
                case x86_64::kPCRel32_4:
                case x86_64::kPCRel32GOT:
                case x86_64::kPCRel32GOTWeakImport:
-               case x86_64::kPCRel32GOTLoad:
-               case x86_64::kPCRel32GOTLoadWeakImport:
                        switch ( ref->getTarget().getDefinitionKind() ) {
                                case ObjectFile::Atom::kRegularDefinition:
                                case ObjectFile::Atom::kWeakDefinition:
                                case ObjectFile::Atom::kTentativeDefinition:
                                        displacement = (ref->getTarget().getAddress() + (int32_t)ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
                                        break;
+                               case ObjectFile::Atom::kAbsoluteSymbol:
+                                       displacement = (ref->getTarget().getSectionOffset() + (int32_t)ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
+                                       break;
                                case ObjectFile::Atom::kExternalDefinition:
                                case ObjectFile::Atom::kExternalWeakDefinition:
                                        throw "codegen problem, can't use rel32 to external symbol";
@@ -2843,11 +4175,34 @@ void Writer<x86_64>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const
                                        break;
                        }
                        if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
-                               //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
+                               fprintf(stderr, "call out of range from %s (%llX) in %s to %s (%llX) in %s\n", 
+                                       inAtom->getDisplayName(), inAtom->getAddress(), inAtom->getFile()->getPath(), ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), ref->getTarget().getFile()->getPath());
                                throw "rel32 out of range";
                        }
                        LittleEndian::set32(*((uint32_t*)fixUp), (int32_t)displacement);
                        break;
+               case x86_64::kDtraceProbeSite:
+                       // change call site to a NOP
+                       dtraceProbeSite = (uint8_t*)fixUp;
+                       dtraceProbeSite[-1] = 0x90;     // 1-byte nop
+                       dtraceProbeSite[0] = 0x0F;      // 4-byte nop 
+                       dtraceProbeSite[1] = 0x1F;
+                       dtraceProbeSite[2] = 0x40;
+                       dtraceProbeSite[3] = 0x00;
+                       break;
+               case x86_64::kDtraceIsEnabledSite:
+                       // change call site to a clear eax
+                       dtraceProbeSite = (uint8_t*)fixUp;
+                       dtraceProbeSite[-1] = 0x48;             // xorq eax,eax
+                       dtraceProbeSite[0] = 0x33;
+                       dtraceProbeSite[1] = 0xC0;              
+                       dtraceProbeSite[2] = 0x90;              // 1-byte nop
+                       dtraceProbeSite[3] = 0x90;              // 1-byte nop
+                       break;
+               case x86_64::kDtraceTypeReference:
+               case x86_64::kDtraceProbe:
+                       // nothing to fix up
+                       break;
        }
 }
 
@@ -2855,7 +4210,7 @@ template <>
 void Writer<x86_64>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 {
        const int64_t twoGigLimit                 = 0x7FFFFFFF;
-       bool external = (ref->getTarget().getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn);
+       bool external = this->makesExternalRelocatableReference(ref->getTarget());
        uint64_t* fixUp = (uint64_t*)&buffer[ref->getFixUpOffset()];
        int64_t displacement = 0;
        int32_t temp32;
@@ -2887,6 +4242,8 @@ void Writer<x86_64>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref,
                        break;
                case x86_64::kBranchPCRel32:
                case x86_64::kBranchPCRel32WeakImport:
+               case x86_64::kDtraceProbeSite:
+               case x86_64::kDtraceIsEnabledSite:
                case x86_64::kPCRel32:
                case x86_64::kPCRel32_1:
                case x86_64::kPCRel32_2:
@@ -2925,6 +4282,10 @@ void Writer<x86_64>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref,
                        // contains addend (usually zero)
                        LittleEndian::set32(*((uint32_t*)fixUp), (uint32_t)(ref->getTargetOffset()));
                        break;
+               case x86_64::kDtraceTypeReference:
+               case x86_64::kDtraceProbe:
+                       // nothing to fix up
+                       break;
        }
 }
 
@@ -2961,22 +4322,23 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
        uint32_t        instruction;
        uint32_t        newInstruction;
        int64_t         displacement;
-       uint64_t        targetAddr = ref->getTarget().getAddress() + ref->getTargetOffset();
+       uint64_t        targetAddr = 0;
        uint64_t        picBaseAddr;
        uint16_t        instructionLowHalf;
        uint16_t        instructionHighHalf;
        uint32_t*       fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
        pint_t*         fixUpPointer = (pint_t*)&buffer[ref->getFixUpOffset()];
-       bool            relocateableExternal;
-
-       if ( finalLinkedImage )
-               relocateableExternal = (relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal);
-       else
-               relocateableExternal = ( (ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kRegularDefinition)
-                                                                       && shouldExport(ref->getTarget()) );
-
+       bool            relocateableExternal = false;
        const int64_t picbase_twoGigLimit = 0x80000000;
 
+       if ( ref->getTargetBinding() != ObjectFile::Reference::kDontBind ) {
+               targetAddr = ref->getTarget().getAddress() + ref->getTargetOffset();
+               if ( finalLinkedImage )
+                       relocateableExternal = (relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal);
+               else
+                       relocateableExternal = this->makesExternalRelocatableReference(ref->getTarget());       
+       }
+
        switch ( (typename A::ReferenceKinds)(ref->getKind()) ) {
                case A::kNoFixUp:
                case A::kFollowOn:
@@ -2987,27 +4349,65 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                        {
                                //fprintf(stderr, "fixUpReferenceFinal: %s reference to %s\n", this->getDisplayName(), target.getDisplayName());
                                if ( finalLinkedImage && ((SectionInfo*)inAtom->getSection())->fAllLazyPointers ) {
-                                       // lazy-symbol ==> pointer contains address of dyld_stub_binding_helper (stored in "from" target)
-                                       if ( fDyldHelper == NULL )
-                                               throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
-                                       P::setP(*fixUpPointer, fDyldHelper->getAddress());
+                                       if ( fOptions.prebind() ) {
+                                               switch (ref->getTarget().getDefinitionKind()) {
+                                                       case ObjectFile::Atom::kExternalDefinition:
+                                                       case ObjectFile::Atom::kExternalWeakDefinition:
+                                                               // prebound lazy pointer to another dylib ==> pointer contains zero
+                                                               P::setP(*fixUpPointer, 0);
+                                                               break;
+                                                       case ObjectFile::Atom::kTentativeDefinition:
+                                                       case ObjectFile::Atom::kRegularDefinition:
+                                                       case ObjectFile::Atom::kWeakDefinition:
+                                                               // prebound lazy pointer to withing this dylib ==> pointer contains address
+                                                               P::setP(*fixUpPointer, targetAddr);
+                                                               break;
+                                                       case ObjectFile::Atom::kAbsoluteSymbol:
+                                                               break;
+                                               }
+                                       }
+                                       else {
+                                               // lazy-symbol ==> pointer contains address of dyld_stub_binding_helper (stored in "from" target)
+                                               if ( fDyldHelper == NULL )
+                                                       throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
+                                               P::setP(*fixUpPointer, fDyldHelper->getAddress());
+                                       }
                                }
                                else if ( !finalLinkedImage && ((SectionInfo*)inAtom->getSection())->fAllNonLazyPointers ) {
-                                       // indirect symbol table has INDIRECT_SYMBOL_LOCAL, so we must put address in content
-                                       if  ( ref->getTarget().getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn )
+                                       // if INDIRECT_SYMBOL_LOCAL the content is pointer, else it is zero
+                                       if ( this->indirectSymbolIsLocal(ref) ) 
                                                P::setP(*fixUpPointer, targetAddr);
                                        else
                                                P::setP(*fixUpPointer, 0);
                                }
                                else if ( relocateableExternal ) {
-                                       // external realocation ==> pointer contains addend
-                                       P::setP(*fixUpPointer, ref->getTargetOffset());
+                                       if ( fOptions.prebind() ) {
+                                               switch (ref->getTarget().getDefinitionKind()) {
+                                                       case ObjectFile::Atom::kExternalDefinition:
+                                                       case ObjectFile::Atom::kExternalWeakDefinition:
+                                                               // prebound external relocation ==> pointer contains addend
+                                                               P::setP(*fixUpPointer, ref->getTargetOffset());
+                                                               break;
+                                                       case ObjectFile::Atom::kTentativeDefinition:
+                                                       case ObjectFile::Atom::kRegularDefinition:
+                                                       case ObjectFile::Atom::kWeakDefinition:
+                                                               // prebound external relocation to internal atom ==> pointer contains target address + addend
+                                                               P::setP(*fixUpPointer, targetAddr);
+                                                               break;
+                                                       case ObjectFile::Atom::kAbsoluteSymbol:
+                                                               break;
+                                               }
+                                       } 
+                                       else {
+                                               // external realocation ==> pointer contains addend
+                                               P::setP(*fixUpPointer, ref->getTargetOffset());
+                                       }
                                }
                                else {
                                        // internal relocation
                                        if ( finalLinkedImage || (ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition)  ) {
                                                // pointer contains target address
-                                               //printf("Atom::fixUpReference_powerpc() target.name=%s, target.address=0x%08llX\n", target.getDisplayName(), target.getAddress());
+                                               //printf("Atom::fixUpReference_powerpc() target.name=%s, target.address=0x%08llX\n",  ref->getTarget().getDisplayName(), targetAddr);
                                                P::setP(*fixUpPointer, targetAddr);
                                        }
                                        else {
@@ -3023,6 +4423,35 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                case A::kPointerDiff32:
                        P::E::set32(*fixUp, targetAddr - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
                        break;
+               case A::kPointerDiff16:
+                       P::E::set16(*((uint16_t*)fixUp), targetAddr - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
+                       break;
+               case A::kDtraceProbeSite:
+                       if ( finalLinkedImage ) {
+                               // change call site to a NOP
+                               BigEndian::set32(*fixUp, 0x60000000);
+                       }
+                       else {
+                               // set  bl instuction to branch to address zero in .o file
+                               int64_t displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset());
+                               instruction = BigEndian::get32(*fixUp);
+                               newInstruction = (instruction & 0xFC000003) | ((uint32_t)displacement & 0x03FFFFFC);
+                               BigEndian::set32(*fixUp, newInstruction);
+                       }
+                       break;
+               case A::kDtraceIsEnabledSite:
+                       if ( finalLinkedImage ) {
+                               // change call site to a li r3,0
+                               BigEndian::set32(*fixUp, 0x38600000);
+                       }
+                       else { 
+                               // set  bl instuction to branch to address zero in .o file
+                               int64_t displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset());
+                               instruction = BigEndian::get32(*fixUp);
+                               newInstruction = (instruction & 0xFC000003) | ((uint32_t)displacement & 0x03FFFFFC);
+                               BigEndian::set32(*fixUp, newInstruction);
+                       }
+                       break;
                case A::kBranch24WeakImport:
                case A::kBranch24:
                        {
@@ -3037,9 +4466,9 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                                        const int64_t bl_eightMegLimit = 0x00FFFFFF;
                                        if ( (displacement > bl_eightMegLimit) || (displacement < (-bl_eightMegLimit)) ) {
                                                //fprintf(stderr, "bl out of range (%lld max is +/-16M) from %s in %s to %s in %s\n", displacement, this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
-                                               throwf("bl out of range (%lld max is +/-16M) from %s in %s to %s in %s",
-                                                       displacement, inAtom->getDisplayName(), inAtom->getFile()->getPath(),
-                                                       ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
+                                               throwf("bl out of range (%lld max is +/-16M) from %s at 0x%08llX in %s of %s to %s at 0x%08llX in %s of  %s",
+                                                       displacement, inAtom->getDisplayName(), inAtom->getAddress(), inAtom->getSectionName(), inAtom->getFile()->getPath(),
+                                                       ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), ref->getTarget().getSectionName(), ref->getTarget().getFile()->getPath());
                                        }
                                }
                                instruction = BigEndian::get32(*fixUp);
@@ -3074,7 +4503,7 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                        }
                        break;
                case A::kPICBaseLow16:
-                       picBaseAddr = inAtom->getAddress() + ref->getFromTargetOffset();
+                       picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
                        displacement = targetAddr - picBaseAddr;
                        if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
                                throw "32-bit pic-base out of range";
@@ -3084,7 +4513,7 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                        BigEndian::set32(*fixUp, newInstruction);
                        break;
                case A::kPICBaseLow14:
-                       picBaseAddr = inAtom->getAddress() + ref->getFromTargetOffset();
+                       picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
                        displacement = targetAddr - picBaseAddr;
                        if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
                                throw "32-bit pic-base out of range";
@@ -3096,7 +4525,7 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                        BigEndian::set32(*fixUp, newInstruction);
                        break;
                case A::kPICBaseHigh16:
-                       picBaseAddr = inAtom->getAddress() + ref->getFromTargetOffset();
+                       picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
                        displacement = targetAddr - picBaseAddr;
                        if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
                                throw "32-bit pic-base out of range";
@@ -3108,7 +4537,7 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                        BigEndian::set32(*fixUp, newInstruction);
                        break;
                case A::kAbsLow16:
-                       if ( relocateableExternal )
+                       if ( relocateableExternal && !finalLinkedImage )
                                targetAddr -= ref->getTarget().getAddress();
                        instructionLowHalf = (targetAddr & 0xFFFF);
                        instruction = BigEndian::get32(*fixUp);
@@ -3116,7 +4545,7 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                        BigEndian::set32(*fixUp, newInstruction);
                        break;
                case A::kAbsLow14:
-                       if ( relocateableExternal )
+                       if ( relocateableExternal && !finalLinkedImage )
                                targetAddr -= ref->getTarget().getAddress();
                        if ( (targetAddr & 0x3) != 0 )
                                throw "bad address for absolute lo14 instruction fix-up";
@@ -3126,49 +4555,164 @@ void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const O
                        BigEndian::set32(*fixUp, newInstruction);
                        break;
                case A::kAbsHigh16:
-                       if ( relocateableExternal )
-                               targetAddr -= ref->getTarget().getAddress();
+                       if ( relocateableExternal ) {
+                               if ( finalLinkedImage ) {
+                                       switch (ref->getTarget().getDefinitionKind()) {
+                                               case ObjectFile::Atom::kExternalDefinition:
+                                               case ObjectFile::Atom::kExternalWeakDefinition:
+                                                       throwf("absolute address to symbol %s in a different linkage unit not supported", ref->getTargetName());
+                                                       break;
+                                               case ObjectFile::Atom::kTentativeDefinition:
+                                               case ObjectFile::Atom::kRegularDefinition:
+                                               case ObjectFile::Atom::kWeakDefinition:
+                                                       // use target address
+                                                       break;
+                                               case ObjectFile::Atom::kAbsoluteSymbol:
+                                                       targetAddr = ref->getTarget().getSectionOffset();
+                                                       break;
+                                       }
+                               }
+                               else {
+                                       targetAddr -= ref->getTarget().getAddress();
+                               }
+                       }
                        instructionHighHalf = (targetAddr >> 16);
                        instruction = BigEndian::get32(*fixUp);
                        newInstruction = (instruction & 0xFFFF0000) | instructionHighHalf;
                        BigEndian::set32(*fixUp, newInstruction);
                        break;
                case A::kAbsHigh16AddLow:
-                       if ( relocateableExternal )
-                               targetAddr -= ref->getTarget().getAddress();
+                       if ( relocateableExternal ) {
+                               if ( finalLinkedImage ) {
+                                       switch (ref->getTarget().getDefinitionKind()) {
+                                               case ObjectFile::Atom::kExternalDefinition:
+                                               case ObjectFile::Atom::kExternalWeakDefinition:
+                                                       throwf("absolute address to symbol %s in a different linkage unit not supported", ref->getTargetName());
+                                                       break;
+                                               case ObjectFile::Atom::kTentativeDefinition:
+                                               case ObjectFile::Atom::kRegularDefinition:
+                                               case ObjectFile::Atom::kWeakDefinition:
+                                                       // use target address
+                                                       break;
+                                               case ObjectFile::Atom::kAbsoluteSymbol:
+                                                       targetAddr = ref->getTarget().getSectionOffset();
+                                                       break;
+                                       }
+                               }
+                               else {
+                                       targetAddr -= ref->getTarget().getAddress();
+                               }
+                       }
                        if ( targetAddr & 0x00008000 )
                                targetAddr += 0x00010000;
                        instruction = BigEndian::get32(*fixUp);
                        newInstruction = (instruction & 0xFFFF0000) | (targetAddr >> 16);
                        BigEndian::set32(*fixUp, newInstruction);
                        break;
+               case A::kDtraceTypeReference:
+               case A::kDtraceProbe:
+                       // nothing to fix up
+                       break;
        }
 }
 
 template <>
-bool Writer<ppc>::stubableReferenceKind(uint8_t kind)
-{
-       return (kind == ppc::kBranch24 || kind == ppc::kBranch24WeakImport);
+bool Writer<ppc>::stubableReference(const ObjectFile::Reference* ref)
+{
+       uint8_t kind = ref->getKind();
+       switch ( (ppc::ReferenceKinds)kind ) {
+               case ppc::kNoFixUp:
+               case ppc::kFollowOn:
+               case ppc::kPointer:
+               case ppc::kPointerWeakImport:
+               case ppc::kPointerDiff16:
+               case ppc::kPointerDiff32:
+               case ppc::kPointerDiff64:
+               case ppc::kDtraceProbe:
+               case ppc::kDtraceProbeSite:
+               case ppc::kDtraceIsEnabledSite:
+               case ppc::kDtraceTypeReference:
+                       // these are never used to call external functions
+                       return false;
+               case ppc::kBranch24: 
+               case ppc::kBranch24WeakImport: 
+               case ppc::kBranch14: 
+                       // these are used to call external functions
+                       return true;
+               case ppc::kPICBaseLow16:
+               case ppc::kPICBaseLow14:
+               case ppc::kPICBaseHigh16:
+               case ppc::kAbsLow16:
+               case ppc::kAbsLow14:
+               case ppc::kAbsHigh16:
+               case ppc::kAbsHigh16AddLow:
+                       // these are only used to call external functions
+                       // in -mlong-branch stubs
+                       switch ( ref->getTarget().getDefinitionKind() ) {
+                               case ObjectFile::Atom::kExternalDefinition:
+                               case ObjectFile::Atom::kExternalWeakDefinition:
+                                       return true;
+                               case ObjectFile::Atom::kTentativeDefinition:
+                               case ObjectFile::Atom::kRegularDefinition:
+                               case ObjectFile::Atom::kWeakDefinition:
+                               case ObjectFile::Atom::kAbsoluteSymbol:
+                                       return false;
+                       }
+                       break;
+       }
+       return false;
 }
 
+
 template <>
-bool Writer<ppc64>::stubableReferenceKind(uint8_t kind)
-{
-       return (kind == ppc64::kBranch24 || kind == ppc64::kBranch24WeakImport);
+bool Writer<ppc64>::stubableReference(const ObjectFile::Reference* ref)
+{
+       uint8_t kind = ref->getKind();
+       switch ( (ppc64::ReferenceKinds)kind ) {
+               case ppc::kNoFixUp:
+               case ppc::kFollowOn:
+               case ppc::kPointer:
+               case ppc::kPointerWeakImport:
+               case ppc::kPointerDiff16:
+               case ppc::kPointerDiff32:
+               case ppc::kPointerDiff64:
+               case ppc::kPICBaseLow16:
+               case ppc::kPICBaseLow14:
+               case ppc::kPICBaseHigh16:
+               case ppc::kAbsLow16:
+               case ppc::kAbsLow14:
+               case ppc::kAbsHigh16:
+               case ppc::kAbsHigh16AddLow:
+               case ppc::kDtraceProbe:
+               case ppc::kDtraceProbeSite:
+               case ppc::kDtraceIsEnabledSite:
+               case ppc::kDtraceTypeReference:
+                       // these are never used to call external functions
+                       return false;
+               case ppc::kBranch24: 
+               case ppc::kBranch24WeakImport: 
+               case ppc::kBranch14: 
+                       // these are used to call external functions
+                       return true;
+       }
+       return false;
 }
 
 template <>
-bool Writer<x86>::stubableReferenceKind(uint8_t kind)
+bool Writer<x86>::stubableReference(const ObjectFile::Reference* ref)
 {
+       uint8_t kind = ref->getKind();
        return (kind == x86::kPCRel32 || kind == x86::kPCRel32WeakImport);
 }
 
 template <>
-bool Writer<x86_64>::stubableReferenceKind(uint8_t kind)
+bool Writer<x86_64>::stubableReference(const ObjectFile::Reference* ref)
 {
+       uint8_t kind = ref->getKind();
        return (kind == x86_64::kBranchPCRel32 || kind == x86_64::kBranchPCRel32WeakImport);
 }
 
+
 template <>
 bool Writer<ppc>::weakImportReferenceKind(uint8_t kind)
 {
@@ -3233,13 +4777,145 @@ bool Writer<x86_64>::GOTReferenceKind(uint8_t kind)
        return false;
 }
 
+template <>
+bool Writer<ppc>::optimizableGOTReferenceKind(uint8_t kind)
+{
+       return false;
+}
+
+template <>
+bool Writer<ppc64>::optimizableGOTReferenceKind(uint8_t kind)
+{
+       return false;
+}
+
+template <>
+bool Writer<x86>::optimizableGOTReferenceKind(uint8_t kind)
+{
+       return false;
+}
+
+template <>
+bool Writer<x86_64>::optimizableGOTReferenceKind(uint8_t kind)
+{
+       switch ( kind ) {
+               case x86_64::kPCRel32GOTLoad:
+               case x86_64::kPCRel32GOTLoadWeakImport:
+                       return true;
+       }
+       return false;
+}
+
+
+
+// 64-bit architectures never need module table, 32-bit sometimes do for backwards compatiblity
+template <typename A> bool Writer<A>::needsModuleTable() {return fOptions.needsModuleTable(); }
+template <> bool Writer<ppc64>::needsModuleTable() { return false; }
+template <> bool Writer<x86_64>::needsModuleTable() { return false; }
+
 
 template <typename A>
-void Writer<A>::scanForAbsoluteReferences()
+void Writer<A>::optimizeDylibReferences()
+{
+       //fprintf(stderr, "original ordinals table:\n");
+       //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
+       //      fprintf(stderr, "%u <== %p/%s\n", it->second, it->first, it->first->getPath());
+       //}
+       // find unused dylibs that can be removed
+       std::map<uint32_t, ObjectFile::Reader*> ordinalToReader;
+       std::map<ObjectFile::Reader*, ObjectFile::Reader*> readerAliases;
+       for (std::map<ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {   
+               ObjectFile::Reader* reader = it->first;
+               std::map<ObjectFile::Reader*, ObjectFile::Reader*>::iterator aliasPos = fLibraryAliases.find(reader);
+               if ( aliasPos != fLibraryAliases.end() ) {
+                       // already noticed that this reader has same install name as another reader
+                       readerAliases[reader] = aliasPos->second;
+               }
+               else if ( !reader->providedExportAtom() && (reader->implicitlyLinked() || fOptions.deadStripDylibs()) ) {
+                       // this reader can be optimized away
+                       it->second = 0xFFFFFFFF;
+                       typename std::map<class ObjectFile::Reader*, class DylibLoadCommandsAtom<A>* >::iterator pos = fLibraryToLoadCommand.find(reader);
+                       if ( pos != fLibraryToLoadCommand.end() ) 
+                               pos->second->optimizeAway();
+               }
+               else {
+                       // mark this reader as using it ordinal
+                       std::map<uint32_t, ObjectFile::Reader*>::iterator pos = ordinalToReader.find(it->second);
+                       if ( pos == ordinalToReader.end() ) 
+                               ordinalToReader[it->second] = reader;
+                       else
+                               readerAliases[reader] = pos->second;
+               }
+       }
+       // renumber ordinals (depends on iterator walking in ordinal order)
+       uint32_t newOrdinal = 0;
+       for (std::map<uint32_t, ObjectFile::Reader*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
+               if ( it->first <= fLibraryToOrdinal.size() )
+                       fLibraryToOrdinal[it->second] = ++newOrdinal;
+       }
+
+       // add aliases (e.g. -lm points to libSystem.dylib)
+       for (std::map<ObjectFile::Reader*, ObjectFile::Reader*>::iterator it = readerAliases.begin(); it != readerAliases.end(); ++it) {
+               fLibraryToOrdinal[it->first] = fLibraryToOrdinal[it->second];
+       }
+
+       // fprintf(stderr, "new ordinals table:\n");
+       //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
+       //      fprintf(stderr, "%u <== %p/%s\n", it->second, it->first, it->first->getPath());
+       //}
+}
+
+
+template <>
+void Writer<x86_64>::scanForAbsoluteReferences()
+{
+       // x86_64 codegen never has absolute references
+}
+
+template <>
+void  Writer<x86>::scanForAbsoluteReferences()
+{
+       // when linking -pie verify there are no absolute addressing
+       if ( fOptions.positionIndependentExecutable() ) {
+               for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
+                       ObjectFile::Atom* atom = *it;
+                       std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
+                       for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                               ObjectFile::Reference* ref = *rit;
+                               switch (ref->getKind()) {
+                                       case x86::kAbsolute32:
+                                               throwf("cannot link -pie: -mdynamic-no-pic codegen found in %s from %s\n", atom->getDisplayName(), atom->getFile()->getPath());
+                                               return;
+                               }
+                       }
+               }
+       }
+}
+
+template <>
+void  Writer<ppc>::scanForAbsoluteReferences()
 {
-       // do nothing
+       // when linking -pie verify there are no absolute addressing
+       if ( fOptions.positionIndependentExecutable() ) {
+               for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
+                       ObjectFile::Atom* atom = *it;
+                       std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
+                       for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                               ObjectFile::Reference* ref = *rit;
+                               switch (ref->getKind()) {
+                                       case ppc::kAbsLow16:
+                                       case ppc::kAbsLow14:
+                                       case ppc::kAbsHigh16:
+                                       case ppc::kAbsHigh16AddLow:
+                                               throwf("cannot link -pie: -mdynamic-no-pic codegen found in %s from %s\n", atom->getDisplayName(), atom->getFile()->getPath());
+                                               return;
+                               }
+                       }
+               }
+       }
 }
 
+
 // for ppc64 look for any -mdynamic-no-pic codegen
 template <>
 void  Writer<ppc64>::scanForAbsoluteReferences()
@@ -3256,7 +4932,7 @@ void  Writer<ppc64>::scanForAbsoluteReferences()
                                        case ppc64::kAbsLow14:
                                        case ppc64::kAbsHigh16:
                                        case ppc64::kAbsHigh16AddLow:
-                                               //fprintf(stderr, "found -mdyanmic-no-pic codegen in %s in %s\n", atom->getDisplayName(), atom->getFile()->getPath());
+                                               //fprintf(stderr, "found -mdynamic-no-pic codegen in %s in %s\n", atom->getDisplayName(), atom->getFile()->getPath());
                                                // shrink page-zero and add pad segment to compensate
                                                fPadSegmentInfo = new SegmentInfo();
                                                strcpy(fPadSegmentInfo->fName, "__4GBFILL");
@@ -3269,14 +4945,41 @@ void  Writer<ppc64>::scanForAbsoluteReferences()
 }
 
 
+template <typename A>
+void Writer<A>::insertDummyStubs()
+{
+       // only needed for x86
+}
+
+template <>
+void Writer<x86>::insertDummyStubs()
+{
+       // any 5-byte stubs that cross a 32-byte cache line may update incorrectly
+       std::vector<class StubAtom<x86>*>        betterStubs;
+       for (std::vector<class StubAtom<x86>*>::iterator it=fAllSynthesizedStubs.begin(); it != fAllSynthesizedStubs.end(); it++) {
+               switch (betterStubs.size() % 64 ) {
+                       case 12:// stub would occupy 0x3C->0x41
+                       case 25:// stub would occupy 0x7D->0x82
+                       case 38:// stub would occupy 0xBE->0xC3
+                       case 51:// stub would occupy 0xFF->0x04
+                               betterStubs.push_back(new StubAtom<x86>(*this, *((ObjectFile::Atom*)NULL))); //pad with dummy stub
+                               break;
+               }
+               betterStubs.push_back(*it);
+       }
+       // replace 
+       fAllSynthesizedStubs.clear();
+       fAllSynthesizedStubs.insert(fAllSynthesizedStubs.begin(), betterStubs.begin(), betterStubs.end());
+}
+
 template <typename A>
 void Writer<A>::synthesizeStubs()
 {
        switch ( fOptions.outputKind() ) {
-               case Options::kStaticExecutable:
                case Options::kObjectFile:
                        // these output kinds never have stubs
                        return;
+               case Options::kStaticExecutable:
                case Options::kDyld:
                case Options::kDynamicLibrary:
                case Options::kDynamicBundle:
@@ -3291,68 +4994,98 @@ void Writer<A>::synthesizeStubs()
                std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
                for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
                        ObjectFile::Reference* ref = *rit;
-                       ObjectFile::Atom& target = ref->getTarget();
-                       // build map of which symbols need weak importing
-                       if ( (target.getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
-                               || (target.getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
-                               bool weakImport = this->weakImportReferenceKind(ref->getKind());
-                               std::map<const ObjectFile::Atom*,bool>::iterator pos = fWeakImportMap.find(&target);
-                               if ( pos == fWeakImportMap.end() ) {
-                                       // target not in fWeakImportMap, so add
-                                       fWeakImportMap[&target] = weakImport;
-                               }
-                               else {
-                                       // target in fWeakImportMap, check for weakness mismatch
-                                       if ( pos->second != weakImport ) {
-                                               // found mismatch
-                                               switch ( fOptions.weakReferenceMismatchTreatment() ) {
-                                                       case Options::kWeakReferenceMismatchError:
-                                                               throwf("mismatching weak references for symbol: %s", target.getName());
-                                                       case Options::kWeakReferenceMismatchWeak:
-                                                               pos->second = true;
-                                                               break;
-                                                       case Options::kWeakReferenceMismatchNonWeak:
-                                                               pos->second = false;
-                                                               break;
+                       switch ( ref->getTargetBinding()) {
+                               case ObjectFile::Reference::kUnboundByName:
+                               case ObjectFile::Reference::kDontBind:
+                                       break;
+                               case ObjectFile::Reference::kBoundByName:
+                               case ObjectFile::Reference::kBoundDirectly:
+                                       ObjectFile::Atom& target = ref->getTarget();
+                                       // build map of which symbols need weak importing
+                                       if ( (target.getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
+                                               || (target.getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
+                                               bool weakImport = this->weakImportReferenceKind(ref->getKind());
+                                               std::map<const ObjectFile::Atom*,bool>::iterator pos = fWeakImportMap.find(&target);
+                                               if ( pos == fWeakImportMap.end() ) {
+                                                       // target not in fWeakImportMap, so add
+                                                       fWeakImportMap[&target] = weakImport;
+                                               }
+                                               else {
+                                                       // target in fWeakImportMap, check for weakness mismatch
+                                                       if ( pos->second != weakImport ) {
+                                                               // found mismatch
+                                                               switch ( fOptions.weakReferenceMismatchTreatment() ) {
+                                                                       case Options::kWeakReferenceMismatchError:
+                                                                               throwf("mismatching weak references for symbol: %s", target.getName());
+                                                                       case Options::kWeakReferenceMismatchWeak:
+                                                                               pos->second = true;
+                                                                               break;
+                                                                       case Options::kWeakReferenceMismatchNonWeak:
+                                                                               pos->second = false;
+                                                                               break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       // create stubs as needed
+                                       if ( this->stubableReference(ref) 
+                                               && (ref->getTargetOffset() == 0)
+                                               && this->relocationNeededInFinalLinkedImage(target) == kRelocExternal ) {
+                                               ObjectFile::Atom* stub = NULL;
+                                               std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(&target);
+                                               if ( pos == fStubsMap.end() ) {
+                                                       stub = new StubAtom<A>(*this, target);
+                                                       fStubsMap[&target] = stub;
+                                               }
+                                               else {
+                                                       stub = pos->second;
+                                               }
+                                               // alter reference to use stub instead
+                                               ref->setTarget(*stub, 0);
+                                       }
+                                       // create GOT slots (non-lazy pointers) as needed
+                                       else if ( this->GOTReferenceKind(ref->getKind()) ) {
+                                               // 
+                                               bool mustUseGOT = ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal );
+                                               bool useGOT;
+                                               if ( fBiggerThanTwoGigs ) {
+                                                       // in big images use GOT for all zero fill atoms
+                                                       // this is just a heuristic and may need to be re-examined
+                                                       useGOT = mustUseGOT || ref->getTarget().isZeroFill();
+                                               }
+                                               else {
+                                                       // < 2GB image so remove all GOT entries that we can
+                                                       useGOT = mustUseGOT;
+                                               }
+                                               // if this GOT usage cannot be optimized away then make a GOT enry
+                                               if ( ! this->optimizableGOTReferenceKind(ref->getKind()) )
+                                                       useGOT = true;
+                                               if ( useGOT  ) {
+                                                       ObjectFile::Atom* nlp = NULL;
+                                                       std::map<ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fGOTMap.find(&target);
+                                                       if ( pos == fGOTMap.end() ) {
+                                                               nlp = new NonLazyPointerAtom<A>(*this, target);
+                                                               fGOTMap[&target] = nlp;
+                                                       }
+                                                       else {
+                                                               nlp = pos->second;
+                                                       }
+                                                       // alter reference to use non lazy pointer instead
+                                                       ref->setTarget(*nlp, ref->getTargetOffset());
                                                }
                                        }
-                               }
-                       }
-                       // create stubs as needed
-                       if ( this->stubableReferenceKind(ref->getKind())
-                               && this->relocationNeededInFinalLinkedImage(target) == kRelocExternal ) {
-                               ObjectFile::Atom* stub = NULL;
-                               std::map<ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(&target);
-                               if ( pos == fStubsMap.end() ) {
-                                       stub = new StubAtom<A>(*this, target);
-                                       fStubsMap[&target] = stub;
-                               }
-                               else {
-                                       stub = pos->second;
-                               }
-                               // alter reference to use stub instead
-                               ref->setTarget(*stub, 0);
-                       }
-                       // create GOT slots (non-lazy pointers) as needed
-                       else if ( this->GOTReferenceKind(ref->getKind()) ) {
-                               ObjectFile::Atom* nlp = NULL;
-                               std::map<ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fGOTMap.find(&target);
-                               if ( pos == fGOTMap.end() ) {
-                                       nlp = new NonLazyPointerAtom<A>(*this, target);
-                                       fGOTMap[&target] = nlp;
-                               }
-                               else {
-                                       nlp = pos->second;
-                               }
-                               // alter reference to use non lazy pointer instead
-                               ref->setTarget(*nlp, ref->getTargetOffset());
                        }
                }
        }
 
        // sort stubs
+       std::sort(fAllSynthesizedStubs.begin(), fAllSynthesizedStubs.end(), AtomByNameSorter());
+
+       // add dummy stubs (x86 only)
+       this->insertDummyStubs();
 
        // sort lazy pointers
+       std::sort(fAllSynthesizedLazyPointers.begin(), fAllSynthesizedLazyPointers.end(), AtomByNameSorter());
 
        // add stubs to fAllAtoms
        if ( fAllSynthesizedStubs.size() != 0 ) {
@@ -3428,7 +5161,8 @@ void Writer<A>::synthesizeStubs()
                        if ( nextSection != curSection ) {
                                if ( (prevAtom != NULL) 
                                        && ((strcmp(prevAtom->getSectionName(), "__dyld") == 0) 
-                                       || ((fOptions.outputKind() == Options::kDyld) && (strcmp(prevAtom->getSectionName(), "__data") == 0))) ) {
+                                       || ((strcmp(prevAtom->getSectionName(), "__data") == 0) &&
+                                               ((fOptions.outputKind() == Options::kDyld) || (fOptions.outputKind() == Options::kStaticExecutable))) ) ) {
                                        // found end of __dyld section, insert lazy pointers here
                                        fAllAtoms->insert(it, fAllSynthesizedNonLazyPointers.begin(), fAllSynthesizedNonLazyPointers.end());
                                        inserted = true;
@@ -3442,6 +5176,29 @@ void Writer<A>::synthesizeStubs()
                        throw "can't insert non-lazy pointers, __dyld section not found";
                }
        }
+       
+       // build LC_SEGMENT_SPLIT_INFO content now that all atoms exist
+       if ( fSplitCodeToDataContentAtom != NULL ) {
+               for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
+                       ObjectFile::Atom* atom = *it;
+                       std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
+                       for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                               ObjectFile::Reference* ref = *rit;
+                               switch ( ref->getTargetBinding()) {
+                                       case ObjectFile::Reference::kUnboundByName:
+                                       case ObjectFile::Reference::kDontBind:
+                                               break;
+                                       case ObjectFile::Reference::kBoundByName:
+                                       case ObjectFile::Reference::kBoundDirectly:
+                                               if ( this->segmentsCanSplitApart(*atom, ref->getTarget()) ) {
+                                                       this->addCrossSegmentRef(atom, ref);
+                                               }
+                                               break;
+                               }
+                       }
+               }
+       }
+
 }
 
 
@@ -3455,6 +5212,7 @@ void Writer<A>::partitionIntoSections()
        ObjectFile::Section* curSection = NULL;
        SectionInfo* currentSectionInfo = NULL;
        SegmentInfo* currentSegmentInfo = NULL;
+       SectionInfo* cstringSectionInfo = NULL;
        unsigned int sectionIndex = 1;
        fSegmentInfos.reserve(8);
        for (unsigned int i=0; i < fAllAtoms->size(); ++i) {
@@ -3472,11 +5230,12 @@ void Writer<A>::partitionIntoSections()
                                strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
                                currentSectionInfo->fAlignment = atom->getAlignment().powerOf2;
                                currentSectionInfo->fAllZeroFill = atom->isZeroFill();
-                               currentSectionInfo->fVirtualSection = ( (currentSectionInfo->fSectionName[0] == '.') || 
-                                               (oneSegmentCommand && (atom->getDefinitionKind()==ObjectFile::Atom::kTentativeDefinition)) && !fOptions.makeTentativeDefinitionsReal() );
+                               currentSectionInfo->fVirtualSection = (currentSectionInfo->fSectionName[0] == '.');
                                if ( !currentSectionInfo->fVirtualSection || fEmitVirtualSections )
                                        currentSectionInfo->setIndex(sectionIndex++);
                                currentSegmentInfo->fSections.push_back(currentSectionInfo);
+                               if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__cstring") == 0) ) 
+                                       cstringSectionInfo = currentSectionInfo;
                        }
                        else {
                                if ( (currentSegmentInfo == NULL) || (strcmp(currentSegmentInfo->fName, atom->getSegment().getName()) != 0) ) {
@@ -3489,13 +5248,24 @@ void Writer<A>::partitionIntoSections()
                                                initprot |= VM_PROT_WRITE;
                                        if ( atom->getSegment().isContentExecutable() )
                                                initprot |= VM_PROT_EXECUTE;
+                                       if ( fOptions.readOnlyx86Stubs() && (strcmp(atom->getSegment().getName(), "__IMPORT") == 0) )
+                                               initprot &= ~VM_PROT_WRITE;     // hack until i386 __pointers section is synthesized by linker
                                        currentSegmentInfo->fInitProtection = initprot;
                                        if ( initprot == 0 )
                                                currentSegmentInfo->fMaxProtection = 0;  // pagezero should have maxprot==initprot==0
                                        else
                                                currentSegmentInfo->fMaxProtection = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
+                                       std::vector<Options::SegmentProtect>& customSegProtections = fOptions.customSegmentProtections();
+                                       for(std::vector<Options::SegmentProtect>::iterator it = customSegProtections.begin(); it != customSegProtections.end(); ++it) {
+                                               if ( strcmp(it->name, currentSegmentInfo->fName) == 0 ) {
+                                                       currentSegmentInfo->fInitProtection = it->init;
+                                                       currentSegmentInfo->fMaxProtection = it->max;
+                                               }
+                                       }
                                        currentSegmentInfo->fBaseAddress = atom->getSegment().getBaseAddress();
                                        currentSegmentInfo->fFixedAddress = atom->getSegment().hasFixedAddress();
+                                       if ( currentSegmentInfo->fFixedAddress && (&(atom->getSegment()) == &Segment::fgStackSegment) )
+                                               currentSegmentInfo->fIndependentAddress = true;
                                        this->fSegmentInfos.push_back(currentSegmentInfo);
                                }
                                currentSectionInfo = new SectionInfo();
@@ -3527,6 +5297,8 @@ void Writer<A>::partitionIntoSections()
                                currentSectionInfo->fAllNonLazyPointers = true;
                        if ( (strcmp(currentSectionInfo->fSegmentName, "__IMPORT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__pointers") == 0) )
                                currentSectionInfo->fAllNonLazyPointers = true;
+                       if ( (fOptions.outputKind() == Options::kDyld) && (strcmp(currentSectionInfo->fSegmentName, "__DATA") == 0) && (strcmp(currentSectionInfo->fSectionName, "__pointers") == 0) )
+                               currentSectionInfo->fAllNonLazyPointers = true;
                        if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__picsymbolstub1") == 0) )
                                currentSectionInfo->fAllStubs = true;
                        if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__symbol_stub1") == 0) )
@@ -3535,9 +5307,15 @@ void Writer<A>::partitionIntoSections()
                                currentSectionInfo->fAllStubs = true;
                        if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__symbol_stub") == 0) )
                                currentSectionInfo->fAllStubs = true;
-                       if ( (strcmp(currentSectionInfo->fSegmentName, "__IMPORT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__jump_table") == 0) )
+                       if ( (strcmp(currentSectionInfo->fSegmentName, "__IMPORT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__jump_table") == 0) ) {
                                currentSectionInfo->fAllSelfModifyingStubs = true;
+                               currentSectionInfo->fAlignment = 6; // force x86 fast stubs to start on 64-byte boundary
+                       }
                        curSection = atom->getSection();
+                       if ( currentSectionInfo->fAllNonLazyPointers || currentSectionInfo->fAllLazyPointers 
+                               || currentSectionInfo->fAllStubs || currentSectionInfo->fAllStubs ) {
+                                       fSymbolTableCommands->needDynamicTable();
+                               }
                }
                // any non-zero fill atoms make whole section marked not-zero-fill
                if ( currentSectionInfo->fAllZeroFill && ! atom->isZeroFill() )
@@ -3546,7 +5324,7 @@ void Writer<A>::partitionIntoSections()
                atom->setSection(currentSectionInfo);
                // section alignment is that of a contained atom with the greatest alignment
                uint8_t atomAlign = atom->getAlignment().powerOf2;
-               if ( currentSectionInfo->fAlignment < atomAlign )
+               if ( currentSectionInfo->fAlignment < atomAlign ) 
                        currentSectionInfo->fAlignment = atomAlign;
                // calculate section offset for this atom
                uint64_t offset = currentSectionInfo->fSize;
@@ -3568,6 +5346,18 @@ void Writer<A>::partitionIntoSections()
                if ( !currentSectionInfo->fAllZeroFill && (curAtomSize > fLargestAtomSize) )
                        fLargestAtomSize = curAtomSize;
        }
+       if ( (cstringSectionInfo != NULL) && (cstringSectionInfo->fAlignment > 0) ) {
+               // when merging cstring sections in .o files, all strings need to use the max alignment
+               uint64_t offset = 0;
+               uint64_t cstringAlignment = 1 << cstringSectionInfo->fAlignment;
+               for (std::vector<ObjectFile::Atom*>::iterator it=cstringSectionInfo->fAtoms.begin(); it != cstringSectionInfo->fAtoms.end(); it++) {
+                       offset = (offset + (cstringAlignment-1)) & (-cstringAlignment);
+                       ObjectFile::Atom* atom = *it;
+                       atom->setSectionOffset(offset);
+                       offset += atom->getSize();
+               }
+               cstringSectionInfo->fSize = offset;
+       }
 }
 
 
@@ -3661,13 +5451,13 @@ bool Writer<A>::addPPCBranchIslands()
        bool result = false;
        // Can only possibly need branch islands if __TEXT segment > 16M
        if ( fLoadCommandsSegment->fSize > 16000000 ) {
-               if ( log) fprintf(stderr, "ld64: checking for branch islands, __TEXT segment size=%llu\n", fLoadCommandsSegment->fSize);
-               const uint32_t kBetweenRegions = 15000000; // place regions of islands every 15MB in __text section
+               if ( log) fprintf(stderr, "ld: checking for branch islands, __TEXT segment size=%llu\n", fLoadCommandsSegment->fSize);
+               const uint32_t kBetweenRegions = 15*1024*1024; // place regions of islands every 15MB in __text section
                SectionInfo* textSection = NULL;
                for (std::vector<SectionInfo*>::iterator it=fLoadCommandsSegment->fSections.begin(); it != fLoadCommandsSegment->fSections.end(); it++) {
                        if ( strcmp((*it)->fSectionName, "__text") == 0 ) {
                                textSection = *it;
-                               if ( log) fprintf(stderr, "ld64: checking for branch islands, __text section size=%llu\n", textSection->fSize);
+                               if ( log) fprintf(stderr, "ld: checking for branch islands, __text section size=%llu\n", textSection->fSize);
                                break;
                        }
                }
@@ -3752,7 +5542,7 @@ bool Writer<A>::addPPCBranchIslands()
 
                // insert islands into __text section and adjust section offsets
                if ( islandCount > 0 ) {
-                       if ( log) fprintf(stderr, "ld64: %u branch islands required\n", islandCount);
+                       if ( log ) fprintf(stderr, "ld: %u branch islands required in %u regions\n", islandCount, kIslandRegionsCount);
                        std::vector<ObjectFile::Atom*> newAtomList;
                        newAtomList.reserve(textSection->fAtoms.size()+islandCount);
                        uint64_t islandRegionAddr = kBetweenRegions;
@@ -3783,9 +5573,9 @@ bool Writer<A>::addPPCBranchIslands()
                                if ( atomSlide != 0 )
                                        atom->setSectionOffset(atom->getSectionOffset()+atomSlide);
                        }
+                       sectionOffset = textSection->fSize+atomSlide;
                        // put any remaining islands at end of __text section
                        if ( regionIndex < kIslandRegionsCount ) {
-                               sectionOffset = textSection->fSize;
                                std::vector<ObjectFile::Atom*>* regionIslands = &regionsIslands[regionIndex];
                                for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
                                        ObjectFile::Atom* islandAtom = *rit;
@@ -3830,16 +5620,16 @@ void Writer<A>::adjustLoadCommandsAndPadding()
 
        std::vector<SectionInfo*>& sectionInfos = fLoadCommandsSegment->fSections;
        const int sectionCount = sectionInfos.size();
+       uint32_t totalSizeOfHeaderAndLoadCommands = 0;
+       for(int j=0; j < sectionCount; ++j) {
+               SectionInfo* curSection = sectionInfos[j];
+               totalSizeOfHeaderAndLoadCommands += curSection->fSize;
+               if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 )
+                       break;
+       }
        uint64_t paddingSize = 0;
        if ( fOptions.outputKind() == Options::kDyld ) {
                // dyld itself has special padding requirements.  We want the beginning __text section to start at a stable address
-               uint32_t totalSizeOfHeaderAndLoadCommands = 0;
-               for(int j=0; j < sectionCount; ++j) {
-                       SectionInfo* curSection = sectionInfos[j];
-                       totalSizeOfHeaderAndLoadCommands += curSection->fSize;
-                       if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 )
-                               break;
-               }
                paddingSize = 4096 - (totalSizeOfHeaderAndLoadCommands % 4096);
        }
        else if ( fOptions.outputKind() == Options::kObjectFile ) {
@@ -3847,22 +5637,31 @@ void Writer<A>::adjustLoadCommandsAndPadding()
                paddingSize = 0;
        }
        else {
-               // calculate max padding to keep segment size same, but all free space at end of load commands
-               uint64_t totalSize = 0;
-               uint64_t worstCaseAlignmentPadding = 0;
-               for(int j=0; j < sectionCount; ++j) {
+               // work backwards from end of segment and lay out sections so that extra room goes to padding atom
+               uint64_t addr = 0;
+               for(int j=sectionCount-1; j >=0; --j) {
                        SectionInfo* curSection = sectionInfos[j];
-                       totalSize += curSection->fSize;
-                       if ( j != 0 ) // don't count aligment of mach_header which is page-aligned
-                               worstCaseAlignmentPadding += (1 << curSection->fAlignment) - 1;
+                       addr -= curSection->fSize;
+                       addr = addr & (0 - (1 << curSection->fAlignment));
+                       if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 ) {
+                               addr -= totalSizeOfHeaderAndLoadCommands;
+                               paddingSize = addr % 4096;
+                               break;
+                       }
                }
-               uint64_t segmentSize = ((totalSize+worstCaseAlignmentPadding+4095) & (-4096));
-               // don't know exactly how it will layout, but we can inflate padding atom this big and still keep aligment constraints
-               paddingSize = segmentSize - (totalSize+worstCaseAlignmentPadding);
 
                // if command line requires more padding than this
-               if ( paddingSize < fOptions.minimumHeaderPad() ) {
-                       int extraPages = (fOptions.minimumHeaderPad() - paddingSize + 4095)/4096;
+               uint32_t minPad = fOptions.minimumHeaderPad();
+               if ( fOptions.maxMminimumHeaderPad() ) {
+                       // -headerpad_max_install_names means there should be room for every path load command to grow to 1204 bytes
+                       uint32_t altMin = fLibraryToOrdinal.size() * MAXPATHLEN;
+                       if ( fOptions.outputKind() ==  Options::kDynamicLibrary )
+                               altMin += MAXPATHLEN;
+                       if ( altMin > minPad )
+                               minPad = altMin;
+               }
+               if ( paddingSize < minPad ) {
+                       int extraPages = (minPad - paddingSize + 4095)/4096;
                        paddingSize += extraPages * 4096;
                }
        }
@@ -3884,11 +5683,32 @@ void Writer<A>::assignFileOffsets()
        bool haveFixedSegments = false;
        uint64_t fileOffset = 0;
        uint64_t nextContiguousAddress = fOptions.baseAddress();
+       uint64_t nextReadOnlyAddress = fOptions.baseAddress();
+       uint64_t nextWritableAddress = fOptions.baseWritableAddress();
+
+       // process segments with fixed addresses (-segaddr)
+       for (std::vector<Options::SegmentStart>::iterator it = fOptions.customSegmentAddresses().begin(); it != fOptions.customSegmentAddresses().end(); ++it) {
+                       for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
+                       SegmentInfo* curSegment = *segit;
+                       if ( strcmp(curSegment->fName, it->name) == 0 ) {
+                               curSegment->fBaseAddress = it->address;
+                               curSegment->fFixedAddress = true;
+                               break;
+                       }
+               }
+       }
 
        // Run through the segments and each segment's sections to assign addresses
        for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
                SegmentInfo* curSegment = *segit;
                
+               if ( fOptions.splitSeg() ) {
+                       if ( curSegment->fInitProtection & VM_PROT_WRITE ) 
+                               nextContiguousAddress = nextWritableAddress;
+                       else
+                               nextContiguousAddress = nextReadOnlyAddress;
+               }
+               
                fileOffset = (fileOffset+4095) & (-4096);
                curSegment->fFileOffset = fileOffset;
                
@@ -3923,7 +5743,7 @@ void Writer<A>::assignFileOffsets()
                        // update section info
                        curSection->fFileOffset = fileOffset;
                        curSection->setBaseAddress(address);
-                       
+
                        // keep track of trailing zero fill sections
                        if ( curSection->fAllZeroFill && (firstZeroFillSection == NULL) )
                                firstZeroFillSection = curSection;
@@ -3935,6 +5755,10 @@ void Writer<A>::assignFileOffsets()
                                address += curSection->fSize;
                        fileOffset += curSection->fSize;
                        
+                       // sanity check size of 32-bit binaries
+                       if ( address > maxAddress() )
+                               throwf("section %s exceeds 4GB limit", curSection->fSectionName);
+                       
                        // update segment info
                        curSegment->fFileSize = fileOffset - curSegment->fFileOffset;
                        curSegment->fSize = curSegment->fFileSize;
@@ -3953,8 +5777,13 @@ void Writer<A>::assignFileOffsets()
                        // page align segment size
                        curSegment->fFileSize = (curSegment->fFileSize+4095) & (-4096);
                        curSegment->fSize         = (curSegment->fSize+4095) & (-4096);
-                       if ( curSegment->fBaseAddress == nextContiguousAddress )
+                       if ( !curSegment->fIndependentAddress && (curSegment->fBaseAddress >= nextContiguousAddress) ) {
                                nextContiguousAddress = (curSegment->fBaseAddress+curSegment->fSize+4095) & (-4096);
+                               if ( curSegment->fInitProtection & VM_PROT_WRITE )
+                                       nextWritableAddress = nextContiguousAddress;
+                               else
+                                       nextReadOnlyAddress = nextContiguousAddress;
+                       }
                }
        }
                        
@@ -4009,7 +5838,7 @@ void Writer<A>::adjustLinkEditSections()
        while ( strcmp(lastSeg->fSections[firstLinkEditSectionIndex]->fSegmentName, "__LINKEDIT") != 0 )
                ++firstLinkEditSectionIndex;
 
-       const unsigned int sectionCount = lastSeg->fSections.size();
+       const unsigned int linkEditSectionCount = lastSeg->fSections.size();
        uint64_t fileOffset = lastSeg->fSections[firstLinkEditSectionIndex]->fFileOffset;
        uint64_t address = lastSeg->fSections[firstLinkEditSectionIndex]->getBaseAddress();
        if ( fPadSegmentInfo != NULL ) {
@@ -4027,13 +5856,19 @@ void Writer<A>::adjustLinkEditSections()
                address = fOptions.zeroPageSize();
                lastSeg->fBaseAddress = fOptions.zeroPageSize();
        }
-       for (unsigned int i=firstLinkEditSectionIndex; i < sectionCount; ++i) {
+       for (unsigned int i=firstLinkEditSectionIndex; i < linkEditSectionCount; ++i) {
                std::vector<class ObjectFile::Atom*>& atoms = lastSeg->fSections[i]->fAtoms;
-               const unsigned int atomCount = atoms.size();
-               uint64_t sectionOffset = 0;
-               lastSeg->fSections[i]->fFileOffset = fileOffset;
+               // adjust section address based on alignment
+               uint64_t sectionAlignment = 1 << lastSeg->fSections[i]->fAlignment;
+               uint64_t pad = ((address+sectionAlignment-1) & (-sectionAlignment)) - address;
+               address += pad;
+               fileOffset += pad;      // adjust file offset to match address
                lastSeg->fSections[i]->setBaseAddress(address);
-               for (unsigned int j=0; j < atomCount; ++j) {
+               if ( strcmp(lastSeg->fSections[i]->fSectionName, "._absolute") == 0 )
+                       lastSeg->fSections[i]->setBaseAddress(0);
+               lastSeg->fSections[i]->fFileOffset = fileOffset;
+               uint64_t sectionOffset = 0;
+               for (unsigned int j=0; j < atoms.size(); ++j) {
                        ObjectFile::Atom* atom = atoms[j];
                        uint64_t alignment = 1 << atom->getAlignment().powerOf2;
                        sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
@@ -4082,8 +5917,9 @@ ObjectFile::Atom::SymbolTableInclusion MachHeaderAtom<A>::getSymbolTableInclusio
 {
        switch ( fWriter.fOptions.outputKind() ) {
                case Options::kDynamicExecutable:
-               case Options::kStaticExecutable:
                        return ObjectFile::Atom::kSymbolTableInAndNeverStrip;
+               case Options::kStaticExecutable:
+                       return ObjectFile::Atom::kSymbolTableInAsAbsolute;
                case Options::kDynamicLibrary:
                case Options::kDynamicBundle:
                case Options::kDyld:
@@ -4156,7 +5992,7 @@ void MachHeaderAtom<A>::copyRawContent(uint8_t buffer[]) const
        // get flags
        uint32_t flags = 0;
        if ( fWriter.fOptions.outputKind() == Options::kObjectFile ) {
-               if ( ! fWriter.fSeenFollowOnReferences )
+               if ( fWriter.fCanScatter )
                        flags = MH_SUBSECTIONS_VIA_SYMBOLS;
        }
        else {
@@ -4181,9 +6017,21 @@ void MachHeaderAtom<A>::copyRawContent(uint8_t buffer[]) const
                                flags |= MH_WEAK_DEFINES;
                        if ( fWriter.fReferencesWeakImports || fWriter.fHasWeakExports )
                                flags |= MH_BINDS_TO_WEAK;
+                       if ( fWriter.fOptions.prebind() )
+                               flags |= MH_PREBOUND;
+                       if ( fWriter.fOptions.splitSeg() )
+                               flags |= MH_SPLIT_SEGS;
+                       if ( (fWriter.fOptions.outputKind() == Options::kDynamicLibrary) && fWriter.fNoReExportedDylibs ) 
+                               flags |= MH_NO_REEXPORTED_DYLIBS;
+                       if ( fWriter.fOptions.positionIndependentExecutable() ) 
+                               flags |= MH_PIE;
                }
                if ( fWriter.fOptions.hasExecutableStack() )
                        flags |= MH_ALLOW_STACK_EXECUTION;
+               if ( fWriter.fOptions.readerOptions().fRootSafe )
+                       flags |= MH_ROOT_SAFE;
+               if ( fWriter.fOptions.readerOptions().fSetuidSafe )
+                       flags |= MH_SETUID_SAFE;
        }
 
        // get commands info
@@ -4191,16 +6039,15 @@ void MachHeaderAtom<A>::copyRawContent(uint8_t buffer[]) const
        uint32_t commandsCount = 0;
 
        std::vector<class ObjectFile::Atom*>& loadCommandAtoms = fWriter.fLoadCommandsSection->fAtoms;
-       const unsigned int atomCount = loadCommandAtoms.size();
-       for (unsigned int i=0; i < atomCount; ++i) {
-               ObjectFile::Atom* atom = loadCommandAtoms[i];
+       for (std::vector<ObjectFile::Atom*>::iterator it=loadCommandAtoms.begin(); it != loadCommandAtoms.end(); it++) {
+               ObjectFile::Atom* atom = *it;
                commandsSize += atom->getSize();
                // segment and symbol table atoms can contain more than one load command
                if ( atom == fWriter.fSegmentCommands )
                        commandsCount += fWriter.fSegmentCommands->commandCount();
                else if ( atom == fWriter.fSymbolTableCommands )
                        commandsCount += fWriter.fSymbolTableCommands->commandCount();
-               else if ( atom->getSize() != 0)
+               else if ( atom->getSize() != 0 )
                        ++commandsCount;
        }
 
@@ -4218,7 +6065,20 @@ void MachHeaderAtom<ppc>::setHeaderInfo(macho_header<ppc::P>& header) const
 {
        header.set_magic(MH_MAGIC);
        header.set_cputype(CPU_TYPE_POWERPC);
-       header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL);
+       switch ( fWriter.fCpuConstraint ) {
+               case ObjectFile::Reader::kCpuAny:
+                       header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL);
+                       break;
+               case ObjectFile::Reader::kCpuG3:
+                       header.set_cpusubtype(CPU_SUBTYPE_POWERPC_750);
+                       break;
+               case ObjectFile::Reader::kCpuG4:
+                       header.set_cpusubtype(CPU_SUBTYPE_POWERPC_7400);
+                       break;
+               case ObjectFile::Reader::kCpuG5:
+                       header.set_cpusubtype(CPU_SUBTYPE_POWERPC_970);
+                       break;
+       }
 }
 
 template <>
@@ -4226,7 +6086,10 @@ void MachHeaderAtom<ppc64>::setHeaderInfo(macho_header<ppc64::P>& header) const
 {
        header.set_magic(MH_MAGIC_64);
        header.set_cputype(CPU_TYPE_POWERPC64);
-       header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL);
+       if ( (fWriter.fOptions.outputKind() == Options::kDynamicExecutable) && (fWriter.fOptions.macosxVersionMin() >= ObjectFile::ReaderOptions::k10_5) )
+               header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL | 0x80000000);
+       else
+               header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL);
        header.set_reserved(0);
 }
 
@@ -4243,7 +6106,11 @@ void MachHeaderAtom<x86_64>::setHeaderInfo(macho_header<x86_64::P>& header) cons
 {
        header.set_magic(MH_MAGIC_64);
        header.set_cputype(CPU_TYPE_X86_64);
-       header.set_cpusubtype(CPU_SUBTYPE_X86_64_ALL);
+       if ( (fWriter.fOptions.outputKind() == Options::kDynamicExecutable) && (fWriter.fOptions.macosxVersionMin() >= ObjectFile::ReaderOptions::k10_5) )
+               header.set_cpusubtype(CPU_SUBTYPE_X86_64_ALL | 0x80000000);
+       else
+               header.set_cpusubtype(CPU_SUBTYPE_X86_64_ALL);
+       header.set_reserved(0);
 }
 
 
@@ -4406,7 +6273,7 @@ void SegmentLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
                                        sect->set_flags(S_MOD_TERM_FUNC_POINTERS);
                                }
                                else if ( (strcmp(sectInfo->fSectionName, "__eh_frame") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
-                                       sect->set_flags(S_COALESCED);
+                                       sect->set_flags(S_COALESCED | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS);
                                }
                                else if ( (strcmp(sectInfo->fSectionName, "__textcoal_nt") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
                                        sect->set_flags(S_COALESCED);
@@ -4432,6 +6299,12 @@ void SegmentLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
                                else if ( (strcmp(sectInfo->fSectionName, "__message_refs") == 0) && (strcmp(sectInfo->fSegmentName, "__OBJC") == 0) ) {
                                        sect->set_flags(S_LITERAL_POINTERS);
                                }
+                               else if ( (strncmp(sectInfo->fSectionName, "__dof_", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
+                                       sect->set_flags(S_DTRACE_DOF);
+                               }
+                               else if ( (strncmp(sectInfo->fSectionName, "__dof_", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
+                                       sect->set_flags(S_DTRACE_DOF);
+                               }
                                else if ( (strncmp(sectInfo->fSectionName, "__text", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
                                        sect->set_flags(S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS);
                                }
@@ -4450,16 +6323,37 @@ SymbolTableLoadCommandsAtom<A>::SymbolTableLoadCommandsAtom(Writer<A>& writer)
 {
        bzero(&fSymbolTable, sizeof(macho_symtab_command<P>));
        bzero(&fDynamicSymbolTable, sizeof(macho_dysymtab_command<P>));
+       switch ( fWriter.fOptions.outputKind() ) {
+               case Options::kDynamicExecutable:
+               case Options::kDynamicLibrary:
+               case Options::kDynamicBundle:
+               case Options::kDyld:
+                       fNeedsDynamicSymbolTable = true;
+                       break;
+               case Options::kObjectFile:
+               case Options::kStaticExecutable:
+                       fNeedsDynamicSymbolTable = false;
+                       break;
+       }
        writer.fSymbolTableCommands = this;
 }
 
+
+
+template <typename A>
+void SymbolTableLoadCommandsAtom<A>::needDynamicTable() 
+{
+       fNeedsDynamicSymbolTable = true;
+}
+       
+
 template <typename A>
 uint64_t SymbolTableLoadCommandsAtom<A>::getSize() const
 {
-       if ( fWriter.fOptions.outputKind() == Options::kStaticExecutable )
-               return this->alignedSize(sizeof(macho_symtab_command<P>));
-       else
+       if ( fNeedsDynamicSymbolTable )
                return this->alignedSize(sizeof(macho_symtab_command<P>) + sizeof(macho_dysymtab_command<P>));
+       else
+               return this->alignedSize(sizeof(macho_symtab_command<P>));
 }
 
 template <typename A>
@@ -4476,7 +6370,7 @@ void SymbolTableLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
        symbolTableCmd->set_strsize(fWriter.fStringsAtom->getSize());
 
        // build LC_DYSYMTAB command
-       if ( fWriter.fOptions.outputKind() != Options::kStaticExecutable ) {
+       if ( fNeedsDynamicSymbolTable ) {
                macho_dysymtab_command<P>* dynamicSymbolTableCmd = (macho_dysymtab_command<P>*)&buffer[sizeof(macho_symtab_command<P>)];
                bzero(dynamicSymbolTableCmd, sizeof(macho_dysymtab_command<P>));
                dynamicSymbolTableCmd->set_cmd(LC_DYSYMTAB);
@@ -4487,6 +6381,14 @@ void SymbolTableLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
                dynamicSymbolTableCmd->set_nextdefsym(fWriter.fSymbolTableExportCount);
                dynamicSymbolTableCmd->set_iundefsym(fWriter.fSymbolTableImportStartIndex);
                dynamicSymbolTableCmd->set_nundefsym(fWriter.fSymbolTableImportCount);
+               if ( fWriter.fModuleInfoAtom != NULL ) {
+                       dynamicSymbolTableCmd->set_tocoff(fWriter.fModuleInfoAtom->getTableOfContentsFileOffset());
+                       dynamicSymbolTableCmd->set_ntoc(fWriter.fSymbolTableExportCount);
+                       dynamicSymbolTableCmd->set_modtaboff(fWriter.fModuleInfoAtom->getModuleTableFileOffset());
+                       dynamicSymbolTableCmd->set_nmodtab(1);
+                       dynamicSymbolTableCmd->set_extrefsymoff(fWriter.fModuleInfoAtom->getReferencesFileOffset());
+                       dynamicSymbolTableCmd->set_nextrefsyms(fWriter.fModuleInfoAtom->getReferencesCount());
+               }
                dynamicSymbolTableCmd->set_indirectsymoff(fWriter.fIndirectTableAtom->getFileOffset());
                dynamicSymbolTableCmd->set_nindirectsyms(fWriter.fIndirectTableAtom->fTable.size());
                if ( fWriter.fOptions.outputKind() != Options::kObjectFile ) {
@@ -4498,10 +6400,11 @@ void SymbolTableLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
        }
 }
 
+
 template <typename A>
 unsigned int SymbolTableLoadCommandsAtom<A>::commandCount()
 {
-       return (fWriter.fOptions.outputKind() == Options::kStaticExecutable) ? 1 : 2;
+       return fNeedsDynamicSymbolTable ? 2 : 1;
 }
 
 template <typename A>
@@ -4548,27 +6451,32 @@ void AllowableClientLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 template <typename A>
 uint64_t DylibLoadCommandsAtom<A>::getSize() const
 {
-       const char* path = fInfo.reader->getInstallPath();
-       if ( fInfo.options.fInstallPathOverride != NULL )
-               path = fInfo.options.fInstallPathOverride;
-       return this->alignedSize(sizeof(macho_dylib_command<P>) + strlen(path) + 1);
+       if ( fOptimizedAway ) {
+               return 0;
+       }
+       else {
+               const char* path = fInfo.reader->getInstallPath();
+               return this->alignedSize(sizeof(macho_dylib_command<P>) + strlen(path) + 1);
+       }
 }
 
 template <typename A>
 void DylibLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
+       if ( fOptimizedAway ) 
+               return;
        uint64_t size = this->getSize();
        bzero(buffer, size);
        const char* path = fInfo.reader->getInstallPath();
-       if ( fInfo.options.fInstallPathOverride != NULL )
-               path = fInfo.options.fInstallPathOverride;
        macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)buffer;
        if ( fInfo.options.fWeakImport )
                cmd->set_cmd(LC_LOAD_WEAK_DYLIB);
+       else if ( fInfo.options.fReExport && (fWriter.fOptions.macosxVersionMin() >= ObjectFile::ReaderOptions::k10_5) )
+               cmd->set_cmd(LC_REEXPORT_DYLIB);
        else
                cmd->set_cmd(LC_LOAD_DYLIB);
        cmd->set_cmdsize(this->getSize());
-       cmd->set_timestamp(fInfo.reader->getTimestamp());
+       cmd->set_timestamp(2);  // needs to be some constant value that is different than DylibIDLoadCommandsAtom uses
        cmd->set_current_version(fInfo.reader->getCurrentVersion());
        cmd->set_compatibility_version(fInfo.reader->getCompatibilityVersion());
        cmd->set_name_offset();
@@ -4586,16 +6494,13 @@ uint64_t DylibIDLoadCommandsAtom<A>::getSize() const
 template <typename A>
 void DylibIDLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
-       struct timeval currentTime = { 0 , 0 };
-       gettimeofday(&currentTime, NULL);
-       time_t timestamp = currentTime.tv_sec;
        uint64_t size = this->getSize();
        bzero(buffer, size);
        macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)buffer;
        cmd->set_cmd(LC_ID_DYLIB);
        cmd->set_cmdsize(this->getSize());
        cmd->set_name_offset();
-       cmd->set_timestamp(timestamp);
+       cmd->set_timestamp(1);  // needs to be some constant value that is different than DylibLoadCommandsAtom uses
        cmd->set_current_version(fWriter.fOptions.currentVersion());
        cmd->set_compatibility_version(fWriter.fOptions.compatibilityVersion());
        strcpy((char*)&buffer[sizeof(macho_dylib_command<P>)], fWriter.fOptions.installPath());
@@ -4632,6 +6537,30 @@ void SubUmbrellaLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
        strcpy((char*)&buffer[sizeof(macho_sub_umbrella_command<P>)], fName);
 }
 
+template <typename A>
+void UUIDLoadCommandAtom<A>::generate() 
+{
+       switch ( fWriter.fOptions.getUUIDMode() ) {
+               case Options::kUUIDNone: 
+                       fEmit = false;
+                       break;
+               case Options::kUUIDRandom:
+                       ::uuid_generate_random(fUUID);
+                       fEmit = true;
+                       break;
+               case Options::kUUIDContent: 
+                       bzero(fUUID, 16);
+                       fEmit = true;
+                       break;
+       }
+}
+
+template <typename A>
+void UUIDLoadCommandAtom<A>::setContent(const uint8_t uuid[16]) 
+{
+       memcpy(fUUID, uuid, 16);
+}
+
 template <typename A>
 void UUIDLoadCommandAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
@@ -4645,6 +6574,7 @@ void UUIDLoadCommandAtom<A>::copyRawContent(uint8_t buffer[]) const
        }
 }
 
+
 template <typename A>
 uint64_t SubLibraryLoadCommandsAtom<A>::getSize() const
 {
@@ -4752,7 +6682,7 @@ void ThreadsLoadCommandsAtom<x86>::copyRawContent(uint8_t buffer[]) const
        cmd->set_count(16);                             // i386_THREAD_STATE_COUNT;
        cmd->set_thread_register(10, start);
        if ( fWriter.fOptions.hasCustomStack() )
-               cmd->set_thread_register(15, fWriter.fOptions.customStackAddr());       // uesp
+               cmd->set_thread_register(7, fWriter.fOptions.customStackAddr());        // esp
 }
 
 
@@ -4773,6 +6703,25 @@ void ThreadsLoadCommandsAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 }
 
 
+template <typename A>
+uint64_t RPathLoadCommandsAtom<A>::getSize() const
+{
+       return this->alignedSize(sizeof(macho_rpath_command<P>) + strlen(fPath) + 1);
+}
+
+template <typename A>
+void RPathLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
+{
+       uint64_t size = this->getSize();
+       bzero(buffer, size);
+       macho_rpath_command<P>* cmd = (macho_rpath_command<P>*)buffer;
+       cmd->set_cmd(LC_RPATH);
+       cmd->set_cmdsize(this->getSize());
+       cmd->set_path_offset();
+       strcpy((char*)&buffer[sizeof(macho_rpath_command<P>)], fPath);
+}
+
+
 template <typename A>
 void LoadCommandsPaddingAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
@@ -4843,6 +6792,7 @@ uint64_t ExternalRelocationsLinkEditAtom<A>::getSize() const
 template <typename A>
 void ExternalRelocationsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
+       std::sort(fWriter.fExternalRelocs.begin(), fWriter.fExternalRelocs.end(), ExternalRelocSorter<P>());
        memcpy(buffer, &fWriter.fExternalRelocs[0], this->getSize());
 }
 
@@ -4873,445 +6823,385 @@ void IndirectTableLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
 
 
-template <typename A>
-StringsLinkEditAtom<A>::StringsLinkEditAtom(Writer<A>& writer)
-       : LinkEditAtom<A>(writer), fCurrentBuffer(NULL), fCurrentBufferUsed(0)
-{
-       fCurrentBuffer = new char[kBufferSize];
-       // burn first byte of string pool (so zero is never a valid string offset)
-       fCurrentBuffer[fCurrentBufferUsed++] = ' ';
-       // make offset 1 always point to an empty string
-       fCurrentBuffer[fCurrentBufferUsed++] = '\0';
-}
-
-template <typename A>
-uint64_t StringsLinkEditAtom<A>::getSize() const
-{
-       return kBufferSize * fFullBuffers.size() + fCurrentBufferUsed;
-}
-
-template <typename A>
-void StringsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
-{
-       uint64_t offset = 0;
-       for (unsigned int i=0; i < fFullBuffers.size(); ++i) {
-               memcpy(&buffer[offset], fFullBuffers[i], kBufferSize);
-               offset += kBufferSize;
-       }
-       memcpy(&buffer[offset], fCurrentBuffer, fCurrentBufferUsed);
-}
-
-template <typename A>
-int32_t StringsLinkEditAtom<A>::add(const char* name)
-{
-       int32_t offset = kBufferSize * fFullBuffers.size() + fCurrentBufferUsed;
-       int lenNeeded = strlcpy(&fCurrentBuffer[fCurrentBufferUsed], name, kBufferSize-fCurrentBufferUsed)+1;
-       if ( (fCurrentBufferUsed+lenNeeded) < kBufferSize ) {
-               fCurrentBufferUsed += lenNeeded;
-       }
-       else {
-               int copied = kBufferSize-fCurrentBufferUsed-1;
-               // change trailing '\0' that strlcpy added to real char
-               fCurrentBuffer[kBufferSize-1] = name[copied];
-               // alloc next buffer
-               fFullBuffers.push_back(fCurrentBuffer);
-               fCurrentBuffer = new char[kBufferSize];
-               fCurrentBufferUsed = 0;
-               // append rest of string
-               this->add(&name[copied+1]);
-       }
-       return offset;
-}
-
-
-template <typename A>
-int32_t StringsLinkEditAtom<A>::addUnique(const char* name)
-{
-       StringToOffset::iterator pos = fUniqueStrings.find(name);
-       if ( pos != fUniqueStrings.end() ) {
-               return pos->second;
-       }
-       else {
-               int32_t offset = this->add(name);
-               fUniqueStrings[name] = offset;
-               return offset;
-       }
-}
-
-
-template <typename A>
-BranchIslandAtom<A>::BranchIslandAtom(Writer<A>& writer, const char* name, int islandRegion, ObjectFile::Atom& target, uint32_t targetOffset)
- : WriterAtom<A>(writer, Segment::fgTextSegment), fTarget(target), fTargetOffset(targetOffset)
-{
-       char* buf = new char[strlen(name)+32];
-       if ( targetOffset == 0 ) {
-               if ( islandRegion == 0 )
-                       sprintf(buf, "%s$island", name);
-               else
-                       sprintf(buf, "%s$island_%d", name, islandRegion);
-       }
-       else {
-               sprintf(buf, "%s_plus_%d$island_%d", name, targetOffset, islandRegion);
-       }
-       fName = buf;
-}
-
-
-template <>
-void BranchIslandAtom<ppc>::copyRawContent(uint8_t buffer[]) const
-{
-       int64_t displacement = fTarget.getAddress() + fTargetOffset - this->getAddress();
-       int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC);
-       OSWriteBigInt32(buffer, 0, branchInstruction);
-}
-
-template <>
-void BranchIslandAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
-{
-       int64_t displacement = fTarget.getAddress() + fTargetOffset - this->getAddress();
-       int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC);
-       OSWriteBigInt32(buffer, 0, branchInstruction);
-}
-
-template <>
-uint64_t BranchIslandAtom<ppc>::getSize() const
-{
-       return 4;
-}
-
-template <>
-uint64_t BranchIslandAtom<ppc64>::getSize() const
-{
-       return 4;
-}
-
-
-template <>
-bool StubAtom<ppc64>::pic() const
-{
-       // no-pic stubs for ppc64 don't work if lazy pointer is above low 2GB.
-       // This usually only happens when a large zero-page is requested
-       switch ( fWriter.fOptions.outputKind() ) {
-               case Options::kDynamicExecutable:
-                       return (fWriter.fPageZeroAtom->getSize() > 4096);
-               case Options::kDynamicLibrary:
-               case Options::kDynamicBundle:
-                       return true;
-               case Options::kObjectFile:
-               case Options::kDyld:
-               case Options::kStaticExecutable:
-                       break;
-       }
-       throw "internal ld64 error: file type does not use stubs";
-}
-
-template <>
-bool StubAtom<ppc>::pic() const
-{
-       return ( fWriter.fOptions.outputKind() != Options::kDynamicExecutable );
-}
-
-template <>
-ObjectFile::Alignment StubAtom<ppc>::getAlignment() const
-{
-       return 2;
-}
-
-template <>
-ObjectFile::Alignment StubAtom<ppc64>::getAlignment() const
-{
-       return 2;
-}
-
-template <>
-StubAtom<ppc>::StubAtom(Writer<ppc>& writer, ObjectFile::Atom& target)
- : WriterAtom<ppc>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
-{
-       writer.fAllSynthesizedStubs.push_back(this);
-
-       LazyPointerAtom<ppc>* lp = new LazyPointerAtom<ppc>(writer, target);
-       if ( pic() ) {
-               // picbase is 8 bytes into atom
-               fReferences.push_back(new WriterReference<ppc>(12, ppc::kPICBaseHigh16, lp, 0, NULL, 8));
-               fReferences.push_back(new WriterReference<ppc>(20, ppc::kPICBaseLow16, lp, 0, NULL, 8));
-       }
-       else {
-               fReferences.push_back(new WriterReference<ppc>(0, ppc::kAbsHigh16AddLow, lp));
-               fReferences.push_back(new WriterReference<ppc>(4, ppc::kAbsLow16, lp));
-       }
-}
-
-template <>
-StubAtom<ppc64>::StubAtom(Writer<ppc64>& writer, ObjectFile::Atom& target)
- : WriterAtom<ppc64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
-{
-       writer.fAllSynthesizedStubs.push_back(this);
-
-       LazyPointerAtom<ppc64>* lp = new LazyPointerAtom<ppc64>(writer, target);
-       if ( pic() ) {
-               // picbase is 8 bytes into atom
-               fReferences.push_back(new WriterReference<ppc64>(12, ppc64::kPICBaseHigh16, lp, 0, NULL, 8));
-               fReferences.push_back(new WriterReference<ppc64>(20, ppc64::kPICBaseLow14, lp, 0, NULL, 8));
-       }
-       else {
-               fReferences.push_back(new WriterReference<ppc64>(0, ppc64::kAbsHigh16AddLow, lp));
-               fReferences.push_back(new WriterReference<ppc64>(4, ppc64::kAbsLow14, lp));
-       }
-}
-
-// specialize to put x86 fast stub in __IMPORT segment with no lazy pointer
-template <>
-StubAtom<x86>::StubAtom(Writer<x86>& writer, ObjectFile::Atom& target)
- : WriterAtom<x86>(writer, Segment::fgImportSegment), fName(stubName(target.getName())), fTarget(target)
-{
-       writer.fAllSynthesizedStubs.push_back(this);
-}
-
-template <>
-StubAtom<x86_64>::StubAtom(Writer<x86_64>& writer, ObjectFile::Atom& target)
- : WriterAtom<x86_64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
-{
-       writer.fAllSynthesizedStubs.push_back(this);
-
-       LazyPointerAtom<x86_64>* lp = new LazyPointerAtom<x86_64>(writer, target);
-       fReferences.push_back(new WriterReference<x86_64>(2, x86_64::kPCRel32, lp));
-}
-
-template <typename A>
-const char* StubAtom<A>::stubName(const char* name)
-{
-       char* buf;
-       asprintf(&buf, "%s$stub", name);
-       return buf;
-}
-
-template <>
-uint64_t StubAtom<ppc>::getSize() const
+template <typename A>
+uint64_t ModuleInfoLinkEditAtom<A>::getSize() const
 {
-       return ( pic() ? 32 : 16 );
+       return fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>) 
+                       + sizeof(macho_dylib_module<P>) 
+                       + this->getReferencesCount()*sizeof(uint32_t);
 }
 
-template <>
-uint64_t StubAtom<ppc64>::getSize() const
+template <typename A>
+uint32_t ModuleInfoLinkEditAtom<A>::getTableOfContentsFileOffset() const
 {
-       return ( pic() ? 32 : 16 );
+       return this->getFileOffset();
 }
 
-template <>
-uint64_t StubAtom<x86>::getSize() const
+template <typename A>
+uint32_t ModuleInfoLinkEditAtom<A>::getModuleTableFileOffset() const
 {
-       return 5;
+       return this->getFileOffset() + fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>);
 }
 
-template <>
-uint64_t StubAtom<x86_64>::getSize() const
+template <typename A>
+uint32_t ModuleInfoLinkEditAtom<A>::getReferencesFileOffset() const
 {
-       return 6;
+       return this->getModuleTableFileOffset() + sizeof(macho_dylib_module<P>);
 }
 
-template <>
-ObjectFile::Alignment StubAtom<x86>::getAlignment() const
+template <typename A>
+uint32_t ModuleInfoLinkEditAtom<A>::getReferencesCount() const
 {
-       // special case x86 fast stubs to be byte aligned
-       return 0;
+       return fWriter.fSymbolTableExportCount + fWriter.fSymbolTableImportCount;
 }
 
-template <>
-void StubAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
+template <typename A>
+void ModuleInfoLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
-       if ( pic() ) {
-               OSWriteBigInt32(&buffer [0], 0, 0x7c0802a6);    //      mflr r0
-               OSWriteBigInt32(&buffer[ 4], 0, 0x429f0005);    //  bcl 20,31,Lpicbase
-               OSWriteBigInt32(&buffer[ 8], 0, 0x7d6802a6);    // Lpicbase: mflr r11
-               OSWriteBigInt32(&buffer[12], 0, 0x3d6b0000);    //      addis r11,r11,ha16(L_fwrite$lazy_ptr-Lpicbase)
-               OSWriteBigInt32(&buffer[16], 0, 0x7c0803a6);    //      mtlr r0
-               OSWriteBigInt32(&buffer[20], 0, 0xe98b0001);    //      ldu r12,lo16(L_fwrite$lazy_ptr-Lpicbase)(r11)
-               OSWriteBigInt32(&buffer[24], 0, 0x7d8903a6);    //  mtctr r12
-               OSWriteBigInt32(&buffer[28], 0, 0x4e800420);    //  bctr
+       uint64_t size = this->getSize();
+       bzero(buffer, size);
+       // create toc.  The symbols are already sorted, they are all in the smae module
+       macho_dylib_table_of_contents<P>* p = (macho_dylib_table_of_contents<P>*)buffer;
+       for(uint32_t i=0; i < fWriter.fSymbolTableExportCount; ++i, ++p) {
+               p->set_symbol_index(fWriter.fSymbolTableExportStartIndex+i);
+               p->set_module_index(0);
        }
-       else {
-               OSWriteBigInt32(&buffer[ 0], 0, 0x3d600000);    // lis r11,ha16(L_fwrite$lazy_ptr)
-               OSWriteBigInt32(&buffer[ 4], 0, 0xe98b0001);    // ldu r12,lo16(L_fwrite$lazy_ptr)(r11)
-               OSWriteBigInt32(&buffer[ 8], 0, 0x7d8903a6);    // mtctr r12
-               OSWriteBigInt32(&buffer[12], 0, 0x4e800420);    // bctr
+       // create module table (one entry)
+       uint16_t numInits = 0;
+       uint16_t numTerms = 0;
+       std::vector<SegmentInfo*>& segmentInfos = fWriter.fSegmentInfos;
+       for (std::vector<SegmentInfo*>::iterator segit = segmentInfos.begin(); segit != segmentInfos.end(); ++segit) {
+               if ( strcmp((*segit)->fName, "__DATA") == 0 ) {
+                       std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
+                       for (std::vector<SectionInfo*>::iterator sectit = sectionInfos.begin(); sectit != sectionInfos.end(); ++sectit) {
+                               if ( strcmp((*sectit)->fSectionName, "__mod_init_func") == 0 ) 
+                                       numInits = (*sectit)->fSize / sizeof(typename A::P::uint_t);
+                               else if ( strcmp((*sectit)->fSectionName, "__mod_term_func") == 0 ) 
+                                       numTerms = (*sectit)->fSize / sizeof(typename A::P::uint_t);
+                       }
+               }
        }
-}
-
-template <>
-void StubAtom<ppc>::copyRawContent(uint8_t buffer[]) const
-{
-       if ( pic() ) {
-               OSWriteBigInt32(&buffer[ 0], 0, 0x7c0802a6);    //      mflr r0
-               OSWriteBigInt32(&buffer[ 4], 0, 0x429f0005);    //  bcl 20,31,Lpicbase
-               OSWriteBigInt32(&buffer[ 8], 0, 0x7d6802a6);    // Lpicbase: mflr r11
-               OSWriteBigInt32(&buffer[12], 0, 0x3d6b0000);    //      addis r11,r11,ha16(L_fwrite$lazy_ptr-Lpicbase)
-               OSWriteBigInt32(&buffer[16], 0, 0x7c0803a6);    //      mtlr r0
-               OSWriteBigInt32(&buffer[20], 0, 0x858b0000);    //      lwzu r12,lo16(L_fwrite$lazy_ptr-Lpicbase)(r11)
-               OSWriteBigInt32(&buffer[24], 0, 0x7d8903a6);    //  mtctr r12
-               OSWriteBigInt32(&buffer[28], 0, 0x4e800420);    //  bctr
+       macho_dylib_module<P>* module = (macho_dylib_module<P>*)&buffer[fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>)];
+       module->set_module_name(fModuleNameOffset);
+       module->set_iextdefsym(fWriter.fSymbolTableExportStartIndex);
+       module->set_nextdefsym(fWriter.fSymbolTableExportCount);
+       module->set_irefsym(0);
+       module->set_nrefsym(this->getReferencesCount());
+       module->set_ilocalsym(fWriter.fSymbolTableStabsStartIndex);
+       module->set_nlocalsym(fWriter.fSymbolTableStabsCount+fWriter.fSymbolTableLocalCount);
+       module->set_iextrel(0);
+       module->set_nextrel(fWriter.fExternalRelocs.size());
+       module->set_iinit_iterm(0,0);
+       module->set_ninit_nterm(numInits,numTerms);
+       module->set_objc_module_info_addr(0);   // Not used by ld_classic, and not used by objc runtime for many years
+       module->set_objc_module_info_size(0);   // Not used by ld_classic, and not used by objc runtime for many years
+       // create reference table
+       macho_dylib_reference<P>* ref = (macho_dylib_reference<P>*)((uint8_t*)module + sizeof(macho_dylib_module<P>));
+       for(uint32_t i=0; i < fWriter.fSymbolTableExportCount; ++i, ++ref) {
+               ref->set_isym(fWriter.fSymbolTableExportStartIndex+i);
+               ref->set_flags(REFERENCE_FLAG_DEFINED);
        }
-       else {
-               OSWriteBigInt32(&buffer[ 0], 0, 0x3d600000);    // lis r11,ha16(L_fwrite$lazy_ptr)
-               OSWriteBigInt32(&buffer[ 4], 0, 0x858b0000);    // lwzu r12,lo16(L_fwrite$lazy_ptr)(r11)
-               OSWriteBigInt32(&buffer[ 8], 0, 0x7d8903a6);    // mtctr r12
-               OSWriteBigInt32(&buffer[12], 0, 0x4e800420);    // bctr
+       for(uint32_t i=0; i < fWriter.fSymbolTableImportCount; ++i, ++ref) {
+               ref->set_isym(fWriter.fSymbolTableImportStartIndex+i);
+               std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fWriter.fStubsMap.find(fWriter.fImportedAtoms[i]);
+               if ( pos != fWriter.fStubsMap.end() )
+                       ref->set_flags(REFERENCE_FLAG_UNDEFINED_LAZY);
+               else
+                       ref->set_flags(REFERENCE_FLAG_UNDEFINED_NON_LAZY);
        }
 }
 
-template <>
-void StubAtom<x86>::copyRawContent(uint8_t buffer[]) const
+
+
+template <typename A>
+StringsLinkEditAtom<A>::StringsLinkEditAtom(Writer<A>& writer)
+       : LinkEditAtom<A>(writer), fCurrentBuffer(NULL), fCurrentBufferUsed(0)
 {
-       buffer[0] = 0xF4;
-       buffer[1] = 0xF4;
-       buffer[2] = 0xF4;
-       buffer[3] = 0xF4;
-       buffer[4] = 0xF4;
+       fCurrentBuffer = new char[kBufferSize];
+       // burn first byte of string pool (so zero is never a valid string offset)
+       fCurrentBuffer[fCurrentBufferUsed++] = ' ';
+       // make offset 1 always point to an empty string
+       fCurrentBuffer[fCurrentBufferUsed++] = '\0';
 }
 
-template <>
-void StubAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
+template <typename A>
+uint64_t StringsLinkEditAtom<A>::getSize() const
 {
-       buffer[0] = 0xFF;               // jmp *foo$lazy_pointer(%rip)
-       buffer[1] = 0x25;
-       buffer[2] = 0x00;
-       buffer[3] = 0x00;
-       buffer[4] = 0x00;
-       buffer[5] = 0x00;
+       // align size
+       return (kBufferSize * fFullBuffers.size() + fCurrentBufferUsed + sizeof(typename A::P::uint_t) - 1) & (-sizeof(typename A::P::uint_t));
 }
 
-// x86_64 stubs are 7 bytes and need no alignment
-template <>
-ObjectFile::Alignment StubAtom<x86_64>::getAlignment() const
+template <typename A>
+void StringsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
-       return 0;
+       uint64_t offset = 0;
+       for (unsigned int i=0; i < fFullBuffers.size(); ++i) {
+               memcpy(&buffer[offset], fFullBuffers[i], kBufferSize);
+               offset += kBufferSize;
+       }
+       memcpy(&buffer[offset], fCurrentBuffer, fCurrentBufferUsed);
+       // zero fill end to align
+       offset += fCurrentBufferUsed;
+       while ( (offset % sizeof(typename A::P::uint_t)) != 0 )
+               buffer[offset++] = 0;
 }
 
-template <>
-const char*    StubAtom<ppc>::getSectionName() const
+template <typename A>
+int32_t StringsLinkEditAtom<A>::add(const char* name)
 {
-       return ( pic() ? "__picsymbolstub1" : "__symbol_stub1");
+       int32_t offset = kBufferSize * fFullBuffers.size() + fCurrentBufferUsed;
+       int lenNeeded = strlcpy(&fCurrentBuffer[fCurrentBufferUsed], name, kBufferSize-fCurrentBufferUsed)+1;
+       if ( (fCurrentBufferUsed+lenNeeded) < kBufferSize ) {
+               fCurrentBufferUsed += lenNeeded;
+       }
+       else {
+               int copied = kBufferSize-fCurrentBufferUsed-1;
+               // change trailing '\0' that strlcpy added to real char
+               fCurrentBuffer[kBufferSize-1] = name[copied];
+               // alloc next buffer
+               fFullBuffers.push_back(fCurrentBuffer);
+               fCurrentBuffer = new char[kBufferSize];
+               fCurrentBufferUsed = 0;
+               // append rest of string
+               this->add(&name[copied+1]);
+       }
+       return offset;
 }
 
-template <>
-const char*    StubAtom<ppc64>::getSectionName() const
+
+template <typename A>
+int32_t StringsLinkEditAtom<A>::addUnique(const char* name)
 {
-       return ( pic() ? "__picsymbolstub1" : "__symbol_stub1");
+       StringToOffset::iterator pos = fUniqueStrings.find(name);
+       if ( pos != fUniqueStrings.end() ) {
+               return pos->second;
+       }
+       else {
+               int32_t offset = this->add(name);
+               fUniqueStrings[name] = offset;
+               return offset;
+       }
 }
 
-template <>
-const char*    StubAtom<x86>::getSectionName() const
+
+template <typename A>
+const char* StringsLinkEditAtom<A>::stringForIndex(int32_t index) const
 {
-       return "__jump_table";
+       int32_t currentBufferStartIndex = kBufferSize * fFullBuffers.size();
+       int32_t maxIndex = currentBufferStartIndex + fCurrentBufferUsed;
+       // check for out of bounds
+       if ( index > maxIndex )
+               return "";
+       // check for index in fCurrentBuffer
+       if ( index > currentBufferStartIndex )
+               return &fCurrentBuffer[index-currentBufferStartIndex];
+       // otherwise index is in a full buffer
+       uint32_t fullBufferIndex = index/kBufferSize;
+       return &fFullBuffers[fullBufferIndex][index-(kBufferSize*fullBufferIndex)];
 }
 
 
 
-template <>
-StubHelperAtom<x86_64>::StubHelperAtom(Writer<x86_64>& writer, ObjectFile::Atom& target, ObjectFile::Atom& lazyPointer)
- : WriterAtom<x86_64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
+template <typename A>
+BranchIslandAtom<A>::BranchIslandAtom(Writer<A>& writer, const char* name, int islandRegion, ObjectFile::Atom& target, uint32_t targetOffset)
+ : WriterAtom<A>(writer, Segment::fgTextSegment), fTarget(target), fTargetOffset(targetOffset)
 {
-       writer.fAllSynthesizedStubHelpers.push_back(this);
-
-       fReferences.push_back(new WriterReference<x86_64>(3, x86_64::kPCRel32, &lazyPointer));
-       fReferences.push_back(new WriterReference<x86_64>(8, x86_64::kPCRel32, writer.fDyldHelper));
-       if ( writer.fDyldHelper == NULL )
-               throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
+       char* buf = new char[strlen(name)+32];
+       if ( targetOffset == 0 ) {
+               if ( islandRegion == 0 )
+                       sprintf(buf, "%s$island", name);
+               else
+                       sprintf(buf, "%s$island_%d", name, islandRegion);
+       }
+       else {
+               sprintf(buf, "%s_plus_%d$island_%d", name, targetOffset, islandRegion);
+       }
+       fName = buf;
 }
 
+
 template <>
-uint64_t StubHelperAtom<x86_64>::getSize() const
+void BranchIslandAtom<ppc>::copyRawContent(uint8_t buffer[]) const
 {
-       return 12;
+       int64_t displacement = fTarget.getAddress() + fTargetOffset - this->getAddress();
+       int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC);
+       OSWriteBigInt32(buffer, 0, branchInstruction);
 }
 
 template <>
-void StubHelperAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
+void BranchIslandAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
 {
-       buffer[0]  = 0x4C;              // lea foo$lazy_ptr(%rip),%r11
-       buffer[1]  = 0x8D;
-       buffer[2]  = 0x1D;
-       buffer[3]  = 0x00;
-       buffer[4]  = 0x00;
-       buffer[5]  = 0x00;
-       buffer[6]  = 0x00;
-       buffer[7]  = 0xE9;              // jmp dyld_stub_binding_helper
-       buffer[8]  = 0x00;
-       buffer[9]  = 0x00;
-       buffer[10] = 0x00;
-       buffer[11] = 0x00;
+       int64_t displacement = fTarget.getAddress() + fTargetOffset - this->getAddress();
+       int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC);
+       OSWriteBigInt32(buffer, 0, branchInstruction);
 }
 
-template <typename A>
-const char* StubHelperAtom<A>::stubName(const char* name)
+template <>
+uint64_t BranchIslandAtom<ppc>::getSize() const
 {
-       char* buf;
-       asprintf(&buf, "%s$stubHelper", name);
-       return buf;
+       return 4;
 }
 
-
-// specialize lazy pointer for x86_64 to initially pointer to stub helper
 template <>
-LazyPointerAtom<x86_64>::LazyPointerAtom(Writer<x86_64>& writer, ObjectFile::Atom& target)
- : WriterAtom<x86_64>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target)
+uint64_t BranchIslandAtom<ppc64>::getSize() const
 {
-       writer.fAllSynthesizedLazyPointers.push_back(this);
-
-       StubHelperAtom<x86_64>* helper = new StubHelperAtom<x86_64>(writer, target, *this);
-       fReferences.push_back(new WriterReference<x86_64>(0, x86_64::kPointer, helper));
+       return 4;
 }
 
 
+
 template <typename A>
-LazyPointerAtom<A>::LazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target)
- : WriterAtom<A>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target)
+uint64_t SegmentSplitInfoLoadCommandsAtom<A>::getSize() const
 {
-       writer.fAllSynthesizedLazyPointers.push_back(this);
-
-       fReferences.push_back(new WriterReference<A>(0, A::kPointer, &target));
+       if ( fWriter.fSplitCodeToDataContentAtom->canEncode() )
+               return this->alignedSize(sizeof(macho_linkedit_data_command<P>));
+       else
+               return 0;       // a zero size causes the load command to be suppressed
 }
 
+template <typename A>
+void SegmentSplitInfoLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
+{
+       uint64_t size = this->getSize();
+       bzero(buffer, size);
+       macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)buffer;
+       cmd->set_cmd(LC_SEGMENT_SPLIT_INFO);
+       cmd->set_cmdsize(size);
+       cmd->set_dataoff(fWriter.fSplitCodeToDataContentAtom->getFileOffset());
+       cmd->set_datasize(fWriter.fSplitCodeToDataContentAtom->getSize());
+}
 
 
 template <typename A>
-const char* LazyPointerAtom<A>::lazyPointerName(const char* name)
+uint64_t SegmentSplitInfoContentAtom<A>::getSize() const
 {
-       char* buf;
-       asprintf(&buf, "%s$lazy_pointer", name);
-       return buf;
+       return fEncodedData.size();
 }
 
 template <typename A>
-void LazyPointerAtom<A>::copyRawContent(uint8_t buffer[]) const
+void SegmentSplitInfoContentAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
-       bzero(buffer, getSize());
+       memcpy(buffer, &fEncodedData[0], fEncodedData.size());
 }
 
 
 template <typename A>
-NonLazyPointerAtom<A>::NonLazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target)
- : WriterAtom<A>(writer, Segment::fgDataSegment), fName(nonlazyPointerName(target.getName())), fTarget(target)
+void SegmentSplitInfoContentAtom<A>::uleb128EncodeAddresses(const std::vector<SegmentSplitInfoContentAtom<A>::AtomAndOffset>& locations)
+{
+       pint_t addr = fWriter.fOptions.baseAddress();
+       for(typename std::vector<AtomAndOffset>::const_iterator it = locations.begin(); it != locations.end(); ++it) {
+               pint_t nextAddr = it->atom->getAddress() + it->offset;
+               //fprintf(stderr, "\t0x%0llX\n", (uint64_t)nextAddr);
+               uint64_t delta = nextAddr - addr;
+               if ( delta == 0 ) 
+                       throw "double split seg info for same address";
+               // uleb128 encode
+               uint8_t byte;
+               do {
+                       byte = delta & 0x7F;
+                       delta &= ~0x7F;
+                       if ( delta != 0 )
+                               byte |= 0x80;
+                       fEncodedData.push_back(byte);
+                       delta = delta >> 7;
+               } 
+               while( byte >= 0x80 );
+               addr = nextAddr;
+       }
+}
+
+template <typename A>
+void SegmentSplitInfoContentAtom<A>::encode()
 {
-       writer.fAllSynthesizedNonLazyPointers.push_back(this);
+       if ( ! fCantEncode ) {
+               fEncodedData.reserve(8192);
+               
+               if ( fKind1Locations.size() != 0 ) {
+                       fEncodedData.push_back(1);
+                       //fprintf(stderr, "type 1:\n");
+                       this->uleb128EncodeAddresses(fKind1Locations);
+                       fEncodedData.push_back(0);
+               }
+               
+               if ( fKind2Locations.size() != 0 ) {
+                       fEncodedData.push_back(2);
+                       //fprintf(stderr, "type 2:\n");
+                       this->uleb128EncodeAddresses(fKind2Locations);
+                       fEncodedData.push_back(0);
+               }
+               
+               if ( fKind3Locations.size() != 0 ) {
+                       fEncodedData.push_back(3);
+                       //fprintf(stderr, "type 3:\n");
+                       this->uleb128EncodeAddresses(fKind3Locations);
+                       fEncodedData.push_back(0);
+               }
+               
+               if ( fKind4Locations.size() != 0 ) {
+                       fEncodedData.push_back(4);
+                       //fprintf(stderr, "type 4:\n");
+                       this->uleb128EncodeAddresses(fKind4Locations);
+                       fEncodedData.push_back(0);
+               }
+               
+               // always add zero byte to mark end
+               fEncodedData.push_back(0);
 
-       fReferences.push_back(new WriterReference<A>(0, A::kPointer, &target));
+               // add zeros to end to align size
+               while ( (fEncodedData.size() % sizeof(pint_t)) != 0 )
+                       fEncodedData.push_back(0);
+       }
 }
 
+
 template <typename A>
-const char* NonLazyPointerAtom<A>::nonlazyPointerName(const char* name)
-{
-       char* buf;
-       asprintf(&buf, "%s$non_lazy_pointer", name);
-       return buf;
+ObjCInfoAtom<A>::ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcConstraint, bool objcReplacementClasses)
+       : WriterAtom<A>(writer, getInfoSegment())
+{
+       fContent[0] = 0;
+       uint32_t value = 0;
+       //      struct objc_image_info  {
+       //              uint32_t        version;        // initially 0
+       //              uint32_t        flags;
+       //      };
+       // #define OBJC_IMAGE_SUPPORTS_GC   2
+       // #define OBJC_IMAGE_GC_ONLY       4
+       //
+       if ( objcReplacementClasses ) 
+               value = 1;
+       switch ( objcConstraint ) {
+               case ObjectFile::Reader::kObjcNone:
+               case ObjectFile::Reader::kObjcRetainRelease:
+                       break;
+               case ObjectFile::Reader::kObjcRetainReleaseOrGC:
+                       value |= 2;
+                       break;
+               case ObjectFile::Reader::kObjcGC:
+                       value |= 6;
+                       break;
+       }
+       A::P::E::set32(fContent[1], value);
 }
 
 template <typename A>
-void NonLazyPointerAtom<A>::copyRawContent(uint8_t buffer[]) const
+void ObjCInfoAtom<A>::copyRawContent(uint8_t buffer[]) const
 {
-       bzero(buffer, getSize());
+       memcpy(buffer, &fContent[0], 8);
 }
 
 
+// objc info section is in a different segment and section for 32 vs 64 bit runtimes
+template <> const char* ObjCInfoAtom<ppc>::getSectionName()    const { return "__image_info"; }
+template <> const char* ObjCInfoAtom<x86>::getSectionName()    const { return "__image_info"; }
+template <> const char* ObjCInfoAtom<ppc64>::getSectionName()  const { return "__objc_imageinfo"; }
+template <> const char* ObjCInfoAtom<x86_64>::getSectionName() const { return "__objc_imageinfo"; }
+
+template <> Segment& ObjCInfoAtom<ppc>::getInfoSegment()    const { return Segment::fgObjCSegment; }
+template <> Segment& ObjCInfoAtom<x86>::getInfoSegment()    const { return Segment::fgObjCSegment; }
+template <> Segment& ObjCInfoAtom<ppc64>::getInfoSegment()  const { return Segment::fgDataSegment; }
+template <> Segment& ObjCInfoAtom<x86_64>::getInfoSegment() const { return Segment::fgDataSegment; }
+
+
 
 }; // namespace executable
 }; // namespace mach_o
index accdf559ee4d041609af7c45478fafad6008a277..ce9801a97b9bfac7cd981de87158d55e5c6521d9 100644 (file)
@@ -37,6 +37,10 @@ static bool                  sDumpContent= true;
 static bool                    sDumpStabs      = false;
 static bool                    sSort           = true;
 static cpu_type_t      sPreferredArch = CPU_TYPE_POWERPC64;
+static const char* sMatchName;
+static int sPrintRestrict;
+static int sPrintAlign;
+static int sPrintName;
 
 
  __attribute__((noreturn))
@@ -152,13 +156,18 @@ static void dumpStabs(std::vector<ObjectFile::Reader::Stab>* stabs)
 
 static void dumpAtom(ObjectFile::Atom* atom)
 {
+       if(sMatchName && strcmp(sMatchName, atom->getDisplayName()))
+               return;
+
        //printf("atom:    %p\n", atom);
        
        // name
-       printf("name:    %s\n",  atom->getDisplayName());
+       if(!sPrintRestrict || sPrintName)
+               printf("name:    %s\n",  atom->getDisplayName());
        
        // scope
-       switch ( atom->getScope() ) {
+       if(!sPrintRestrict)
+               switch ( atom->getScope() ) {
                case ObjectFile::Atom::scopeTranslationUnit:
                        printf("scope:   translation unit\n");
                        break;
@@ -170,10 +179,11 @@ static void dumpAtom(ObjectFile::Atom* atom)
                        break;
                default:
                        printf("scope:   unknown\n");
-       }
+               }
        
        // kind
-       switch ( atom->getDefinitionKind() ) {
+       if(!sPrintRestrict)
+               switch ( atom->getDefinitionKind() ) {
                case ObjectFile::Atom::kRegularDefinition:
                        printf("kind:     regular\n");
                        break;
@@ -189,36 +199,51 @@ static void dumpAtom(ObjectFile::Atom* atom)
                case ObjectFile::Atom::kExternalWeakDefinition:
                        printf("kind:     weak import\n");
                        break;
+               case ObjectFile::Atom::kAbsoluteSymbol:
+                       printf("kind:     absolute symbol\n");
+                       break;
                default:
-                       printf("scope:   unknown\n");
-       }
+                       printf("kind:   unknown\n");
+               }
 
        // segment and section
-       printf("section: %s,%s\n", atom->getSegment().getName(), atom->getSectionName());
+       if(!sPrintRestrict)
+               printf("section: %s,%s\n", atom->getSegment().getName(), atom->getSectionName());
 
        // attributes
-       printf("attrs:   ");
-       if ( atom->dontDeadStrip() )
-               printf("dont-dead-strip ");
-       if ( atom->isZeroFill() )
-               printf("zero-fill ");
-       printf("\n");
+       if(!sPrintRestrict) {
+               printf("attrs:   ");
+               if ( atom->dontDeadStrip() )
+                       printf("dont-dead-strip ");
+               if ( atom->isZeroFill() )
+                       printf("zero-fill ");
+               printf("\n");
+       }
        
        // size
-       printf("size:    0x%012llX\n", atom->getSize());
+       if(!sPrintRestrict)
+               printf("size:    0x%012llX\n", atom->getSize());
        
        // alignment
-       printf("align:    %u mod %u\n", atom->getAlignment().modulus, (1 << atom->getAlignment().powerOf2) );
+       if(!sPrintRestrict || sPrintAlign)
+               printf("align:    %u mod %u\n", atom->getAlignment().modulus, (1 << atom->getAlignment().powerOf2) );
 
        // content
-       if ( sDumpContent ) { 
+       if (!sPrintRestrict && sDumpContent ) { 
                uint64_t size = atom->getSize();
                if ( size < 4096 ) {
                        uint8_t content[size];
                        atom->copyRawContent(content);
                        printf("content: ");
                        if ( strcmp(atom->getSectionName(), "__cstring") == 0 ) {
-                               printf("\"%s\"", content);
+                               printf("\"");
+                               for (unsigned int i=0; i < size; ++i) {
+                                       if(content[i]<'!' || content[i]>=127)
+                                               printf("\\%o", content[i]);
+                                       else
+                                               printf("%c", content[i]);
+                               }
+                               printf("\"");
                        }
                        else {
                                for (unsigned int i=0; i < size; ++i)
@@ -229,30 +254,38 @@ static void dumpAtom(ObjectFile::Atom* atom)
        }
        
        // references
-       std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
-       const int refCount = references.size();
-       printf("references: (%u)\n", refCount);
-       for (int i=0; i < refCount; ++i) {
-               ObjectFile::Reference* ref = references[i];
-               printf("   %s\n", ref->getDescription());
+       if(!sPrintRestrict) {
+               std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
+               const int refCount = references.size();
+               printf("references: (%u)\n", refCount);
+               for (int i=0; i < refCount; ++i) {
+                       ObjectFile::Reference* ref = references[i];
+                       printf("   %s\n", ref->getDescription());
+               }
        }
        
        // line info
-       std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
-       if ( (lineInfo != NULL) && (lineInfo->size() > 0) ) {
-               printf("line info: (%lu)\n", lineInfo->size());
-               for (std::vector<ObjectFile::LineInfo>::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) {
-                       printf("   offset 0x%04X, line %d, file %s\n", it->atomOffset, it->lineNumber, it->fileName);
+       if(!sPrintRestrict) {
+               std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
+               if ( (lineInfo != NULL) && (lineInfo->size() > 0) ) {
+                       printf("line info: (%lu)\n", lineInfo->size());
+                       for (std::vector<ObjectFile::LineInfo>::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) {
+                               printf("   offset 0x%04X, line %d, file %s\n", it->atomOffset, it->lineNumber, it->fileName);
+                       }
                }
        }
 
+       if(!sPrintRestrict)
+               printf("\n");
 }
 
 struct AtomSorter
 {
-     bool operator()(ObjectFile::Atom* left, ObjectFile::Atom* right)
+     bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right)
      {
-          return (strcmp(left->getDisplayName(), right->getDisplayName()) < 0);
+               if ( left == right )
+                       return false;
+        return (strcmp(left->getDisplayName(), right->getDisplayName()) < 0);
      }
 };
 
@@ -274,10 +307,8 @@ static void dumpFile(ObjectFile::Reader* reader)
        if ( sSort )
                std::sort(sortedAtoms.begin(), sortedAtoms.end(), AtomSorter());
        
-       for(std::vector<ObjectFile::Atom*>::iterator it=sortedAtoms.begin(); it != sortedAtoms.end(); ++it) {
+       for(std::vector<ObjectFile::Atom*>::iterator it=sortedAtoms.begin(); it != sortedAtoms.end(); ++it)
                dumpAtom(*it);
-               printf("\n");
-       }
 }
 
 
@@ -296,7 +327,6 @@ static ObjectFile::Reader* createReader(const char* path, const ObjectFile::Read
                const struct fat_header* fh = (struct fat_header*)p;
                const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
                for (unsigned long i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
-                       fprintf(stderr, "archs[i].cputype = %X\n", archs[i].cputype);
                        if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)sPreferredArch ) {
                                p = p + OSSwapBigToHostInt32(archs[i].offset);
                                mh = (struct mach_header*)p;
@@ -304,19 +334,37 @@ static ObjectFile::Reader* createReader(const char* path, const ObjectFile::Read
                }
        }
        if ( mach_o::relocatable::Reader<x86>::validFile(p) )
-               return mach_o::relocatable::Reader<x86>::make(p, path, 0, options);
+               return new mach_o::relocatable::Reader<x86>::Reader(p, path, 0, options, 0);
        else if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
-               return mach_o::relocatable::Reader<ppc>::make(p, path, 0, options);
+               return new mach_o::relocatable::Reader<ppc>::Reader(p, path, 0, options, 0);
        else if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
-               return mach_o::relocatable::Reader<ppc64>::make(p, path, 0, options);
+               return new mach_o::relocatable::Reader<ppc64>::Reader(p, path, 0, options, 0);
        else if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
-               return mach_o::relocatable::Reader<x86_64>::make(p, path, 0, options);
+               return new mach_o::relocatable::Reader<x86_64>::Reader(p, path, 0, options, 0);
        throwf("not a mach-o object file: %s", path);
 }
 
+static
+void
+usage()
+{
+       fprintf(stderr, "ObjectDump options:\n"
+                       "\t-no_content\tdon't dump contents\n"
+                       "\t-stabs\t\tdump stabs\n"
+                       "\t-arch aaa\tonly dump info about arch aaa\n"
+                       "\t-only sym\tonly dump info about sym\n"
+                       "\t-align\t\tonly print alignment info\n"
+                       "\t-name\t\tonly print symbol names\n"
+               );
+}
 
 int main(int argc, const char* argv[])
 {
+       if(argc<2) {
+               usage();
+               return 0;
+       }
+
        ObjectFile::ReaderOptions options;
        try {
                for(int i=1; i < argc; ++i) {
@@ -332,7 +380,7 @@ int main(int argc, const char* argv[])
                                        sSort = false;
                                }
                                else if ( strcmp(arg, "-arch") == 0 ) {
-                                       const char* arch = argv[++i];
+                                       const char* arch = ++i<argc? argv[i]: "";
                                        if ( strcmp(arch, "ppc64") == 0 )
                                                sPreferredArch = CPU_TYPE_POWERPC64;
                                        else if ( strcmp(arch, "ppc") == 0 )
@@ -344,7 +392,19 @@ int main(int argc, const char* argv[])
                                        else 
                                                throwf("unknown architecture %s", arch);
                                }
+                               else if ( strcmp(arg, "-only") == 0 ) {
+                                       sMatchName = ++i<argc? argv[i]: NULL;
+                               }
+                               else if ( strcmp(arg, "-align") == 0 ) {
+                                       sPrintRestrict = true;
+                                       sPrintAlign = true;
+                               }
+                               else if ( strcmp(arg, "-name") == 0 ) {
+                                       sPrintRestrict = true;
+                                       sPrintName = true;
+                               }
                                else {
+                                       usage();
                                        throwf("unknown option: %s\n", arg);
                                }
                        }
@@ -361,6 +421,3 @@ int main(int argc, const char* argv[])
        
        return 0;
 }
-
-
-
index 69aeac62f871d0c09a31f16ee2ef8e18cacf4214..3f570c84ab0479c208ec83e63f8625d280d230eb 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -59,21 +59,40 @@ struct LineInfo
 class ReaderOptions
 {
 public:
-                                               ReaderOptions() : fFullyLoadArchives(false), fLoadObjcClassesInArchives(false), fFlatNamespace(false), 
-                                                                               fForFinalLinkedImage(false), fWhyLoad(false), fDebugInfoStripping(kDebugInfoFull),
-                                                                                fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceOutputFile(NULL) {}
+                                               ReaderOptions() : fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false), fLinkingMainExecutable(false), 
+                                                                               fForFinalLinkedImage(false), fForStatic(false), fForDyld(false), fMakeTentativeDefinitionsReal(false), 
+                                                                               fWhyLoad(false), fRootSafe(false), fSetuidSafe(false),fDebugInfoStripping(kDebugInfoFull),
+                                                                               fLogObjectFiles(false), fLogAllFiles(false),
+                                                                               fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), 
+                                                                               fTraceOutputFile(NULL), fVersionMin(kMinUnset) {}
        enum DebugInfoStripping { kDebugInfoNone, kDebugInfoMinimal, kDebugInfoFull };
+       enum VersionMin { kMinUnset, k10_1, k10_2, k10_3, k10_4, k10_5 };
 
-       bool                            fFullyLoadArchives;
-       bool                            fLoadObjcClassesInArchives;
-       bool                            fFlatNamespace;
-       bool                            fForFinalLinkedImage;
-       bool                            fWhyLoad;
-       DebugInfoStripping      fDebugInfoStripping;
-       bool                            fTraceDylibs;
-       bool                            fTraceIndirectDylibs;
-       bool                            fTraceArchives;
-       const char*                     fTraceOutputFile;
+       struct AliasPair {
+               const char*                     realName;
+               const char*                     alias;
+       };
+
+       bool                                    fFullyLoadArchives;
+       bool                                    fLoadAllObjcObjectsFromArchives;
+       bool                                    fFlatNamespace;
+       bool                                    fLinkingMainExecutable;
+       bool                                    fForFinalLinkedImage;
+       bool                                    fForStatic;
+       bool                                    fForDyld;
+       bool                                    fMakeTentativeDefinitionsReal;
+       bool                                    fWhyLoad;
+       bool                                    fRootSafe;
+       bool                                    fSetuidSafe;
+       DebugInfoStripping              fDebugInfoStripping;
+       bool                                    fLogObjectFiles;
+       bool                                    fLogAllFiles;
+       bool                                    fTraceDylibs;
+       bool                                    fTraceIndirectDylibs;
+       bool                                    fTraceArchives;
+       const char*                             fTraceOutputFile;
+       VersionMin                              fVersionMin;
+       std::vector<AliasPair>  fAliases;
 };
 
 
@@ -90,6 +109,16 @@ public:
                uint32_t        value;
                const char* string;
        };
+       enum ObjcConstraint { kObjcNone,  kObjcRetainRelease,  kObjcRetainReleaseOrGC,  kObjcGC };
+       enum CpuConstraint  { kCpuAny,  kCpuG3,  kCpuG4,  kCpuG5  };
+
+       class DylibHander
+       {
+       public:
+               virtual                         ~DylibHander()  {}
+               virtual Reader*         findDylib(const char* installPath, const char* fromPath) = 0;
+       };
+
 
        static Reader* createReader(const char* path, const ReaderOptions& options);
 
@@ -99,24 +128,31 @@ public:
        virtual std::vector<class Atom*>&       getAtoms() = 0;
        virtual std::vector<class Atom*>*       getJustInTimeAtomsFor(const char* name) = 0;
        virtual std::vector<Stab>*                      getStabs() = 0;
-                       unsigned int                            getSortOrder() const { return fSortOrder; }
-                       void                                            setSortOrder(unsigned int order) { fSortOrder=order; }
+       virtual ObjcConstraint                          getObjCConstraint()                     { return kObjcNone; }
+       virtual CpuConstraint                           getCpuConstraint()                      { return kCpuAny; }
+       virtual bool                                            objcReplacementClasses()        { return false; }
+
+       // For relocatable object files only
+       virtual bool                                            canScatterAtoms()                       { return true; }
+       virtual void                                            optimize(std::vector<ObjectFile::Atom*>&, std::vector<ObjectFile::Atom*>&, uint32_t)            { }
 
        // For Dynamic Libraries only
        virtual const char*                                     getInstallPath()                        { return NULL; }
        virtual uint32_t                                        getTimestamp()                          { return 0; }
        virtual uint32_t                                        getCurrentVersion()                     { return 0; }
        virtual uint32_t                                        getCompatibilityVersion()       { return 0; }
-       virtual std::vector<const char*>*       getDependentLibraryPaths()      { return NULL; }
-       virtual bool                                            reExports(Reader*)                      { return false; }
+       virtual void                                            processIndirectLibraries(DylibHander* handler)  { }
+       virtual void                                            setExplicitlyLinked()           { }
+       virtual bool                                            explicitlyLinked()                      { return false; }
+       virtual bool                                            implicitlyLinked()                      { return false; }
+       virtual bool                                            providedExportAtom()            { return false; }
        virtual const char*                                     parentUmbrella()                        { return NULL; }
        virtual std::vector<const char*>*       getAllowableClients()           { return NULL; }
 
+
 protected:
-                                                                               Reader() : fSortOrder(0) {}
+                                                                               Reader() {}
        virtual                                                         ~Reader() {}
-
-       unsigned int                                            fSortOrder;
 };
 
 class Segment
@@ -157,7 +193,7 @@ protected:
 struct Alignment 
 { 
                                Alignment(int p2, int m=0) : powerOf2(p2), modulus(m) {}
-       uint8_t         leadingZeros() const { return (modulus==0) ? powerOf2 : __builtin_clz(modulus); }
+       uint8_t         trailingZeros() const { return (modulus==0) ? powerOf2 : __builtin_ctz(modulus); }
        uint16_t        powerOf2;  
        uint16_t        modulus; 
 };
@@ -195,11 +231,16 @@ struct Alignment
 //     not-in                  Anonymous atoms such literal c-strings, or other compiler generated data
 //     in-never-strip  Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o)
 //
+// Ordinal:
+// When a reader is created it is given a base ordinal number.  All atoms created by the reader
+// should return a contiguous range of ordinal values that start at the base ordinal.  The ordinal
+// values are used by the linker to sort the atom graph when producing the output file. 
+//
 class Atom
 {
 public:
        enum Scope { scopeTranslationUnit, scopeLinkageUnit, scopeGlobal };
-       enum DefinitionKind { kRegularDefinition, kWeakDefinition, kTentativeDefinition, kExternalDefinition, kExternalWeakDefinition };
+       enum DefinitionKind { kRegularDefinition, kWeakDefinition, kTentativeDefinition, kExternalDefinition, kExternalWeakDefinition, kAbsoluteSymbol };
        enum SymbolTableInclusion { kSymbolTableNotIn, kSymbolTableIn, kSymbolTableInAndNeverStrip, kSymbolTableInAsAbsolute };
 
        virtual Reader*                                                 getFile() const = 0;
@@ -216,8 +257,8 @@ public:
        virtual bool                                                    mustRemainInSection() const = 0;
        virtual const char*                                             getSectionName() const = 0;
        virtual Segment&                                                getSegment() const = 0;
-       virtual bool                                                    requiresFollowOnAtom() const = 0;
        virtual Atom&                                                   getFollowOnAtom() const = 0;
+       virtual uint32_t                                                getOrdinal() const = 0;
        virtual std::vector<LineInfo>*                  getLineInfo() const = 0;
        virtual Alignment                                               getAlignment() const = 0;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const = 0;
@@ -225,43 +266,21 @@ public:
 
 
                        uint64_t                                                getSectionOffset() const        { return fSectionOffset; }
-                       uint64_t                                                getSegmentOffset() const        { return fSegmentOffset; }
                        uint64_t                                                getAddress() const      { return fSection->getBaseAddress() + fSectionOffset; }
-                       unsigned int                                    getSortOrder() const { return fSortOrder; }
                        class Section*                                  getSection() const { return fSection; }
 
-                       void                                                    setSegmentOffset(uint64_t offset) { fSegmentOffset = offset; }
-                       void                                                    setSectionOffset(uint64_t offset) { fSectionOffset = offset; }
-                       void                                                    setSection(class Section* sect) { fSection = sect; }
-                       unsigned int                                    setSortOrder(unsigned int order); // recursively sets follow-on atoms
+       virtual void                                                    setSectionOffset(uint64_t offset) { fSectionOffset = offset; }
+       virtual void                                                    setSection(class Section* sect) { fSection = sect; }
 
 protected:
-                                                                                       Atom() : fSegmentOffset(0), fSectionOffset(0), fSortOrder(0), fSection(NULL) {}
+                                                                                       Atom() :  fSectionOffset(0), fSection(NULL) {}
                virtual                                                         ~Atom() {}
 
-               uint64_t                                                        fSegmentOffset;
                uint64_t                                                        fSectionOffset;
-               unsigned int                                            fSortOrder;
                class Section*                                          fSection;
 };
 
 
-
-// recursively sets follow-on atoms
-inline unsigned int Atom::setSortOrder(unsigned int order)
-{
-       if ( this->requiresFollowOnAtom() ) {
-               fSortOrder = order;
-               return this->getFollowOnAtom().setSortOrder(order+1);
-       }
-       else {
-               fSortOrder = order;
-               return (order + 1);
-       }
-}
-
-
-
 //
 // A Reference is a directed edge to another Atom.  When an instruction in
 // the content of an Atom refers to another Atom, that is represented by a
@@ -287,15 +306,15 @@ inline unsigned int Atom::setSortOrder(unsigned int order)
 class Reference
 {
 public:
+       enum TargetBinding { kUnboundByName, kBoundDirectly, kBoundByName, kDontBind };
 
-       virtual bool                    isTargetUnbound() const = 0;
-       virtual bool                    isFromTargetUnbound() const = 0;
+       virtual TargetBinding   getTargetBinding() const = 0;
+       virtual TargetBinding   getFromTargetBinding() const = 0;
        virtual uint8_t                 getKind() const = 0;
        virtual uint64_t                getFixUpOffset() const = 0;
        virtual const char*             getTargetName() const = 0;
        virtual Atom&                   getTarget() const = 0;
        virtual uint64_t                getTargetOffset() const = 0;
-       virtual bool                    hasFromTarget() const = 0;
        virtual Atom&                   getFromTarget() const = 0;
        virtual const char*             getFromTargetName() const = 0;
        virtual uint64_t                getFromTargetOffset() const = 0;
diff --git a/src/OpaqueSection.hpp b/src/OpaqueSection.hpp
new file mode 100644 (file)
index 0000000..ccb3f2f
--- /dev/null
@@ -0,0 +1,198 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __OPAQUE_SECTION__
+#define __OPAQUE_SECTION__
+
+
+#include <vector>
+
+#include "ObjectFile.h"
+
+namespace opaque_section {
+
+
+class Segment : public ObjectFile::Segment
+{
+public:
+                                                               Segment(const char* name)               { fName = name; }
+       virtual const char*                     getName() const                                 { return fName; }
+       virtual bool                            isContentReadable() const               { return true; }
+       virtual bool                            isContentWritable() const               { return false; }
+       virtual bool                            isContentExecutable() const             { return (strcmp(fName, "__TEXT") == 0); }
+private:
+       const char*                                     fName;
+};
+
+
+class Reader : public ObjectFile::Reader 
+{
+public:
+                                                                                               Reader(const char* segmentName, const char* sectionName, const char* path, 
+                                                                                                       const uint8_t fileContent[], uint64_t fileLength, uint32_t ordinal, const char* symbolName=NULL);
+       virtual                                                                         ~Reader();
+       
+       void                                                                                    addSectionReference(uint8_t kind, uint64_t offsetInSection, const ObjectFile::Atom* targetAtom, 
+                                                                                                                                               uint64_t offsetInTarget, const ObjectFile::Atom* fromTargetAtom=NULL, uint64_t offsetInFromTarget=0);
+       
+       virtual const char*                                                             getPath()                                                               { return fPath; }
+       virtual time_t                                                                  getModificationTime()                                   { return 0; }
+       virtual DebugInfoKind                                                   getDebugInfoKind()                                              { return ObjectFile::Reader::kDebugInfoNone; }
+       virtual std::vector<class ObjectFile::Atom*>&   getAtoms()                                                              { return fAtoms; }
+       virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) { return NULL; }
+       virtual std::vector<Stab>*                                              getStabs()                                                              { return NULL; }
+
+private:
+       const char*                                                                             fPath;
+       std::vector<class ObjectFile::Atom*>                    fAtoms;
+};
+
+class Reference : public ObjectFile::Reference
+{
+public:
+                                                       Reference(uint8_t kind, uint64_t fixupOffset, const ObjectFile::Atom* target, uint64_t targetOffset,
+                                                                               const ObjectFile::Atom* fromTarget=NULL, uint64_t fromTargetOffset=0)
+                                                               : fFixUpOffset(fixupOffset), fTarget(target), fTargetOffset(targetOffset), fKind(kind), 
+                                                                       fFromTarget(fromTarget), fFromTargetOffset(fromTargetOffset)  {}
+       virtual                                 ~Reference() {}
+
+
+       virtual ObjectFile::Reference::TargetBinding    getTargetBinding() const        { return ObjectFile::Reference::kBoundDirectly; }
+       virtual ObjectFile::Reference::TargetBinding    getFromTargetBinding() const{ return ObjectFile::Reference::kDontBind; }
+       virtual uint8_t                                                                 getKind() const                         { return fKind; }
+       virtual uint64_t                                                                getFixUpOffset() const          { return fFixUpOffset; }
+       virtual const char*                                                             getTargetName() const           { return fTarget->getName(); }
+       virtual ObjectFile::Atom&                                               getTarget() const                       { return *((ObjectFile::Atom*)fTarget); }
+       virtual uint64_t                                                                getTargetOffset() const         { return fTargetOffset; }
+       virtual ObjectFile::Atom&                                               getFromTarget() const           { return *((ObjectFile::Atom*)fFromTarget); }
+       virtual const char*                                                             getFromTargetName() const       { return fFromTarget->getName();  }
+       virtual uint64_t                                                                getFromTargetOffset() const { return fFromTargetOffset; }
+       virtual void                                                                    setTarget(ObjectFile::Atom&, uint64_t offset) { throw "can't set target"; }
+       virtual void                                                                    setFromTarget(ObjectFile::Atom&) { throw "can't set from target"; }
+       virtual const char*                                                             getDescription() const          { return "opaque section reference"; }
+
+private:
+       uint64_t                                fFixUpOffset;
+       const ObjectFile::Atom* fTarget;
+       uint64_t                                fTargetOffset;
+       uint8_t                                 fKind;
+       const ObjectFile::Atom* fFromTarget;
+       uint64_t                                fFromTargetOffset;
+};
+
+
+class Atom : public ObjectFile::Atom {
+public:
+       virtual ObjectFile::Reader*                                     getFile() const                         { return &fOwner; }
+       virtual bool                                                            getTranslationUnitSource(const char** dir, const char** name) const { return false; }
+       virtual const char*                                                     getName() const                         { return fName; }
+       virtual const char*                                                     getDisplayName() const;
+       virtual Scope                                                           getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
+       virtual DefinitionKind                                          getDefinitionKind() const       { return kRegularDefinition; }
+       virtual SymbolTableInclusion                            getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
+       virtual bool                                                            dontDeadStrip() const           { return true; }
+       virtual bool                                                            isZeroFill() const                      { return false; }
+       virtual uint64_t                                                        getSize() const                         { return fFileLength; }
+       virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
+       virtual bool                                                            mustRemainInSection() const { return false; }
+       virtual const char*                                                     getSectionName() const          { return fSectionName; }
+       virtual Segment&                                                        getSegment() const                      { return fSegment; }
+       virtual ObjectFile::Atom&                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
+       virtual uint32_t                                                        getOrdinal() const                      { return fOrdinal; }
+       virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
+       virtual ObjectFile::Alignment                           getAlignment() const            { return ObjectFile::Alignment(4); }
+       virtual void                                                            copyRawContent(uint8_t buffer[]) const;
+
+       virtual void                                                            setScope(Scope)                         { }
+
+protected:
+       friend class Reader;
+       
+                                                                                       Atom(Reader& owner, Segment& segment, const char* sectionName, 
+                                                                                               const uint8_t fileContent[], uint64_t fileLength, uint32_t ordinal, const char* symbolName);
+       virtual                                                                 ~Atom() {}
+       
+       Reader&                                                                 fOwner;
+       Segment&                                                                fSegment;
+       const char*                                                             fName;
+       const char*                                                             fSectionName;
+       const uint8_t*                                                  fFileContent;
+       uint32_t                                                                fOrdinal;
+       uint64_t                                                                fFileLength;
+       std::vector<ObjectFile::Reference*>             fReferences;
+};
+
+
+       
+Atom::Atom(Reader& owner, Segment& segment, const char* sectionName, const uint8_t fileContent[], uint64_t fileLength, uint32_t ordinal, const char* symbolName) 
+       : fOwner(owner), fSegment(segment), fSectionName(sectionName), fFileContent(fileContent), fOrdinal(ordinal), fFileLength(fileLength) 
+{ 
+       if ( symbolName != NULL )
+               fName = strdup(symbolName);
+       else
+               asprintf((char**)&fName, "__section$%s%s", segment.getName(), sectionName);
+}
+
+
+Reader::Reader(const char* segmentName, const char* sectionName, const char* path, const uint8_t fileContent[], 
+                       uint64_t fileLength, uint32_t ordinal, const char* symbolName)
+ : fPath(path)
+{
+       fAtoms.push_back(new Atom(*this, *(new Segment(segmentName)), strdup(sectionName), fileContent, fileLength, ordinal, symbolName));
+}
+
+Reader::~Reader()
+{
+}
+
+void Reader::addSectionReference(uint8_t kind, uint64_t offsetInSection, const ObjectFile::Atom* targetAtom, 
+                                                               uint64_t offsetInTarget, const ObjectFile::Atom* fromTargetAtom, uint64_t offsetInFromTarget)
+{
+       fAtoms[0]->getReferences().push_back(new Reference(kind, offsetInSection, targetAtom, offsetInTarget, fromTargetAtom, offsetInFromTarget));
+}
+
+
+const char*     Atom::getDisplayName() const
+{
+       static char name[64];
+       sprintf(name, "opaque section %s %s", fSegment.getName(), fSectionName);
+       return name;
+}
+
+
+void Atom::copyRawContent(uint8_t buffer[]) const
+{
+       memcpy(buffer, fFileContent, fFileLength);
+}
+
+
+
+};
+
+
+
+#endif // __OPAQUE_SECTION__
+
+
+
index 1eb135b0d219cb0480fe591fb0dc6baf6cbee305..50bd636213e3d26322e98c81b543ad14bae94634 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -25,6 +25,7 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <mach/vm_prot.h>
 #include <math.h>
 #include <fcntl.h>
 #include <vector>
@@ -44,22 +45,27 @@ void throwf(const char* format, ...)
 }
 
 Options::Options(int argc, const char* argv[])
-       : fOutputFile("a.out"), fArchitecture(0), fOutputKind(kDynamicExecutable), fBindAtLoad(false),
-         fStripLocalSymbols(false),  fKeepPrivateExterns(false),
-         fInterposable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false), fDeadStrip(kDeadStripOff),
-         fVersionMin(kMinUnset),fNameSpace(kTwoLevelNameSpace),
-         fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fEntryName("start"), fBaseAddress(0),
+       : fOutputFile("a.out"), fArchitecture(0), fOutputKind(kDynamicExecutable), fPrebind(false), fBindAtLoad(false),
+         fKeepPrivateExterns(false),
+         fInterposable(false), fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fForceSubtypeAll(false), 
+         fDeadStrip(kDeadStripOff), fNameSpace(kTwoLevelNameSpace),
+         fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName("start"), fBaseAddress(0),
+         fBaseWritableAddress(0), fSplitSegs(false),
          fExportMode(kExportDefault), fLibrarySearchMode(kSearchAllDirsForDylibsThenAllDirsForArchives),
-         fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(false), fPICTreatment(kError),
-         fWeakReferenceMismatchTreatment(kWeakReferenceMismatchError), fMultiplyDefinedDynamic(kWarning),
-         fMultiplyDefinedUnused(kSuppress), fWarnOnMultiplyDefined(false), fClientName(NULL),
-         fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL), fBundleLoader(NULL),
-         fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false), fMinimumHeaderPad(0),
-         fCommonsMode(kCommonsIgnoreDylibs), fWarnCommons(false), fVerbose(false), fKeepRelocations(false),
-         fEmitUUID(true),fWarnStabs(false),
+         fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(false), 
+         fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
+         fClientName(NULL),
+         fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
+         fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL), 
+         fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fExecutableStack(false), fMinimumHeaderPad(32),
+         fCommonsMode(kCommonsIgnoreDylibs),  fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false), 
+         fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
          fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
-         fMakeTentativeDefinitionsReal(false)
+         fSharedRegionEligible(false), fPrintOrderFileStatistics(false),  
+         fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
+         fDeadStripDylibs(false), fSuppressWarnings(false), fSaveTempFiles(false)
 {
+       this->checkForClassic(argc, argv);
        this->parsePreCommandLineEnvironmentSettings();
        this->parse(argc, argv);
        this->parsePostCommandLineEnvironmentSettings();
@@ -96,11 +102,6 @@ Options::OutputKind Options::outputKind()
        return fOutputKind;
 }
 
-bool Options::stripLocalSymbols()
-{
-       return fStripLocalSymbols;
-}
-
 bool Options::bindAtLoad()
 {
        return fBindAtLoad;
@@ -125,6 +126,8 @@ const char* Options::installPath()
 {
        if ( fDylibInstallName != NULL )
                return fDylibInstallName;
+       else if ( fFinalName != NULL )
+               return fFinalName;
        else
                return fOutputFile;
 }
@@ -159,6 +162,11 @@ bool Options::interposable()
        return fInterposable;
 }
 
+bool Options::needsModuleTable()
+{
+       return fNeedsModuleTable;
+}
+
 bool Options::ignoreOtherArchInputFiles()
 {
        return fIgnoreOtherArchFiles;
@@ -184,9 +192,9 @@ Options::UndefinedTreatment Options::undefinedTreatment()
        return fUndefinedTreatment;
 }
 
-Options::VersionMin Options::macosxVersionMin()
+ObjectFile::ReaderOptions::VersionMin Options::macosxVersionMin()
 {
-       return fVersionMin;
+       return fReaderOptions.fVersionMin;
 }
 
 Options::WeakReferenceMismatchTreatment        Options::weakReferenceMismatchTreatment()
@@ -194,21 +202,6 @@ Options::WeakReferenceMismatchTreatment    Options::weakReferenceMismatchTreatment(
        return fWeakReferenceMismatchTreatment;
 }
 
-Options::Treatment Options::multipleDefinitionsInDylibs()
-{
-       return fMultiplyDefinedDynamic;
-}
-
-Options::Treatment Options::overridingDefinitionInDependentDylib()
-{
-       return fMultiplyDefinedUnused;
-}
-
-bool Options::warnOnMultipleDefinitionsInObjectFiles()
-{
-       return fWarnOnMultiplyDefined;
-}
-
 const char* Options::umbrellaName()
 {
        return fUmbrellaName;
@@ -259,10 +252,6 @@ bool Options::printWhyLive(const char* symbolName)
        return ( fWhyLive.find(symbolName) != fWhyLive.end() );
 }
 
-std::vector<const char*>& Options::traceSymbols()
-{
-       return fTraceSymbols;
-}
 
 const char*    Options::initFunctionName()
 {
@@ -282,7 +271,7 @@ bool Options::hasExportRestrictList()
 bool Options::allGlobalsAreDeadStripRoots()
 {
        // -exported_symbols_list means globals are not exported by default
-       if ( fExportMode == kExportSome ) 
+       if ( fExportMode == kExportSome )
                return false;
        //
        switch ( fOutputKind ) {
@@ -329,11 +318,6 @@ bool Options::keepRelocations()
        return fKeepRelocations;
 }
 
-bool Options::emitUUID()
-{
-       return fEmitUUID;
-}
-
 bool Options::warnStabs()
 {
        return fWarnStabs;
@@ -353,15 +337,30 @@ bool Options::shouldExport(const char* symbolName)
 {
        switch (fExportMode) {
                case kExportSome:
-                       return ( fExportSymbols.find(symbolName) != fExportSymbols.end() );
+                       return fExportSymbols.contains(symbolName);
                case kDontExportSome:
-                       return ( fDontExportSymbols.find(symbolName) == fDontExportSymbols.end() );
+                       return ! fDontExportSymbols.contains(symbolName);
                case kExportDefault:
                        return true;
        }
        throw "internal error";
 }
 
+bool Options::keepLocalSymbol(const char* symbolName)
+{
+       switch (fLocalSymbolHandling) {
+               case kLocalSymbolsAll:
+                       return true;
+               case kLocalSymbolsNone:
+                       return false;
+               case kLocalSymbolsSelectiveInclude:
+                       return fLocalSymbolsIncluded.contains(symbolName);
+               case kLocalSymbolsSelectiveExclude:
+                       return ! fLocalSymbolsExcluded.contains(symbolName);
+       }
+       throw "internal error";
+}
+
 void Options::parseArch(const char* architecture)
 {
        if ( architecture == NULL )
@@ -429,6 +428,13 @@ Options::FileInfo Options::findLibrary(const char* rootName)
                                                if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
                                                        return result;
                                        }
+                                       for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
+                                                it != fLibrarySearchPaths.end();
+                                                it++) {
+                                               const char* dir = *it;
+                                               if ( checkForFile("%s/lib%s.so", dir, rootName, result) )
+                                                       return result;
+                                       }
                                }
                                // next look in all directories for just for archives
                                for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
@@ -448,6 +454,8 @@ Options::FileInfo Options::findLibrary(const char* rootName)
                                        const char* dir = *it;
                                        if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
                                                return result;
+                                       if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
+                                               return result;
                                        if ( checkForFile("%s/lib%s.a", dir, rootName, result) )
                                                return result;
                                }
@@ -460,7 +468,7 @@ Options::FileInfo Options::findLibrary(const char* rootName)
 Options::FileInfo Options::findFramework(const char* frameworkName)
 {
        if ( frameworkName == NULL )
-               throw "-frameowrk missing next argument";
+               throw "-framework missing next argument";
        char temp[strlen(frameworkName)+1];
        strcpy(temp, frameworkName);
        const char* name = temp;
@@ -509,7 +517,7 @@ Options::FileInfo Options::findFramework(const char* rootName, const char* suffi
                }
        }
        // try without suffix
-       if ( suffix != NULL ) 
+       if ( suffix != NULL )
                return findFramework(rootName, NULL);
        else
                throwf("framework not found %s", rootName);
@@ -569,6 +577,114 @@ Options::FileInfo Options::findFile(const char* path)
        throwf("file not found: %s", path);
 }
 
+Options::FileInfo Options::findFileUsingPaths(const char* path)
+{
+       FileInfo result;
+
+       const char* lastSlash = strrchr(path, '/');
+       const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
+
+       // Is this in a framework?
+       // /path/Foo.framework/Foo                                                      ==> true (Foo)
+       // /path/Foo.framework/Frameworks/Bar.framework/Bar ==> true (Bar)
+       // /path/Foo.framework/Resources/Bar                            ==> false
+       bool isFramework = false;
+       if ( lastSlash != NULL ) {
+               char frameworkDir[strlen(leafName) + 20];
+               strcpy(frameworkDir, "/");
+               strcat(frameworkDir, leafName);
+               strcat(frameworkDir, ".framework/");
+               if ( strstr(path, frameworkDir) != NULL )
+                       isFramework = true;
+       }
+       
+       // These are abbreviated versions of the routines findFramework and findLibrary above
+       // because we already know the final name of the file that we're looking for and so
+       // don't need to try variations, just paths. We do need to add the additional bits
+       // onto the framework path though.
+       if ( isFramework ) {
+               for (std::vector<const char*>::iterator it = fFrameworkSearchPaths.begin();
+                        it != fFrameworkSearchPaths.end();
+                        it++) {
+                       const char* dir = *it;
+                       char possiblePath[PATH_MAX];
+                       strcpy(possiblePath, dir);
+                       strcat(possiblePath, "/");
+                       strcat(possiblePath, leafName);
+                       strcat(possiblePath, ".framework");
+
+                       //fprintf(stderr,"Finding Framework: %s/%s, leafName=%s\n", possiblePath, leafName, leafName);
+                       if ( checkForFile("%s/%s", possiblePath, leafName, result) )
+                               return result;
+               }
+       } 
+       else {
+               for (std::vector<const char*>::iterator it = fLibrarySearchPaths.begin();
+                        it != fLibrarySearchPaths.end();
+                        it++) {
+                       const char* dir = *it;
+                       //fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
+                       if ( checkForFile("%s/%s", dir, leafName, result) )
+                               return result;
+               }
+       }
+
+       // If we didn't find it fall back to findFile.
+       return findFile(path);
+}
+
+void Options::parseSegAddrTable(const char* segAddrPath, const char* installPath)
+{
+       FILE* file = fopen(segAddrPath, "r");
+       if ( file == NULL ) {
+               fprintf(stderr, "ld64: warning, -seg_addr_table file cannot be read: %s\n", segAddrPath);
+               return;
+       }
+       
+       char path[PATH_MAX];
+       uint64_t firstColumAddress = 0;
+       uint64_t secondColumAddress = 0;
+       bool hasSecondColumn = false;
+       while ( fgets(path, PATH_MAX, file) != NULL ) {
+               path[PATH_MAX-1] = '\0';
+               char* eol = strchr(path, '\n');
+               if ( eol != NULL )
+                       *eol = '\0';
+               // ignore lines not starting with 0x number
+               if ( (path[0] == '0') && (path[1] == 'x') ) {
+                       char* p;
+                       firstColumAddress = strtoull(path, &p, 16);
+                       while ( isspace(*p) )
+                               ++p;
+                       // see if second column is a number
+                       if ( (p[0] == '0') && (p[1] == 'x') ) {
+                               secondColumAddress = strtoull(p, &p, 16);
+                               hasSecondColumn = true;
+                               while ( isspace(*p) )
+                                       ++p;
+                       }
+                       while ( isspace(*p) )
+                               ++p;
+                       if ( p[0] == '/' ) {
+                               // remove any trailing whitespace
+                               for(char* end = eol-1; (end > p) && isspace(*end); --end)
+                                       *end = '\0';
+                               // see if this line is for the dylib being linked
+                               if ( strcmp(p, installPath) == 0 ) {
+                                       fBaseAddress = firstColumAddress;
+                                       if ( hasSecondColumn ) {
+                                               fBaseWritableAddress = secondColumAddress;
+                                               fSplitSegs = true;
+                                       }
+                                       break; // out of while loop
+                               }
+                       }
+               }
+       }
+
+       fclose(file);
+}
 
 void Options::loadFileList(const char* fileOfPaths)
 {
@@ -592,7 +708,7 @@ void Options::loadFileList(const char* fileOfPaths)
        }
 
        char path[PATH_MAX];
-       while ( fgets(path, 1024, file) != NULL ) {
+       while ( fgets(path, PATH_MAX, file) != NULL ) {
                path[PATH_MAX-1] = '\0';
                char* eol = strchr(path, '\n');
                if ( eol != NULL )
@@ -611,8 +727,97 @@ void Options::loadFileList(const char* fileOfPaths)
        fclose(file);
 }
 
+bool Options::SetWithWildcards::hasWildCards(const char* symbol)
+{
+       // an exported symbol name containing *, ?, or [ requires wildcard matching
+       return ( strpbrk(symbol, "*?[") != NULL );
+}
+
+void Options::SetWithWildcards::insert(const char* symbol)
+{
+       if ( hasWildCards(symbol) )
+               fWildCard.push_back(symbol);
+       else
+               fRegular.insert(symbol);
+}
+
+bool Options::SetWithWildcards::contains(const char* symbol)
+{
+       // first look at hash table on non-wildcard symbols
+       if ( fRegular.find(symbol) != fRegular.end() )
+               return true;
+       // next walk list of wild card symbols looking for a match
+       for(std::vector<const char*>::iterator it = fWildCard.begin(); it != fWildCard.end(); ++it) {
+               if ( wildCardMatch(*it, symbol) )
+                       return true;
+       }
+       return false;
+}
+
+
+bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c)
+{
+       ++p; // find end
+       const char* b = p;
+       while ( *p != '\0' ) {
+               if ( *p == ']') {
+                       const char* e = p;
+                       // found beginining [ and ending ]
+                       unsigned char last = '\0';
+                       for ( const char* s = b; s < e; ++s ) {
+                               if ( *s == '-' ) {
+                                       unsigned char next = *(++s);
+                                       if ( (last <= c) && (c <= next) )
+                                               return true;
+                                       ++s;
+                               }
+                               else {
+                                       if ( *s == c )
+                                               return true;
+                                       last = *s;
+                               }
+                       }
+                       return false;
+               }
+               ++p;
+       }
+       return false;
+}
+
+bool Options::SetWithWildcards::wildCardMatch(const char* pattern, const char* symbol)
+{
+       const char* s = symbol;
+       for (const char* p = pattern; *p != '\0'; ++p) {
+               switch ( *p ) {
+                       case '*':
+                               if ( p[1] == '\0' )
+                                       return true;
+                               for (const char* t = s; *t != '\0'; ++t) {
+                                       if ( wildCardMatch(&p[1], t) )
+                                               return true;
+                               }
+                               return false;
+                       case '?':
+                               if ( *s == '\0' )
+                                       return false;
+                               ++s;
+                               break;
+                       case '[':
+                               if ( ! inCharRange(p, *s) )
+                                       return false;
+                               ++s;
+                               break;
+                       default:
+                               if ( *s != *p )
+                                       return false;
+                               ++s;
+               }
+       }
+       return (*s == '\0');
+}
+
 
-void Options::loadExportFile(const char* fileOfExports, const char* option, NameSet& set)
+void Options::loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set)
 {
        // read in whole file
        int fd = ::open(fileOfExports, O_RDONLY, 0);
@@ -645,7 +850,7 @@ void Options::loadExportFile(const char* fileOfExports, const char* option, Name
                        }
                        break;
                case inSymbol:
-                       if ( *s == '\n' ) {
+                       if ( (*s == '\n') || (*s == '\r') ) {
                                *s = '\0';
                                // removing any trailing spaces
                                char* last = s-1;
@@ -659,7 +864,7 @@ void Options::loadExportFile(const char* fileOfExports, const char* option, Name
                        }
                        break;
                case inComment:
-                       if ( *s == '\n' )
+                       if ( (*s == '\n') || (*s == '\r') )
                                state = lineStart;
                        break;
                }
@@ -682,6 +887,97 @@ void Options::loadExportFile(const char* fileOfExports, const char* option, Name
        // Note: we do not free() the malloc buffer, because the strings are used by the export-set hash table
 }
 
+void Options::parseAliasFile(const char* fileOfAliases)
+{
+       // read in whole file
+       int fd = ::open(fileOfAliases, O_RDONLY, 0);
+       if ( fd == -1 )
+               throwf("can't open alias file: %s", fileOfAliases);
+       struct stat stat_buf;
+       ::fstat(fd, &stat_buf);
+       char* p = (char*)malloc(stat_buf.st_size+1);
+       if ( p == NULL )
+               throwf("can't process alias file: %s", fileOfAliases);
+
+       if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
+               throwf("can't read alias file: %s", fileOfAliases);
+       p[stat_buf.st_size] = '\n';
+       ::close(fd);
+
+       // parse into symbols and add to fAliases
+       ObjectFile::ReaderOptions::AliasPair pair;
+       char * const end = &p[stat_buf.st_size+1];
+       enum { lineStart, inRealName, inBetween, inAliasName, inComment } state = lineStart;
+       int lineNumber = 1;
+       for (char* s = p; s < end; ++s ) {
+               switch ( state ) {
+               case lineStart:
+                       if ( *s =='#' ) {
+                               state = inComment;
+                       }
+                       else if ( !isspace(*s) ) {
+                               state = inRealName;
+                               pair.realName = s;
+                       }
+                       break;
+               case inRealName:
+                       if ( *s == '\n' ) {
+                               fprintf(stderr, "ld64 warning: line needs two symbols but has only one at line #%d in \"%s\"\n", lineNumber, fileOfAliases);
+                               ++lineNumber;
+                               state = lineStart;
+                       }
+                       else if ( isspace(*s) ) {
+                               *s = '\0';
+                               state = inBetween;
+                       }
+                       break;
+               case inBetween:
+                       if ( *s == '\n' ) {
+                               fprintf(stderr, "ld64 warning: line needs two symbols but has only one at line #%d in \"%s\"\n", lineNumber, fileOfAliases);
+                               ++lineNumber;
+                               state = lineStart;
+                       }
+                       else if ( ! isspace(*s) ) {
+                               state = inAliasName;
+                               pair.alias = s;
+                       }
+                       break;
+               case inAliasName:
+                       if ( *s =='#' ) {
+                               *s = '\0';
+                               // removing any trailing spaces
+                               char* last = s-1;
+                               while ( isspace(*last) ) {
+                                       *last = '\0';
+                                       --last;
+                               }
+                               fReaderOptions.fAliases.push_back(pair);
+                               state = inComment;
+                       }
+                       else if ( *s == '\n' ) {
+                               *s = '\0';
+                               // removing any trailing spaces
+                               char* last = s-1;
+                               while ( isspace(*last) ) {
+                                       *last = '\0';
+                                       --last;
+                               }
+                               fReaderOptions.fAliases.push_back(pair);
+                               state = lineStart;
+                       }
+                       break;
+               case inComment:
+                       if ( *s == '\n' )
+                               state = lineStart;
+                       break;
+               }
+       }
+
+       // Note: we do not free() the malloc buffer, because the strings therein are used by fAliases
+}
+
+
+
 void Options::setUndefinedTreatment(const char* treatment)
 {
        if ( treatment == NULL )
@@ -724,19 +1020,19 @@ void Options::setVersionMin(const char* version)
                switch ( num ) {
                        case 0:
                        case 1:
-                               fVersionMin = k10_1;
+                               fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_1;
                                break;
                        case 2:
-                               fVersionMin = k10_2;
+                               fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_2;
                                break;
                        case 3:
-                               fVersionMin = k10_3;
+                               fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_3;
                                break;
                        case 4:
-                               fVersionMin = k10_4;
+                               fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
                                break;
                        default:
-                               fVersionMin = k10_5;
+                               fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_5;
                                break;
                        }
        }
@@ -775,10 +1071,21 @@ Options::CommonsMode Options::parseCommonsTreatment(const char* mode)
                throw "invalid option to -commons [ ignore_dylibs | use_dylibs | error ]";
 }
 
-void Options::setDylibInstallNameOverride(const char* paths)
+void Options::addDylibOverride(const char* paths)
 {
-
-
+       if ( paths == NULL )
+               throw "-dylib_file must followed by two colon separated paths";
+       const char* colon = strchr(paths, ':');
+       if ( colon == NULL )
+               throw "-dylib_file must followed by two colon separated paths";
+       int len = colon-paths;
+       char* target = new char[len+2];
+       strncpy(target, paths, len);
+       target[len] = '\0';
+       DylibOverride entry;
+       entry.installName = target;
+       entry.useInstead = &colon[1];   
+       fDylibOverrides.push_back(entry);
 }
 
 uint64_t Options::parseAddress(const char* addr)
@@ -788,6 +1095,31 @@ uint64_t Options::parseAddress(const char* addr)
        return result;
 }
 
+uint32_t Options::parseProtection(const char* prot)
+{
+       uint32_t result = 0;
+       for(const char* p = prot; *p != '\0'; ++p) {
+               switch(tolower(*p)) {
+                       case 'r':
+                               result |= VM_PROT_READ;
+                               break;
+                       case 'w':
+                               result |= VM_PROT_WRITE;
+                               break;
+                       case 'x':
+                               result |= VM_PROT_EXECUTE;
+                               break;
+                       case '-':
+                               break;
+                       default:
+                               throwf("unknown -segprot lettter in %s", prot);
+               }
+       }
+       return result;
+}
+
+
+
 //
 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
 //
@@ -811,9 +1143,198 @@ uint32_t Options::parseVersionNumber(const char* versionString)
        return (x << 16) | ( y << 8 ) | z;
 }
 
+static const char* cstringSymbolName(const char* orderFileString)
+{
+       char* result;
+       asprintf(&result, "cstring=%s", orderFileString);
+       // convert escaped characters
+       char* d = result;
+       for(const char* s=result; *s != '\0'; ++s, ++d) {
+               if ( *s == '\\' ) {
+                       ++s;
+                       switch ( *s ) {
+                               case 'n':
+                                       *d = '\n';
+                                       break;
+                               case 't':
+                                       *d = '\t';
+                                       break;
+                               case 'v':
+                                       *d = '\v';
+                                       break;
+                               case 'b':
+                                       *d = '\b';
+                                       break;
+                               case 'r':
+                                       *d = '\r';
+                                       break;
+                               case 'f':
+                                       *d = '\f';
+                                       break;
+                               case 'a':
+                                       *d = '\a';
+                                       break;
+                               case '\\':
+                                       *d = '\\';
+                                       break;
+                               case '?':
+                                       *d = '\?';
+                                       break;
+                               case '\'':
+                                       *d = '\r';
+                                       break;
+                               case '\"':
+                                       *d = '\"';
+                                       break;
+                               case 'x':
+                                       // hexadecimal value of char
+                                       {
+                                               ++s;
+                                               char value = 0;
+                                               while ( isxdigit(*s) ) {
+                                                       value *= 16;
+                                                       if ( isdigit(*s) )
+                                                               value += (*s-'0');
+                                                       else
+                                                               value += ((toupper(*s)-'A') + 10);
+                                                       ++s;
+                                               }
+                                               *d = value;
+                                       }
+                                       break;
+                               default:
+                                       if ( isdigit(*s) ) {
+                                               // octal value of char
+                                               char value = 0;
+                                               while ( isdigit(*s) ) {
+                                                       value = (value << 3) + (*s-'0');
+                                                       ++s;
+                                               }
+                                               *d = value;
+                                       }
+                       }
+               }
+               else {
+                       *d = *s;
+               }
+       }
+       *d = '\0';
+       return result;
+}
+
+void Options::parseOrderFile(const char* path, bool cstring)
+{
+       // read in whole file
+       int fd = ::open(path, O_RDONLY, 0);
+       if ( fd == -1 )
+               throwf("can't open order file: %s", path);
+       struct stat stat_buf;
+       ::fstat(fd, &stat_buf);
+       char* p = (char*)malloc(stat_buf.st_size+1);
+       if ( p == NULL )
+               throwf("can't process order file: %s", path);
+       if ( read(fd, p, stat_buf.st_size) != stat_buf.st_size )
+               throwf("can't read order file: %s", path);
+       ::close(fd);
+       p[stat_buf.st_size] = '\n';
+
+       // parse into vector of pairs
+       char * const end = &p[stat_buf.st_size+1];
+       enum { lineStart, inSymbol, inComment } state = lineStart;
+       char* symbolStart = NULL;
+       for (char* s = p; s < end; ++s ) {
+               switch ( state ) {
+               case lineStart:
+                       if ( *s =='#' ) {
+                               state = inComment;
+                       }
+                       else if ( !isspace(*s) || cstring ) {
+                               state = inSymbol;
+                               symbolStart = s;
+                       }
+                       break;
+               case inSymbol:
+                       if ( (*s == '\n') || (!cstring && (*s == '#')) ) {
+                               bool wasComment = (*s == '#');
+                               *s = '\0';
+                               // removing any trailing spaces
+                               char* last = s-1;
+                               while ( isspace(*last) ) {
+                                       *last = '\0';
+                                       --last;
+                               }
+                               if ( strncmp(symbolStart, "ppc:", 4) == 0 ) {
+                                       if ( fArchitecture == CPU_TYPE_POWERPC )
+                                               symbolStart = &symbolStart[4];
+                                       else
+                                               symbolStart = NULL;
+                               }
+                               // if there is an architecture prefix, only use this symbol it if matches current arch
+                               else if ( strncmp(symbolStart, "ppc64:", 6) == 0 ) {
+                                       if ( fArchitecture == CPU_TYPE_POWERPC64 )
+                                               symbolStart = &symbolStart[6];
+                                       else
+                                               symbolStart = NULL;
+                               }
+                               else if ( strncmp(symbolStart, "i386:", 5) == 0 ) {
+                                       if ( fArchitecture == CPU_TYPE_I386 )
+                                               symbolStart = &symbolStart[5];
+                                       else
+                                               symbolStart = NULL;
+                               }
+                               else if ( strncmp(symbolStart, "x86_64:", 7) == 0 ) {
+                                       if ( fArchitecture == CPU_TYPE_X86_64 )
+                                               symbolStart = &symbolStart[7];
+                                       else
+                                               symbolStart = NULL;
+                               }
+                               if ( symbolStart != NULL ) {
+                                       char* objFileName = NULL;
+                                       char* colon = strstr(symbolStart, ".o:");
+                                       if ( colon != NULL ) {
+                                               colon[2] = '\0';
+                                               objFileName = symbolStart;
+                                               symbolStart = &colon[3];
+                                       }
+                                       // trim leading spaces
+                                       while ( isspace(*symbolStart) ) 
+                                               ++symbolStart;
+                                       Options::OrderedSymbol pair;
+                                       if ( cstring )
+                                               pair.symbolName = cstringSymbolName(symbolStart);
+                                       else
+                                               pair.symbolName = symbolStart;
+                                       pair.objectFileName = objFileName;
+                                       fOrderedSymbols.push_back(pair);
+                               }
+                               symbolStart = NULL;
+                               if ( wasComment )
+                                       state = inComment;
+                               else
+                                       state = lineStart;
+                       }
+                       break;
+               case inComment:
+                       if ( *s == '\n' )
+                               state = lineStart;
+                       break;
+               }
+       }
+       // Note: we do not free() the malloc buffer, because the strings are used by the fOrderedSymbols
+}
+
 void Options::parseSectionOrderFile(const char* segment, const char* section, const char* path)
 {
-       fprintf(stderr, "ld64: warning -sectorder not yet supported for 64-bit code\n");
+       if ( (strcmp(section, "__cstring") == 0) && (strcmp(segment, "__TEXT") == 0) ) {
+               parseOrderFile(path, true);
+       }
+       else if ( (strncmp(section, "__literal",9) == 0) && (strcmp(segment, "__TEXT") == 0) ) {
+               fprintf(stderr, "ld64 warning: sorting of __literal[4,8,16] sections not supported\n");
+       }
+       else {
+               // ignore section information and append all symbol names to global order file
+               parseOrderFile(path, false);
+       }
 }
 
 void Options::addSection(const char* segment, const char* section, const char* path)
@@ -863,12 +1384,11 @@ void Options::addSectionAlignment(const char* segment, const char* section, cons
                fprintf(stderr, "ld64 warning: zero is not a valid -sectalign\n");
                value = 1;
        }
-       
+
        // alignment is power of 2 (e.g. page alignment = 12)
-       uint8_t alignment = (uint8_t)log2(value);
-       
+       uint8_t alignment = (uint8_t)__builtin_ctz(value);
        if ( (unsigned long)(1 << alignment) != value ) {
-               fprintf(stderr, "ld64 warning: alignment for -sectalign %s %s is not a power of two, using 0x%X\n", 
+               fprintf(stderr, "ld64 warning: alignment for -sectalign %s %s is not a power of two, using 0x%X\n",
                        segment, section, 1 << alignment);
        }
 
@@ -876,6 +1396,30 @@ void Options::addSectionAlignment(const char* segment, const char* section, cons
        fSectionAlignments.push_back(info);
 }
 
+void Options::addLibrary(const FileInfo& info)
+{
+       // if this library has already been added, don't add again (archives are automatically repeatedly searched)
+       for (std::vector<Options::FileInfo>::iterator fit = fInputFiles.begin(); fit != fInputFiles.end(); fit++) {
+               if ( strcmp(info.path, fit->path) == 0 ) {
+                       // if dylib is specified again but weak, record that it should be weak
+                       if ( info.options.fWeakImport )
+                               fit->options.fWeakImport = true;
+                       return;
+               }
+       }
+       // add to list
+       fInputFiles.push_back(info);
+}
+
+void Options::warnObsolete(const char* arg)
+{
+       if ( emitWarnings() )
+               fprintf(stderr, "ld64: warning: option %s is obsolete and being ignored\n", arg);
+}
+
+
+
+
 //
 // Process all command line arguments.
 //
@@ -908,6 +1452,13 @@ void Options::parse(int argc, const char* argv[])
                        if ( (arg[1] == 'L') || (arg[1] == 'F') ) {
                                // previously handled by buildSearchPaths()
                        }
+                       // The one gnu style option we have to keep compatibility
+                       // with gcc. Might as well have the single hyphen one as well.
+                       else if ( (strcmp(arg, "--help") == 0)
+                                         || (strcmp(arg, "-help") == 0)) {
+                               fprintf (stdout, "ld64: For information on command line options please use 'man ld'.\n");
+                               exit (0);
+                       }
                        else if ( strcmp(arg, "-arch") == 0 ) {
                                parseArch(argv[++i]);
                        }
@@ -915,7 +1466,9 @@ void Options::parse(int argc, const char* argv[])
                                // default
                        }
                        else if ( strcmp(arg, "-static") == 0 ) {
-                               fOutputKind = kStaticExecutable;
+                               if ( fOutputKind != kObjectFile )
+                                       fOutputKind = kStaticExecutable;
+                               fReaderOptions.fForStatic = true;
                        }
                        else if ( strcmp(arg, "-dylib") == 0 ) {
                                fOutputKind = kDynamicLibrary;
@@ -937,14 +1490,14 @@ void Options::parse(int argc, const char* argv[])
                                fOutputFile = argv[++i];
                        }
                        else if ( arg[1] == 'l' ) {
-                               fInputFiles.push_back(findLibrary(&arg[2]));
+                               addLibrary(findLibrary(&arg[2]));
                        }
                        // This causes a dylib to be weakly bound at
                        // link time.  This corresponds to weak_import.
                        else if ( strncmp(arg, "-weak-l", 7) == 0 ) {
                                FileInfo info = findLibrary(&arg[7]);
                                info.options.fWeakImport = true;
-                               fInputFiles.push_back(info);
+                               addLibrary(info);
                        }
                        // Avoid lazy binding.
                        // ??? Deprecate.
@@ -967,49 +1520,78 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-all_load") == 0 ) {
                                fReaderOptions.fFullyLoadArchives = true;
                        }
-                       // Similar to --whole-archive, but for all ObjC classes.
+                       else if ( strcmp(arg, "-noall_load") == 0) {
+                               warnObsolete(arg);
+                       }
+                       // Similar to -all_load
                        else if ( strcmp(arg, "-ObjC") == 0 ) {
-                               fReaderOptions.fLoadObjcClassesInArchives = true;
+                               fReaderOptions.fLoadAllObjcObjectsFromArchives = true;
                        }
                        // Library versioning.
-                       else if ( strcmp(arg, "-dylib_compatibility_version") == 0 ) {
-                               fDylibCompatVersion = parseVersionNumber(argv[++i]);
-                       }
-                       else if ( strcmp(arg, "-dylib_current_version") == 0 ) {
-                               fDylibCurrentVersion = parseVersionNumber(argv[++i]);
+                       else if ( (strcmp(arg, "-dylib_compatibility_version") == 0)
+                                         || (strcmp(arg, "-compatibility_version") == 0)) {
+                                const char* vers = argv[++i];
+                                if ( vers == NULL )
+                                       throw "-dylib_compatibility_version missing <version>";
+                               fDylibCompatVersion = parseVersionNumber(vers);
+                       }
+                       else if ( (strcmp(arg, "-dylib_current_version") == 0)
+                                         || (strcmp(arg, "-current_version") == 0)) {
+                                const char* vers = argv[++i];
+                                if ( vers == NULL )
+                                       throw "-dylib_current_version missing <version>";
+                               fDylibCurrentVersion = parseVersionNumber(vers);
                        }
                        else if ( strcmp(arg, "-sectorder") == 0 ) {
+                                if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
+                                       throw "-sectorder missing <segment> <section> <file-path>";
                                parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
                                i += 3;
                        }
+                       else if ( strcmp(arg, "-order_file") == 0 ) {
+                               parseOrderFile(argv[++i], false);
+                       }
+                       else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
+                               fPrintOrderFileStatistics = true;
+                       }
                        // ??? Deprecate segcreate.
                        // -sectcreate puts whole files into a section in the output.
                        else if ( (strcmp(arg, "-sectcreate") == 0) || (strcmp(arg, "-segcreate") == 0) ) {
+                                if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
+                                       throw "-sectcreate missing <segment> <section> <file-path>";
                                addSection(argv[i+1], argv[i+2], argv[i+3]);
                                i += 3;
                        }
                        // Since we have a full path in binary/library names we need to be able to override it.
-                       else if ( (strcmp(arg, "-dylib_install_name") == 0) || (strcmp(arg, "-dylinker_install_name") == 0) ) {
+                       else if ( (strcmp(arg, "-dylib_install_name") == 0)
+                                         || (strcmp(arg, "-dylinker_install_name") == 0)
+                                         || (strcmp(arg, "-install_name") == 0)) {
                                fDylibInstallName = argv[++i];
+                                if ( fDylibInstallName == NULL )
+                                       throw "-install_name missing <path>";
                        }
                        // Sets the base address of the output.
                        else if ( (strcmp(arg, "-seg1addr") == 0) || (strcmp(arg, "-image_base") == 0) ) {
-                               fBaseAddress = parseAddress(argv[++i]);
+                                const char* address = argv[++i];
+                                if ( address == NULL )
+                                       throwf("%s missing <address>", arg);
+                               fBaseAddress = parseAddress(address);
                        }
                        else if ( strcmp(arg, "-e") == 0 ) {
                                fEntryName = argv[++i];
                        }
                        // Same as -@ from the FSF linker.
                        else if ( strcmp(arg, "-filelist") == 0 ) {
-                                loadFileList(argv[++i]);
+                                const char* path = argv[++i];
+                                if ( (path == NULL) || (path[0] == '-') )
+                                       throw "-filelist missing <path>";
+                                loadFileList(path);
                        }
                        else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
                                 fKeepPrivateExterns = true;
                        }
-                       // ??? Deprecate
                        else if ( strcmp(arg, "-final_output") == 0 ) {
-                                ++i;
-                               // ignore for now
+                               fFinalName = argv[++i];
                        }
                        // Ensure that all calls to exported symbols go through lazy pointers.  Multi-module
                        // just ensures that this happens for cross object file boundaries.
@@ -1028,10 +1610,34 @@ void Options::parse(int argc, const char* argv[])
                        }
                        else if ( strcmp(arg, "-unexported_symbols_list") == 0 ) {
                                if ( fExportMode == kExportSome )
-                                       throw "can't use -exported_symbols_list and -unexported_symbols_list";
+                                       throw "can't use -unexported_symbols_list and -exported_symbols_list";
                                fExportMode = kDontExportSome;
                                loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
                        }
+                       else if ( strcmp(arg, "-exported_symbol") == 0 ) {
+                               if ( fExportMode == kDontExportSome )
+                                       throw "can't use -exported_symbol and -unexported_symbols";
+                               fExportMode = kExportSome;
+                               fExportSymbols.insert(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
+                               if ( fExportMode == kExportSome )
+                                       throw "can't use -unexported_symbol and -exported_symbol";
+                               fExportMode = kDontExportSome;
+                               fDontExportSymbols.insert(argv[++i]);
+                       }
+                       else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
+                               if ( fLocalSymbolHandling == kLocalSymbolsSelectiveExclude )
+                                       throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
+                               fLocalSymbolHandling = kLocalSymbolsSelectiveInclude;
+                               loadExportFile(argv[++i], "-non_global_symbols_no_strip_list", fLocalSymbolsIncluded);
+                       }
+                       else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
+                               if ( fLocalSymbolHandling == kLocalSymbolsSelectiveInclude )
+                                       throw "can't use -non_global_symbols_no_strip_list and -non_global_symbols_strip_list";
+                               fLocalSymbolHandling = kLocalSymbolsSelectiveExclude;
+                               loadExportFile(argv[++i], "-non_global_symbols_strip_list", fLocalSymbolsExcluded);
+                       }
                        // ??? Deprecate
                        else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
                                 fIgnoreOtherArchFiles = true;
@@ -1043,19 +1649,18 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-weak_library") == 0 ) {
                                FileInfo info = findFile(argv[++i]);
                                info.options.fWeakImport = true;
-                               fInputFiles.push_back(info);
+                               addLibrary(info);
                        }
                        else if ( strcmp(arg, "-framework") == 0 ) {
-                               fInputFiles.push_back(findFramework(argv[++i]));
+                               addLibrary(findFramework(argv[++i]));
                        }
                        else if ( strcmp(arg, "-weak_framework") == 0 ) {
                                FileInfo info = findFramework(argv[++i]);
                                info.options.fWeakImport = true;
-                               fInputFiles.push_back(info);
+                               addLibrary(info);
                        }
-                       // ??? Deprecate when we get -Bstatic/-Bdynamic.
                        else if ( strcmp(arg, "-search_paths_first") == 0 ) {
-                               fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
+                               // previously handled by buildSearchPaths()
                        }
                        else if ( strcmp(arg, "-undefined") == 0 ) {
                                 setUndefinedTreatment(argv[++i]);
@@ -1076,16 +1681,9 @@ void Options::parse(int argc, const char* argv[])
                                else if ( temp == kInvalid )
                                        throw "invalid option to -read_only_relocs [ warning | error | suppress ]";
                        }
-                       // Specifies whether or not there are intra section
-                       // relocations and what to do when found. Could be
-                       // errors, warnings, or suppressed.
                        else if ( strcmp(arg, "-sect_diff_relocs") == 0 ) {
-                               fPICTreatment = parseTreatment(argv[++i]);
-
-                               if ( fPICTreatment == kNULL )
-                                       throw "-sect_diff_relocs missing [ warning | error | suppress ]";
-                               else if ( fPICTreatment == kInvalid )
-                                       throw "invalid option to -sect_diff_relocs [ warning | error | suppress ]";
+                               warnObsolete(arg);
+                               ++i;
                        }
                        // Warn, error or make strong a mismatch between weak
                        // and non-weak references.
@@ -1100,98 +1698,129 @@ void Options::parse(int argc, const char* argv[])
                                fPrebind = true;
                        }
                        else if ( strcmp(arg, "-noprebind") == 0 ) {
+                               warnObsolete(arg);
                                fPrebind = false;
                        }
-                       // ??? Deprecate
                        else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
-                                 // Do not handle and suppress warnings always.
+                               warnObsolete(arg);
                        }
-                       // ??? Deprecate
                        else if ( strcmp(arg, "-prebind_all_twolevel_modules") == 0 ) {
-                                 // Ignore.
+                               warnObsolete(arg);
                        }
-                       // ??? Deprecate
                        else if ( strcmp(arg, "-noprebind_all_twolevel_modules") == 0 ) {
-                                 // Ignore.
+                               warnObsolete(arg);
                        }
-                       // Sets a bit in the main executable only that causes fix_prebinding
-                       // not to run.  This is always set.
                        else if ( strcmp(arg, "-nofixprebinding") == 0 ) {
-                                 // Ignore.
+                               warnObsolete(arg);
                        }
                        // This should probably be deprecated when we respect -L and -F
                        // when searching for libraries.
                        else if ( strcmp(arg, "-dylib_file") == 0 ) {
-                                setDylibInstallNameOverride(argv[++i]);
+                                addDylibOverride(argv[++i]);
                        }
-                       // Allows us to rewrite full paths to be relocatable based on
-                       // the path name of the executable.
+                       // What to expand @executable_path to if found in dependent dylibs
                        else if ( strcmp(arg, "-executable_path") == 0 ) {
                                 fExecutablePath = argv[++i];
                                 if ( (fExecutablePath == NULL) || (fExecutablePath[0] == '-') )
                                        throw "-executable_path missing <path>";
+                               // if a directory was passed, add / to end
+                               // <rdar://problem/5171880> ld64 can't find @executable _path relative dylibs from our umbrella frameworks
+                               struct stat statBuffer;
+                               if ( stat(fExecutablePath, &statBuffer) == 0 ) {
+                                       if ( (statBuffer.st_mode & S_IFMT) == S_IFDIR ) {
+                                               char* pathWithSlash = new char[strlen(fExecutablePath)+2];
+                                               strcpy(pathWithSlash, fExecutablePath);
+                                               strcat(pathWithSlash, "/");
+                                               fExecutablePath = pathWithSlash;
+                                       }
+                               }
                        }
-                       // ??? Deprecate
                        // Aligns all segments to the power of 2 boundary specified.
                        else if ( strcmp(arg, "-segalign") == 0 ) {
-                               // Ignore.
+                               warnObsolete(arg);
                                ++i;
                        }
                        // Puts a specified segment at a particular address that must
                        // be a multiple of the segment alignment.
                        else if ( strcmp(arg, "-segaddr") == 0 ) {
-                               // FIX FIX
-                               i += 2;
+                               SegmentStart seg;
+                               seg.name = argv[++i];
+                                if ( (seg.name == NULL) || (argv[i+1] == NULL) )
+                                       throw "-segaddr missing segName Adddress";
+                               seg.address = parseAddress(argv[++i]);
+                               uint64_t temp = seg.address & (-4096); // page align
+                               if ( (seg.address != temp) && emitWarnings() )
+                                       fprintf(stderr, "ld64: warning, -segaddr %s not page aligned, rounding down\n", seg.name);
+                               fCustomSegmentAddresses.push_back(seg);
                        }
                        // ??? Deprecate when we deprecate split-seg.
                        else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
-                               // Ignore.
-                               ++i;
+                               fBaseAddress = parseAddress(argv[++i]);
                        }
                        // ??? Deprecate when we deprecate split-seg.
                        else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
-                               // Ignore.
-                               ++i;
+                               fBaseWritableAddress = parseAddress(argv[++i]);
+                               fSplitSegs = true;
                        }
                        // ??? Deprecate when we get rid of basing at build time.
                        else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
-                               // Ignore.
-                               ++i;
+                               const char* name = argv[++i];
+                               if ( name == NULL )
+                                       throw "-seg_addr_table missing argument";
+                               fSegAddrTablePath = name;
                        }
-                       // ??? Deprecate.
                        else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
-                               // Ignore.
+                               warnObsolete(arg);
                                ++i;
                        }
                        else if ( strcmp(arg, "-segprot") == 0 ) {
-                               // FIX FIX
-                               i += 3;
+                               SegmentProtect seg;
+                               seg.name = argv[++i];
+                                if ( (seg.name == NULL) || (argv[i+1] == NULL) || (argv[i+2] == NULL) )
+                                       throw "-segprot missing segName max-prot init-prot";
+                               seg.max = parseProtection(argv[++i]);
+                               seg.init = parseProtection(argv[++i]);
+                               fCustomSegmentProtections.push_back(seg);
                        }
                        else if ( strcmp(arg, "-pagezero_size") == 0 ) {
-                               fZeroPageSize = parseAddress(argv[++i]);
+                                const char* size = argv[++i];
+                                if ( size == NULL )
+                                       throw "-pagezero_size missing <size>";
+                               fZeroPageSize = parseAddress(size);
                                uint64_t temp = fZeroPageSize & (-4096); // page align
-                               if ( fZeroPageSize != temp )
+                               if ( (fZeroPageSize != temp) && emitWarnings() )
                                        fprintf(stderr, "ld64: warning, -pagezero_size not page aligned, rounding down\n");
                                 fZeroPageSize = temp;
                        }
                        else if ( strcmp(arg, "-stack_addr") == 0 ) {
-                               fStackAddr = parseAddress(argv[++i]);
+                                const char* address = argv[++i];
+                                if ( address == NULL )
+                                       throw "-stack_addr missing <address>";
+                               fStackAddr = parseAddress(address);
                        }
                        else if ( strcmp(arg, "-stack_size") == 0 ) {
-                               fStackSize = parseAddress(argv[++i]);
+                                const char* size = argv[++i];
+                                if ( size == NULL )
+                                       throw "-stack_size missing <address>";
+                               fStackSize = parseAddress(size);
+                               uint64_t temp = fStackSize & (-4096); // page align
+                               if ( (fStackSize != temp) && emitWarnings() )
+                                       fprintf(stderr, "ld64: warning, -stack_size not page aligned, rounding down\n");
                        }
                        else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
                                fExecutableStack = true;
                        }
                        else if ( strcmp(arg, "-sectalign") == 0 ) {
+                                if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) || (argv[i+3]==NULL) )
+                                       throw "-sectalign missing <segment> <section> <file-path>";
                                addSectionAlignment(argv[i+1], argv[i+2], argv[i+3]);
                                i += 3;
                        }
                        else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
-                                // FIX FIX
+                               warnObsolete(arg);
                        }
                        else if ( strcmp(arg, "-sectobjectsymbols") == 0 ) {
-                               // FIX FIX
+                               warnObsolete(arg);
                                i += 2;
                        }
                        else if ( strcmp(arg, "-bundle_loader") == 0 ) {
@@ -1203,7 +1832,7 @@ void Options::parse(int argc, const char* argv[])
                                fInputFiles.push_back(info);
                        }
                        else if ( strcmp(arg, "-private_bundle") == 0 ) {
-                               // FIX FIX
+                               warnObsolete(arg);
                        }
                        else if ( strcmp(arg, "-twolevel_namespace_hints") == 0 ) {
                                // FIX FIX
@@ -1212,49 +1841,31 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
                                setVersionMin(argv[++i]);
                        }
-                       // This option (unlike -m below) only affects how we warn
-                       // on multiple definitions inside dynamic libraries.
                        else if ( strcmp(arg, "-multiply_defined") == 0 ) {
-                               fMultiplyDefinedDynamic = parseTreatment(argv[++i]);
-
-                               if ( fMultiplyDefinedDynamic == kNULL )
-                                       throw "-multiply_defined missing [ warning | error | suppress ]";
-                               else if ( fMultiplyDefinedDynamic == kInvalid )
-                                       throw "invalid option to -multiply_defined [ warning | error | suppress ]";
+                               //warnObsolete(arg);
+                               ++i;
                        }
                        else if ( strcmp(arg, "-multiply_defined_unused") == 0 ) {
-                               fMultiplyDefinedUnused = parseTreatment(argv[++i]);
-
-                               if ( fMultiplyDefinedUnused == kNULL )
-                                       throw "-multiply_defined_unused missing [ warning | error | suppress ]";
-                               else if ( fMultiplyDefinedUnused == kInvalid )
-                                       throw "invalid option to -multiply_defined_unused [ warning | error | suppress ]";
+                               warnObsolete(arg);
+                               ++i;
                        }
                        else if ( strcmp(arg, "-nomultidefs") == 0 ) {
-                                // FIX FIX
+                               warnObsolete(arg);
                        }
                        // Display each file in which the argument symbol appears and whether
                        // the file defines or references it.  This option takes an argument
                        // as -y<symbol> note that there is no space.
                        else if ( strncmp(arg, "-y", 2) == 0 ) {
-                               const char* name = &arg[2];
-
-                               if ( name == NULL )
-                                       throw "-y missing argument";
-
-                               fTraceSymbols.push_back(name);
+                               warnObsolete("-y");
                        }
                        // Same output as -y, but output <arg> number of undefined symbols only.
                        else if ( strcmp(arg, "-Y") == 0 ) {
-                               char* endptr;
-                               fLimitUndefinedSymbols = strtoul (argv[++i], &endptr, 10);
-
-                               if(*endptr != '\0')
-                                       throw "invalid argument for -Y [decimal number]";
+                               //warnObsolete(arg);
+                               ++i;
                        }
                        // This option affects all objects linked into the final result.
                        else if ( strcmp(arg, "-m") == 0 ) {
-                               fWarnOnMultiplyDefined = true;
+                               warnObsolete(arg);
                        }
                        else if ( (strcmp(arg, "-why_load") == 0) || (strcmp(arg, "-whyload") == 0) ) {
                                 fReaderOptions.fWhyLoad = true;
@@ -1272,33 +1883,38 @@ void Options::parse(int argc, const char* argv[])
                                fInitialUndefines.push_back(name);
                        }
                        else if ( strcmp(arg, "-U") == 0 ) {
-                                // FIX FIX
-                                ++i;
+                               const char* name = argv[++i];
+                               if ( name == NULL )
+                                       throw "-U missing argument";
+                               fAllowedUndefined.insert(name);
                        }
                        else if ( strcmp(arg, "-s") == 0 ) {
-                               fStripLocalSymbols = true;
+                               warnObsolete(arg);
+                               fLocalSymbolHandling = kLocalSymbolsNone;
                                fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
                        }
                        else if ( strcmp(arg, "-x") == 0 ) {
-                               fStripLocalSymbols = true;
+                               fLocalSymbolHandling = kLocalSymbolsNone;
                        }
                        else if ( strcmp(arg, "-S") == 0 ) {
                                fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoNone;
                        }
                        else if ( strcmp(arg, "-X") == 0 ) {
-                               // FIX FIX
+                               warnObsolete(arg);
                        }
                        else if ( strcmp(arg, "-Si") == 0 ) {
+                               warnObsolete(arg);
                                fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoFull;
                        }
                        else if ( strcmp(arg, "-b") == 0 ) {
-                               // FIX FIX
+                               warnObsolete(arg);
                        }
                        else if ( strcmp(arg, "-Sn") == 0 ) {
+                               warnObsolete(arg);
                                fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoFull;
                        }
                        else if ( strcmp(arg, "-Sp") == 0 ) {
-                               fReaderOptions.fDebugInfoStripping = ObjectFile::ReaderOptions::kDebugInfoMinimal;
+                               warnObsolete(arg);
                        }
                        else if ( strcmp(arg, "-dead_strip") == 0 ) {
                                fDeadStrip = kDeadStripOnPlusUnusedInits;
@@ -1307,7 +1923,7 @@ void Options::parse(int argc, const char* argv[])
                                fDeadStrip = kDeadStripOn;
                        }
                        else if ( strcmp(arg, "-w") == 0 ) {
-                               // FIX FIX
+                               // previously handled by buildSearchPaths()
                        }
                        else if ( strcmp(arg, "-arch_errors_fatal") == 0 ) {
                                // FIX FIX
@@ -1315,9 +1931,6 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-M") == 0 ) {
                                // FIX FIX
                        }
-                       else if ( strcmp(arg, "-whatsloaded") == 0 ) {
-                               // FIX FIX
-                       }
                        else if ( strcmp(arg, "-headerpad") == 0 ) {
                                const char* size = argv[++i];
                                if ( size == NULL )
@@ -1325,13 +1938,16 @@ void Options::parse(int argc, const char* argv[])
                                 fMinimumHeaderPad = parseAddress(size);
                        }
                        else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
-                               // FIX FIX
+                               fMaxMinimumHeaderPad = true;
                        }
                        else if ( strcmp(arg, "-t") == 0 ) {
-                               // FIX FIX
+                               fReaderOptions.fLogAllFiles = true;
+                       }
+                       else if ( strcmp(arg, "-whatsloaded") == 0 ) {
+                               fReaderOptions.fLogObjectFiles = true;
                        }
                        else if ( strcmp(arg, "-A") == 0 ) {
-                                // FIX FIX
+                               warnObsolete(arg);
                                 ++i;
                        }
                        else if ( strcmp(arg, "-umbrella") == 0 ) {
@@ -1399,7 +2015,7 @@ void Options::parse(int argc, const char* argv[])
                                fStatistics = true;
                        }
                        else if ( strcmp(arg, "-d") == 0 ) {
-                               fMakeTentativeDefinitionsReal = true;
+                               fReaderOptions.fMakeTentativeDefinitionsReal = true;
                        }
                        else if ( strcmp(arg, "-v") == 0 ) {
                                // previously handled by buildSearchPaths()
@@ -1412,18 +2028,99 @@ void Options::parse(int argc, const char* argv[])
                                // previously handled by buildSearchPaths()
                        }
                        else if ( strcmp(arg, "-no_uuid") == 0 ) {
-                               fEmitUUID = false;
+                               fUUIDMode = kUUIDNone;
+                       }
+                       else if ( strcmp(arg, "-random_uuid") == 0 ) {
+                               fUUIDMode = kUUIDRandom;
+                       }
+                       else if ( strcmp(arg, "-dtrace") == 0 ) {
+                               const char* name = argv[++i];
+                               if ( name == NULL )
+                                       throw "-dtrace missing argument";
+                               fDtraceScriptName = name;
+                       }
+                       else if ( strcmp(arg, "-root_safe") == 0 ) {
+                               fReaderOptions.fRootSafe = true;
+                       }
+                       else if ( strcmp(arg, "-setuid_safe") == 0 ) {
+                               fReaderOptions.fSetuidSafe = true;
+                       }
+                       else if ( strcmp(arg, "-alias") == 0 ) {
+                               ObjectFile::ReaderOptions::AliasPair pair;
+                               pair.realName = argv[++i];
+                               if ( pair.realName == NULL )
+                                       throw "missing argument to -alias";
+                               pair.alias = argv[++i];
+                               if ( pair.alias == NULL )
+                                       throw "missing argument to -alias";
+                               fReaderOptions.fAliases.push_back(pair);
+                       }
+                       else if ( strcmp(arg, "-alias_list") == 0 ) {
+                               parseAliasFile(argv[++i]);
                        }
                        // put this last so that it does not interfer with other options starting with 'i'
                        else if ( strncmp(arg, "-i", 2) == 0 ) {
-                               fprintf(stderr, "ld64: -i option (indirect symbols) not supported\n");
+                               const char* colon = strchr(arg, ':');
+                               if ( colon == NULL )
+                                       throwf("unknown option: %s", arg);
+                               ObjectFile::ReaderOptions::AliasPair pair;
+                               char* temp = new char[colon-arg];
+                               strlcpy(temp, &arg[2], colon-arg-1);
+                               pair.realName = &colon[1];
+                               pair.alias = temp;
+                               fReaderOptions.fAliases.push_back(pair);
+                       }
+                       else if ( strcmp(arg, "-save-temps") == 0 ) {
+                               fSaveTempFiles = true;
+                       }
+                       else if ( strcmp(arg, "-rpath") == 0 ) {
+                               const char* path = argv[++i];
+                               if ( path == NULL )
+                                       throw "missing argument to -rpath";
+                               fRPaths.push_back(path);
+                       }
+                       else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
+                               fReadOnlyx86Stubs = true;
+                       }
+                       else if ( strcmp(arg, "-map") == 0 ) {
+                               fMapPath = argv[++i];
+                               if ( fMapPath == NULL )
+                                       throw "missing argument to -map";
+                       }
+                       else if ( strcmp(arg, "-pie") == 0 ) {
+                               fPositionIndependentExecutable = true;
+                       }
+                       else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
+                               FileInfo info = findLibrary(&arg[11]);
+                               info.options.fReExport = true;
+                               addLibrary(info);
+                       }
+                       else if ( strcmp(arg, "-reexport_library") == 0 ) {
+                               FileInfo info = findFile(argv[++i]);
+                               info.options.fReExport = true;
+                               addLibrary(info);
+                       }
+                       else if ( strcmp(arg, "-reexport_framework") == 0 ) {
+                               FileInfo info = findFramework(argv[++i]);
+                               info.options.fReExport = true;
+                               addLibrary(info);
+                       }
+                       else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
+                               fDeadStripDylibs = true;
+                       }
+                       else if ( strcmp(arg, "-new_linker") == 0 ) {
+                               // ignore
                        }
                        else {
                                throwf("unknown option: %s", arg);
                        }
                }
                else {
-                       fInputFiles.push_back(findFile(arg));
+                       FileInfo info = findFile(arg);
+                       if ( strcmp(&info.path[strlen(info.path)-2], ".a") == 0 )
+                               addLibrary(info);
+                       else
+                               fInputFiles.push_back(info);
                }
        }
 }
@@ -1456,8 +2153,8 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                        addStandardLibraryDirectories = false;
                else if ( strcmp(argv[i], "-v") == 0 ) {
                        fVerbose = true;
-                       extern const char ld64VersionString[];
-                       fprintf(stderr, "%s", ld64VersionString);
+                       extern const char ldVersionString[];
+                       fprintf(stderr, "%s", ldVersionString);
                         // if only -v specified, exit cleanly
                         if ( argc == 2 )
                                exit(0);
@@ -1468,14 +2165,21 @@ void Options::buildSearchPaths(int argc, const char* argv[])
                                throw "-syslibroot missing argument";
                        fSDKPaths.push_back(path);
                }
+               else if ( strcmp(argv[i], "-search_paths_first") == 0 ) {
+                       // ??? Deprecate when we get -Bstatic/-Bdynamic.
+                       fLibrarySearchMode = kSearchDylibAndArchiveInEachDir;
+               }
+               else if ( strcmp(argv[i], "-w") == 0 ) {
+                       fSuppressWarnings = true;
+               }
        }
        if ( addStandardLibraryDirectories ) {
                libraryPaths.push_back("/usr/lib");
                libraryPaths.push_back("/usr/local/lib");
 
                frameworkPaths.push_back("/Library/Frameworks/");
-               frameworkPaths.push_back("/Network/Library/Frameworks/");
                frameworkPaths.push_back("/System/Library/Frameworks/");
+               frameworkPaths.push_back("/Network/Library/Frameworks/");
        }
 
        // now merge sdk and library paths to make real search paths
@@ -1578,6 +2282,9 @@ void Options::parsePreCommandLineEnvironmentSettings()
 
        if (fReaderOptions.fTraceDylibs || fReaderOptions.fTraceArchives)
                fReaderOptions.fTraceOutputFile = getenv("LD_TRACE_FILE");
+
+       if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
+               fPrintOrderFileStatistics = true;
 }
 
 // this is run after the command line is parsed
@@ -1587,7 +2294,15 @@ void Options::parsePostCommandLineEnvironmentSettings()
        if ( fExecutablePath == NULL && (fOutputKind == kDynamicExecutable) ) {
                fExecutablePath = fOutputFile;
        }
-       
+
+       // allow build system to set default seg_addr_table
+       if ( fSegAddrTablePath == NULL )
+               fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
+
+       // allow build system to turn on prebinding
+       if ( !fPrebind ) {
+               fPrebind = ( getenv("LD_PREBIND") != NULL );
+       }
 }
 
 void Options::reconfigureDefaults()
@@ -1597,53 +2312,114 @@ void Options::reconfigureDefaults()
                case Options::kObjectFile:
                        fReaderOptions.fForFinalLinkedImage = false;
                        break;
-               case Options::kDynamicExecutable:
-               case Options::kStaticExecutable:
+               case Options::kDyld:
+                       fReaderOptions.fForDyld = true;
+                       fReaderOptions.fForFinalLinkedImage = true;
+                       break;
                case Options::kDynamicLibrary:
                case Options::kDynamicBundle:
-               case Options::kDyld:
+                       fReaderOptions.fForFinalLinkedImage = true;
+                       break;
+               case Options::kDynamicExecutable:
+               case Options::kStaticExecutable:
+                       fReaderOptions.fLinkingMainExecutable = true;
                        fReaderOptions.fForFinalLinkedImage = true;
                        break;
        }
 
        // set default min OS version
-       if ( fVersionMin == kMinUnset ) {
-               switch ( fArchitecture ) {
-                       case CPU_TYPE_POWERPC:
-                               fVersionMin = k10_2;
-                               break;
-                       case CPU_TYPE_I386:
-                       case CPU_TYPE_POWERPC64:
-                       case CPU_TYPE_X86_64:
-                               fVersionMin = k10_4;
-                       default:
-                               // architecture not specified
-                               fVersionMin = k10_4;
-                               break;
-               }
+       if ( fReaderOptions.fVersionMin == ObjectFile::ReaderOptions::kMinUnset ) {
+               // if -macosx_version_min not used, try environment variable
+               const char* envVers = getenv("MACOSX_DEPLOYMENT_TARGET");
+               if ( envVers != NULL ) 
+                       setVersionMin(envVers);
+               // if -macosx_version_min and environment variable not used assume current OS version
+               if ( fReaderOptions.fVersionMin == ObjectFile::ReaderOptions::kMinUnset )
+                       fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_5; // FIX FIX, this really should be a check of the OS version the linker is running on
        }
 
        // adjust min based on architecture
        switch ( fArchitecture ) {
                case CPU_TYPE_I386:
-                       if ( fVersionMin < k10_4 ) {
+                       if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
                                //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for i386\n");
-                               fVersionMin = k10_4;
+                               fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
                        }
                        break;
                case CPU_TYPE_POWERPC64:
-                       if ( fVersionMin < k10_4 ) {
+                       if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
                                //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for ppc64\n");
-                               fVersionMin = k10_4;
+                               fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
                        }
                        break;
                case CPU_TYPE_X86_64:
-                       if ( fVersionMin < k10_4 ) {
+                       if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_4 ) {
                                //fprintf(stderr, "ld64 warning: -macosx_version_min should be 10.4 or later for x86_64\n");
-                               fVersionMin = k10_4;
+                               fReaderOptions.fVersionMin = ObjectFile::ReaderOptions::k10_4;
                        }
                        break;
        }
+
+       // determine if info for shared region should be added
+       if ( fOutputKind == Options::kDynamicLibrary ) {
+               if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_5 )
+                       fSharedRegionEligible = true;
+       }
+
+       // allow build system to force linker to ignore seg_addr_table
+       if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
+                  fSegAddrTablePath = NULL;
+
+       // check for base address specified externally
+       if ( (fSegAddrTablePath != NULL) &&  (fOutputKind == Options::kDynamicLibrary) ) 
+               parseSegAddrTable(fSegAddrTablePath, this->installPath());
+       
+
+       // split segs only allowed for dylibs
+       if ( fSplitSegs ) {
+               if ( fOutputKind != Options::kDynamicLibrary )
+                       fSplitSegs = false;
+               // split seg only supported for ppc and i386
+               switch ( fArchitecture ) {
+                       case CPU_TYPE_POWERPC:
+                       case CPU_TYPE_I386:
+                               break;
+                       default:
+                               fSplitSegs = false;
+                               fBaseAddress = 0;
+                               fBaseWritableAddress = 0;
+               }
+       }
+
+       // disable prebinding depending on arch and min OS version
+       if ( fPrebind ) {
+               switch ( fArchitecture ) {
+                       case CPU_TYPE_POWERPC:
+                       case CPU_TYPE_I386:
+                               if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_4 ) {
+                                       // only split seg dylibs are prebound
+                                       if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
+                                               fPrebind = false;
+                               }
+                               break;
+                       case CPU_TYPE_POWERPC64:
+                       case CPU_TYPE_X86_64:
+                               fPrebind = false;
+                               break;
+               }
+       }
+
+
+       // figure out if module table is needed for compatibility with old ld/dyld
+       if ( fOutputKind == Options::kDynamicLibrary ) {
+               switch ( fArchitecture ) {
+                       case CPU_TYPE_POWERPC:  // 10.3 and earlier dyld requires a module table
+                       case CPU_TYPE_I386:             // ld_classic for 10.4.x requires a module table
+                               if ( fReaderOptions.fVersionMin <= ObjectFile::ReaderOptions::k10_5 )
+                                       fNeedsModuleTable = true;
+               }
+       }
+       
        
 }
 
@@ -1678,7 +2454,7 @@ void Options::checkIllegalOptionCombinations()
                                break;
                        }
                }
-               if ( ! found )
+               if ( ! found && emitWarnings() )
                        fprintf(stderr, "ld64 warning: -sub_umbrella %s does not match a supplied dylib\n", subUmbrella);
        }
 
@@ -1700,7 +2476,7 @@ void Options::checkIllegalOptionCombinations()
                                break;
                        }
                }
-               if ( ! found )
+               if ( ! found && emitWarnings() )
                        fprintf(stderr, "ld64 warning: -sub_library %s does not match a supplied dylib\n", subLibrary);
        }
 
@@ -1736,13 +2512,13 @@ void Options::checkIllegalOptionCombinations()
                                if ( fStackAddr == 0 ) {
                                        fStackAddr = 0xC0000000;
                                }
-                               if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) )
+                               if ( (fStackAddr > 0xB0000000) && ((fStackAddr-fStackSize) < 0xB0000000) && emitWarnings() )
                                        fprintf(stderr, "ld64 warning: custom stack placement overlaps and will disable shared region\n");
                                break;
                        case CPU_TYPE_POWERPC64:
                        case CPU_TYPE_X86_64:
                                if ( fStackAddr == 0 ) {
-                                       fStackAddr = 0x0007FFFF00000000LL;
+                                       fStackAddr = 0x00007FFF5C000000LL;
                                }
                                break;
                }
@@ -1776,10 +2552,20 @@ void Options::checkIllegalOptionCombinations()
                }
        }
 
-       // check -client_name is only used when -bundle is specified
-       if ( (fClientName != NULL) && (fOutputKind != Options::kDynamicBundle) )
-               throw "-client_name can only be used with -bundle";
-
+       // check -client_name is only used when making a bundle or main executable
+       if ( fClientName != NULL ) {
+               switch ( fOutputKind ) {
+                       case Options::kDynamicExecutable:
+                       case Options::kDynamicBundle:
+                               break;
+                       case Options::kStaticExecutable:
+                       case Options::kDynamicLibrary:
+                       case Options::kObjectFile:
+                       case Options::kDyld:
+                               throw "-client_name can only be used with -bundle";
+               }
+       }
+       
        // check -init is only used when building a dylib
        if ( (fInitFunctionName != NULL) && (fOutputKind != Options::kDynamicLibrary) )
                throw "-init can only be used with -dynamiclib";
@@ -1788,22 +2574,77 @@ void Options::checkIllegalOptionCombinations()
        if ( (fBundleLoader != NULL) && (fOutputKind != Options::kDynamicBundle) )
                throw "-bundle_loader can only be used with -bundle";
 
+       // check -dtrace not used with -r
+       if ( (fDtraceScriptName != NULL) && (fOutputKind == Options::kObjectFile) )
+               throw "-dtrace can only be used when creating final linked images";
+
        // check -d can only be used with -r
-       if ( fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
+       if ( fReaderOptions.fMakeTentativeDefinitionsReal && (fOutputKind != Options::kObjectFile) )
                throw "-d can only be used with -r";
-       
+
+       // check that -root_safe is not used with -r
+       if ( fReaderOptions.fRootSafe && (fOutputKind == Options::kObjectFile) )
+               throw "-root_safe cannot be used with -r";
+
+       // check that -setuid_safe is not used with -r
+       if ( fReaderOptions.fSetuidSafe && (fOutputKind == Options::kObjectFile) )
+               throw "-setuid_safe cannot be used with -r";
+
        // make sure all required exported symbols exist
-       for (NameSet::iterator it=fExportSymbols.begin(); it != fExportSymbols.end(); it++) {
+       std::vector<const char*> impliedExports;
+       for (NameSet::iterator it=fExportSymbols.regularBegin(); it != fExportSymbols.regularEnd(); it++) {
                const char* name = *it;
                // never export .eh symbols
-               if ( strcmp(&name[strlen(name)-3], ".eh") != 0 )
+               const int len = strlen(name);
+               if ( (strcmp(&name[len-3], ".eh") == 0) || (strncmp(name, ".objc_category_name_", 20) == 0) ) 
+                       fprintf(stderr, "ld64 warning: ignoring %s in export list\n", name);
+               else
                        fInitialUndefines.push_back(name);
+               if ( strncmp(name, ".objc_class_name_", 17) == 0 ) {
+                       // rdar://problem/4718189 map ObjC class names to new runtime names
+                       switch (fArchitecture) {
+                               case CPU_TYPE_POWERPC64:
+                               case CPU_TYPE_X86_64:
+                                       char* temp;
+                                       asprintf(&temp, "_OBJC_CLASS_$_%s", &name[17]);
+                                       impliedExports.push_back(temp);
+                                       asprintf(&temp, "_OBJC_METACLASS_$_%s", &name[17]);
+                                       impliedExports.push_back(temp);
+                                       break;
+                       }
+               }
        }
-       
+       for (std::vector<const char*>::iterator it=impliedExports.begin(); it != impliedExports.end(); it++) {
+               const char* name = *it;
+               fExportSymbols.insert(name);
+               fInitialUndefines.push_back(name);
+       }
+
        // make sure that -init symbol exist
        if ( fInitFunctionName != NULL )
                fInitialUndefines.push_back(fInitFunctionName);
 
+       // check custom segments
+       if ( fCustomSegmentAddresses.size() != 0 ) {
+               // verify no segment is in zero page
+               if ( fZeroPageSize != ULLONG_MAX ) {
+                       for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
+                               if ( (it->address >= 0) && (it->address < fZeroPageSize) )
+                                       throwf("-segaddr %s 0x%X conflicts with -pagezero_size", it->name, it->address);
+                       }
+               }
+               // verify no duplicates
+               for (std::vector<SegmentStart>::iterator it = fCustomSegmentAddresses.begin(); it != fCustomSegmentAddresses.end(); ++it) {
+                       for (std::vector<SegmentStart>::iterator it2 = fCustomSegmentAddresses.begin(); it2 != fCustomSegmentAddresses.end(); ++it2) {
+                               if ( (it->address == it2->address) && (it != it2) )
+                                       throwf("duplicate -segaddr addresses for %s and %s", it->name, it2->name);
+                       }
+                       // a custom segment address of zero will disable the use of a zero page
+                       if ( it->address == 0 )
+                               fZeroPageSize = 0;
+               }
+       }
+
        if ( fZeroPageSize == ULLONG_MAX ) {
                // zero page size not specified on command line, set default
                switch (fArchitecture) {
@@ -1814,7 +2655,7 @@ void Options::checkIllegalOptionCombinations()
                                break;
                        case CPU_TYPE_POWERPC64:
                                // first 4GB for ppc64 on 10.5
-                               if ( fVersionMin >= k10_5 )
+                               if ( fReaderOptions.fVersionMin >= ObjectFile::ReaderOptions::k10_5 )
                                        fZeroPageSize = 0x100000000ULL;
                                else
                                        fZeroPageSize = 0x1000; // 10.4 dyld may not be able to handle >4GB zero page
@@ -1838,16 +2679,114 @@ void Options::checkIllegalOptionCombinations()
                        case Options::kDynamicBundle:
                        case Options::kObjectFile:
                        case Options::kDyld:
-                               throw "-pagezero_size option can only be used when linking a main executable";
-               }       
+                               if ( fZeroPageSize != 0 )
+                                       throw "-pagezero_size option can only be used when linking a main executable";
+               }
        }
 
        // -dead_strip and -r are incompatible
        if ( (fDeadStrip != kDeadStripOff) && (fOutputKind == Options::kObjectFile) )
                throw "-r and -dead_strip cannot be used together\n";
 
+       // can't use -rpath unless targeting 10.5 or later
+       if ( fRPaths.size() > 0 ) {
+               if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_5 ) 
+                       throw "-rpath can only be used when targeting Mac OS X 10.5 or later\n";
+               switch ( fOutputKind ) {
+                       case Options::kDynamicExecutable:
+                       case Options::kDynamicLibrary:
+                       case Options::kDynamicBundle:
+                               break;
+                       case Options::kStaticExecutable:
+                       case Options::kObjectFile:
+                       case Options::kDyld:
+                               throw "-rpath can only be used when creating a dynamic final linked image";
+               }
+       }
+       
+       // check -pie is only used when building a dynamic main executable for 10.5
+       if ( fPositionIndependentExecutable ) {
+               if ( fOutputKind != Options::kDynamicExecutable )
+                       throw "-pie can only be used when linking a main executable";
+               if ( fReaderOptions.fVersionMin < ObjectFile::ReaderOptions::k10_5 ) 
+                       throw "-pie can only be used when targeting Mac OS X 10.5 or later";
+       }
 }
 
 
 
+void Options::checkForClassic(int argc, const char* argv[])
+{
+       // scan options
+       bool archFound = false;
+       bool staticFound = false;
+       bool dtraceFound = false;
+       bool rFound = false;
+       bool creatingMachKernel = false;
+       bool newLinker = false;
 
+       for(int i=0; i < argc; ++i) {
+               const char* arg = argv[i];
+               if ( arg[0] == '-' ) {
+                       if ( strcmp(arg, "-arch") == 0 ) {
+                               parseArch(argv[++i]);
+                               archFound = true;
+                       }
+                       else if ( strcmp(arg, "-static") == 0 ) {
+                               staticFound = true;
+                       }
+                       else if ( strcmp(arg, "-dtrace") == 0 ) {
+                               dtraceFound = true;
+                       }
+                       else if ( strcmp(arg, "-r") == 0 ) {
+                               rFound = true;
+                       }
+                       else if ( strcmp(arg, "-new_linker") == 0 ) {
+                               newLinker = true;
+                       }
+                       else if ( strcmp(arg, "-classic_linker") == 0 ) {
+                               // ld_classic does not understand this option, so remove it
+                               for(int j=i; j < argc; ++j)
+                                       argv[j] = argv[j+1];
+                               this->gotoClassicLinker(argc-1, argv);
+                       }
+                       else if ( strcmp(arg, "-o") == 0 ) {
+                               const char* outfile = argv[++i];
+                               if ( (outfile != NULL) && (strstr(outfile, "/mach_kernel") != NULL) )
+                                       creatingMachKernel = true;
+                       }
+               }
+       }
+       
+       // -dtrace only supported by new linker
+       if( dtraceFound )
+               return;
+
+       if( archFound ) {
+               switch ( fArchitecture ) {
+               case CPU_TYPE_POWERPC:
+               case CPU_TYPE_I386:
+//                     if ( staticFound && (rFound || !creatingMachKernel) ) {
+                       if ( staticFound && !newLinker ) {
+                               // this environment variable will disable use of ld_classic for -static links
+                               if ( getenv("LD_NO_CLASSIC_LINKER_STATIC") == NULL )
+                                       this->gotoClassicLinker(argc, argv);
+                       }
+                       break;
+               }
+       }
+       else {
+               // work around for VSPTool
+               if ( staticFound )
+                       this->gotoClassicLinker(argc, argv);
+       }
+
+}
+
+void Options::gotoClassicLinker(int argc, const char* argv[])
+{
+       argv[0] = "ld_classic";
+       execvp(argv[0], (char**)argv);
+       fprintf(stderr, "can't exec ld_classic\n");
+       exit(1);
+}
index ad2e45b2eb3aedce7558336b8fb926210feccc05..367075600ce9b0db1725ad2280237cccaab43e06 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Apple  Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -39,12 +39,11 @@ void throwf (const char* format, ...) __attribute__ ((noreturn));
 class DynamicLibraryOptions
 {
 public:
-       DynamicLibraryOptions() : fWeakImport(false), fReExport(false), fBundleLoader(false), fInstallPathOverride(NULL) {}
+       DynamicLibraryOptions() : fWeakImport(false), fReExport(false), fBundleLoader(false) {}
 
        bool            fWeakImport;
        bool            fReExport;
        bool            fBundleLoader;
-       const char* fInstallPathOverride;
 };
 
 //
@@ -71,7 +70,8 @@ public:
                                                                                  kWeakReferenceMismatchNonWeak };
        enum CommonsMode { kCommonsIgnoreDylibs, kCommonsOverriddenByDylibs, kCommonsConflictsDylibsError };
        enum DeadStripMode { kDeadStripOff, kDeadStripOn, kDeadStripOnPlusUnusedInits };
-       enum VersionMin { kMinUnset, k10_1, k10_2, k10_3, k10_4, k10_5 };
+       enum UUIDMode { kUUIDNone, kUUIDRandom, kUUIDContent };
+       enum LocalSymbolHandling { kLocalSymbolsAll, kLocalSymbolsNone, kLocalSymbolsSelectiveInclude, kLocalSymbolsSelectiveExclude };
 
        struct FileInfo {
                const char*                             path;
@@ -94,13 +94,34 @@ public:
                uint8_t                                 alignment;
        };
 
+       struct OrderedSymbol {
+               const char*                             symbolName;
+               const char*                             objectFileName;
+       };
+
+       struct SegmentStart {
+               const char*                             name;
+               uint64_t                                address;
+       };
+       
+       struct SegmentProtect {
+               const char*                             name;
+               uint32_t                                max;
+               uint32_t                                init;
+       };
+       
+       struct DylibOverride {
+               const char*                             installName;
+               const char*                             useInstead;
+       };
+
+
        const ObjectFile::ReaderOptions&        readerOptions();
        const char*                                                     getOutputFilePath();
        std::vector<FileInfo>&                          getInputFiles();
 
        cpu_type_t                                      architecture();
        OutputKind                                      outputKind();
-       bool                                            stripLocalSymbols();
        bool                                            prebind();
        bool                                            bindAtLoad();
        bool                                            fullyLoadArchives();
@@ -113,6 +134,7 @@ public:
        uint64_t                                        baseAddress();
        bool                                            keepPrivateExterns();   // only for kObjectFile
        bool                                            interposable();                 // only for kDynamicLibrary
+       bool                                            needsModuleTable();             // only for kDynamicLibrary
        bool                                            hasExportRestrictList();
        bool                                            allGlobalsAreDeadStripRoots();
        bool                                            shouldExport(const char*);
@@ -122,13 +144,10 @@ public:
        bool                                            traceArchives();
        DeadStripMode                           deadStrip();
        UndefinedTreatment                      undefinedTreatment();
-       VersionMin                                      macosxVersionMin();
+       ObjectFile::ReaderOptions::VersionMin   macosxVersionMin();
        bool                                            messagesPrefixedWithArchitecture();
        Treatment                                       picTreatment();
        WeakReferenceMismatchTreatment  weakReferenceMismatchTreatment();
-       Treatment                                       multipleDefinitionsInDylibs();
-       Treatment                                       overridingDefinitionInDependentDylib();
-       bool                                            warnOnMultipleDefinitionsInObjectFiles();
        const char*                                     umbrellaName();
        std::vector<const char*>&       allowableClients();
        const char*                                     clientName();
@@ -142,19 +161,41 @@ public:
        std::vector<const char*>&       initialUndefines();
        bool                                            printWhyLive(const char* name);
        uint32_t                                        minimumHeaderPad();
+       bool                                            maxMminimumHeaderPad() { return fMaxMinimumHeaderPad; }
        std::vector<ExtraSection>&      extraSections();
        std::vector<SectionAlignment>&  sectionAlignments();
        CommonsMode                                     commonsMode();
        bool                                            warnCommons();
        bool                                            keepRelocations();
-       std::vector<const char*>&   traceSymbols();
        FileInfo                                        findFile(const char* path);
-       bool                                            emitUUID();
+       UUIDMode                                        getUUIDMode() { return fUUIDMode; }
        bool                                            warnStabs();
        bool                                            pauseAtEnd() { return fPause; }
        bool                                            printStatistics() { return fStatistics; }
        bool                                            printArchPrefix() { return fMessagesPrefixedWithArchitecture; }
-       bool                                            makeTentativeDefinitionsReal() { return fMakeTentativeDefinitionsReal; }
+       void                                            gotoClassicLinker(int argc, const char* argv[]);
+       bool                                            sharedRegionEligible() { return fSharedRegionEligible; }
+       bool                                            printOrderFileStatistics() { return fPrintOrderFileStatistics; }
+       const char*                                     dTraceScriptName() { return fDtraceScriptName; }
+       bool                                            dTrace() { return (fDtraceScriptName != NULL); }
+       std::vector<OrderedSymbol>&     orderedSymbols() { return fOrderedSymbols; }
+       bool                                            splitSeg() { return fSplitSegs; }
+       uint64_t                                        baseWritableAddress() { return fBaseWritableAddress; }
+       std::vector<SegmentStart>&      customSegmentAddresses() { return fCustomSegmentAddresses; }
+       std::vector<SegmentProtect>& customSegmentProtections() { return fCustomSegmentProtections; }
+       bool                                            saveTempFiles() { return fSaveTempFiles; }
+       const std::vector<const char*>&   rpaths() { return fRPaths; }
+       bool                                            readOnlyx86Stubs() { return fReadOnlyx86Stubs; }
+       std::vector<DylibOverride>&     dylibOverrides() { return fDylibOverrides; }
+       const char*                                     generatedMapPath() { return fMapPath; }
+       bool                                            positionIndependentExecutable() { return fPositionIndependentExecutable; }
+       Options::FileInfo                       findFileUsingPaths(const char* path);
+       bool                                            deadStripDylibs() { return fDeadStripDylibs; }
+       bool                                            allowedUndefined(const char* name) { return ( fAllowedUndefined.find(name) != fAllowedUndefined.end() ); }
+       bool                                            someAllowedUndefines() { return (fAllowedUndefined.size() != 0); }
+       LocalSymbolHandling                     localSymbolHandling() { return fLocalSymbolHandling; }
+       bool                                            keepLocalSymbol(const char* symbolName);
+       bool                                            emitWarnings() { return !fSuppressWarnings; }
 
 private:
        class CStringEquals
@@ -167,6 +208,22 @@ private:
        enum ExportMode { kExportDefault, kExportSome, kDontExportSome };
        enum LibrarySearchMode { kSearchDylibAndArchiveInEachDir, kSearchAllDirsForDylibsThenAllDirsForArchives };
 
+       class SetWithWildcards {
+       public:
+               void                                    insert(const char*);
+               bool                                    contains(const char*);
+               NameSet::iterator               regularBegin()  { return fRegular.begin(); }
+               NameSet::iterator               regularEnd()    { return fRegular.end(); }
+       private:
+               bool                                    hasWildCards(const char*);
+               bool                                    wildCardMatch(const char* pattern, const char* candidate);
+               bool                                    inCharRange(const char*& range, unsigned char c);
+
+               NameSet                                                 fRegular;
+               std::vector<const char*>                fWildCard;
+       };
+
+
        void                                            parse(int argc, const char* argv[]);
        void                                            checkIllegalOptionCombinations();
        void                                            buildSearchPaths(int argc, const char* argv[]);
@@ -178,21 +235,28 @@ private:
                                                                                         FileInfo& result);
        uint32_t                                        parseVersionNumber(const char*);
        void                                            parseSectionOrderFile(const char* segment, const char* section, const char* path);
+       void                                            parseOrderFile(const char* path, bool cstring);
        void                                            addSection(const char* segment, const char* section, const char* path);
        void                                            addSubLibrary(const char* name);
        void                                            loadFileList(const char* fileOfPaths);
        uint64_t                                        parseAddress(const char* addr);
-       void                                            loadExportFile(const char* fileOfExports, const char* option, NameSet& set);
+       void                                            loadExportFile(const char* fileOfExports, const char* option, SetWithWildcards& set);
+       void                                            parseAliasFile(const char* fileOfAliases);
        void                                            parsePreCommandLineEnvironmentSettings();
        void                                            parsePostCommandLineEnvironmentSettings();
        void                                            setUndefinedTreatment(const char* treatment);
        void                                            setVersionMin(const char* version);
        void                                            setWeakReferenceMismatchTreatment(const char* treatment);
-       void                                            setDylibInstallNameOverride(const char* paths);
+       void                                            addDylibOverride(const char* paths);
        void                                            addSectionAlignment(const char* segment, const char* section, const char* alignment);
        CommonsMode                                     parseCommonsTreatment(const char* mode);
        Treatment                                       parseTreatment(const char* treatment);
        void                                            reconfigureDefaults();
+       void                                            checkForClassic(int argc, const char* argv[]);
+       void                                            parseSegAddrTable(const char* segAddrPath, const char* installPath);
+       void                                            addLibrary(const FileInfo& info);
+       void                                            warnObsolete(const char* arg);
+       uint32_t                                        parseProtection(const char* prot);
 
 
        ObjectFile::ReaderOptions                       fReaderOptions;
@@ -202,70 +266,82 @@ private:
        OutputKind                                                      fOutputKind;
        bool                                                            fPrebind;
        bool                                                            fBindAtLoad;
-       bool                                                            fStripLocalSymbols;
        bool                                                            fKeepPrivateExterns;
        bool                                                            fInterposable;
+       bool                                                            fNeedsModuleTable;
        bool                                                            fIgnoreOtherArchFiles;
        bool                                                            fForceSubtypeAll;
        DeadStripMode                                           fDeadStrip;
-       VersionMin                                                      fVersionMin;
        NameSpace                                                       fNameSpace;
        uint32_t                                                        fDylibCompatVersion;
        uint32_t                                                        fDylibCurrentVersion;
        const char*                                                     fDylibInstallName;
+       const char*                                                     fFinalName;
        const char*                                                     fEntryName;
        uint64_t                                                        fBaseAddress;
-       NameSet                                                         fExportSymbols;
-       NameSet                                                         fDontExportSymbols;
+       uint64_t                                                        fBaseWritableAddress;
+       bool                                                            fSplitSegs;
+       SetWithWildcards                                        fExportSymbols;
+       SetWithWildcards                                        fDontExportSymbols;
        ExportMode                                                      fExportMode;
        LibrarySearchMode                                       fLibrarySearchMode;
        UndefinedTreatment                                      fUndefinedTreatment;
        bool                                                            fMessagesPrefixedWithArchitecture;
-       Treatment                                                       fPICTreatment;
        WeakReferenceMismatchTreatment          fWeakReferenceMismatchTreatment;
-       Treatment                                                       fMultiplyDefinedDynamic;
-       Treatment                                                       fMultiplyDefinedUnused;
-       bool                                                            fWarnOnMultiplyDefined;
        std::vector<const char*>                        fSubUmbellas;
        std::vector<const char*>                        fSubLibraries;
        std::vector<const char*>                        fAllowableClients;
+       std::vector<const char*>                        fRPaths;
        const char*                                                     fClientName;
        const char*                                                     fUmbrellaName;
        const char*                                                     fInitFunctionName;
        const char*                                                     fDotOutputFile;
        const char*                                                     fExecutablePath;
        const char*                                                     fBundleLoader;
+       const char*                                                     fDtraceScriptName;
+       const char*                                                     fSegAddrTablePath;
+       const char*                                                     fMapPath;
        uint64_t                                                        fZeroPageSize;
        uint64_t                                                        fStackSize;
        uint64_t                                                        fStackAddr;
        bool                                                            fExecutableStack;
        uint32_t                                                        fMinimumHeaderPad;
        CommonsMode                                                     fCommonsMode;
+       UUIDMode                                                        fUUIDMode;
+       SetWithWildcards                                        fLocalSymbolsIncluded;
+       SetWithWildcards                                        fLocalSymbolsExcluded;
+       LocalSymbolHandling                                     fLocalSymbolHandling;
        bool                                                            fWarnCommons;
        bool                                                            fVerbose;
        bool                                                            fKeepRelocations;
-       bool                                                            fEmitUUID;
        bool                                                            fWarnStabs;
        bool                                                            fTraceDylibSearching;
        bool                                                            fPause;
        bool                                                            fStatistics;
        bool                                                            fPrintOptions;
-       bool                                                            fMakeTentativeDefinitionsReal;
+       bool                                                            fSharedRegionEligible;
+       bool                                                            fPrintOrderFileStatistics;
+       bool                                                            fReadOnlyx86Stubs;
+       bool                                                            fPositionIndependentExecutable;
+       bool                                                            fMaxMinimumHeaderPad;
+       bool                                                            fDeadStripDylibs;
+       bool                                                            fSuppressWarnings;
        std::vector<const char*>                        fInitialUndefines;
+       NameSet                                                         fAllowedUndefined;
        NameSet                                                         fWhyLive;
-       std::vector<const char*>                        fTraceSymbols;
-       unsigned long                                           fLimitUndefinedSymbols;
        std::vector<ExtraSection>                       fExtraSections;
        std::vector<SectionAlignment>           fSectionAlignments;
+       std::vector<OrderedSymbol>                      fOrderedSymbols;
+       std::vector<SegmentStart>                       fCustomSegmentAddresses;
+       std::vector<SegmentProtect>                     fCustomSegmentProtections;
+       std::vector<DylibOverride>                      fDylibOverrides; 
 
        std::vector<const char*>                        fLibrarySearchPaths;
        std::vector<const char*>                        fFrameworkSearchPaths;
        std::vector<const char*>                        fSDKPaths;
-       bool                                                            fAllowStackExecute;
-
+       bool                                                            fSaveTempFiles;
 };
 
 
 
-
 #endif // __OPTIONS__
diff --git a/src/SectCreate.cpp b/src/SectCreate.cpp
deleted file mode 100644 (file)
index 5677c32..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
- *
- * Copyright (c) 2005-2006 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 <vector>
-
-#include "ObjectFile.h"
-
-namespace SectCreate {
-
-
-class Segment : public ObjectFile::Segment
-{
-public:
-                                                               Segment(const char* name)               { fName = name; }
-       virtual const char*                     getName() const                                 { return fName; }
-       virtual bool                            isContentReadable() const               { return true; }
-       virtual bool                            isContentWritable() const               { return false; }
-       virtual bool                            isContentExecutable() const             { return false; }
-private:
-       const char*                                     fName;
-};
-
-
-class Reader : public ObjectFile::Reader 
-{
-public:
-                                                                                               Reader(const char* segmentName, const char* sectionName, const char* path, const uint8_t fileContent[], uint64_t fileLength);
-       virtual                                                                         ~Reader();
-       
-       virtual const char*                                                             getPath()                                                               { return fPath; }
-       virtual time_t                                                                  getModificationTime()                                   { return 0; }
-       virtual DebugInfoKind                                                   getDebugInfoKind()                                              { return ObjectFile::Reader::kDebugInfoNone; }
-       virtual std::vector<class ObjectFile::Atom*>&   getAtoms()                                                              { return fAtoms; }
-       virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) { return NULL; }
-       virtual std::vector<Stab>*                                              getStabs()                                                              { return NULL; }
-
-private:
-       const char*                                                                             fPath;
-       std::vector<class ObjectFile::Atom*>                    fAtoms;
-};
-
-
-class Atom : public ObjectFile::Atom {
-public:
-       virtual ObjectFile::Reader*                                     getFile() const                         { return &fOwner; }
-       virtual bool                                                            getTranslationUnitSource(const char** dir, const char** name) const { return false; }
-       virtual const char*                                                     getName() const                         { return NULL; }
-       virtual const char*                                                     getDisplayName() const;
-       virtual Scope                                                           getScope() const                        { return ObjectFile::Atom::scopeTranslationUnit; }
-       virtual DefinitionKind                                          getDefinitionKind() const       { return kRegularDefinition; }
-       virtual SymbolTableInclusion                            getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
-       virtual bool                                                            dontDeadStrip() const           { return true; }
-       virtual bool                                                            isZeroFill() const                      { return false; }
-       virtual uint64_t                                                        getSize() const                         { return fFileLength; }
-       virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return fgEmptyReferenceList; }
-       virtual bool                                                            mustRemainInSection() const { return false; }
-       virtual const char*                                                     getSectionName() const          { return fSectionName; }
-       virtual Segment&                                                        getSegment() const                      { return fSegment; }
-       virtual bool                                                            requiresFollowOnAtom() const{ return false; }
-       virtual ObjectFile::Atom&                                       getFollowOnAtom() const         { return *((ObjectFile::Atom*)NULL); }
-       virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
-       virtual ObjectFile::Alignment                           getAlignment() const            { return ObjectFile::Alignment(4); }
-       virtual void                                                            copyRawContent(uint8_t buffer[]) const;
-
-       virtual void                                                            setScope(Scope)                         { }
-
-protected:
-       friend class Reader;
-       
-                                                                                       Atom(Reader& owner, Segment& segment, const char* sectionName, const uint8_t fileContent[], uint64_t fileLength) 
-                                                                                               : fOwner(owner), fSegment(segment), fSectionName(sectionName), fFileContent(fileContent), fFileLength(fileLength) { }
-       virtual                                                                 ~Atom() {}
-       
-       Reader&                                                                 fOwner;
-       Segment&                                                                fSegment;
-       const char*                                                             fSectionName;
-       const uint8_t*                                                  fFileContent;
-       uint64_t                                                                fFileLength;
-       
-       static std::vector<ObjectFile::Reference*> fgEmptyReferenceList;
-};
-
-
-std::vector<ObjectFile::Reference*> Atom::fgEmptyReferenceList;
-
-
-
-Reader::Reader(const char* segmentName, const char* sectionName, const char* path, const uint8_t fileContent[], uint64_t fileLength)
- : fPath(path)
-{
-       fAtoms.push_back(new Atom(*this, *(new Segment(segmentName)), sectionName, fileContent, fileLength));
-}
-
-Reader::~Reader()
-{
-}
-
-
-const char*     Atom::getDisplayName() const
-{
-       static char name[64];
-       sprintf(name, "-sectcreate %s %s", fSegment.getName(), fSectionName);
-       return name;
-}
-
-
-void Atom::copyRawContent(uint8_t buffer[]) const
-{
-       memcpy(buffer, fFileContent, fFileLength);
-}
-
-Reader* MakeReader(const char* segmentName, const char* sectionName, const char* path, const uint8_t fileContent[], uint64_t fileLength)
-{
-       return new Reader(segmentName, sectionName, path, fileContent, fileLength);
-}
-
-
-
-};
-
-
-
-
-
-
-
index d088f9a4f52c654d43c208a4b287d99c8553574c..ff530371c37d53812d5697e8342ee42f8af90b80 100644 (file)
@@ -1,6 +1,5 @@
-/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
- *
- * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
+ * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -35,7 +34,7 @@
 #include <mach/mach_init.h>
 #include <mach/mach_host.h>
 #include <mach-o/fat.h>
-
+#include <dlfcn.h>
 
 #include <string>
 #include <map>
@@ -45,6 +44,8 @@
 #include <list>
 #include <algorithm>
 #include <ext/hash_map>
+#include <dlfcn.h>
+#include <AvailabilityMacros.h>
 
 #include "Options.h"
 
 #include "MachOReaderDylib.hpp"
 #include "MachOWriterExecutable.hpp"
 
-#include "SectCreate.h"
-
-#if 0
-static void dumpAtom(ObjectFile::Atom* atom)
-{
-       //printf("atom:    %p\n", atom);
-
-       // name
-       printf("name:    %s\n",  atom->getDisplayName());
-
-       // scope
-       switch ( atom->getScope() ) {
-               case ObjectFile::Atom::scopeTranslationUnit:
-                       printf("scope:   translation unit\n");
-                       break;
-               case ObjectFile::Atom::scopeLinkageUnit:
-                       printf("scope:   linkage unit\n");
-                       break;
-               case ObjectFile::Atom::scopeGlobal:
-                       printf("scope:   global\n");
-                       break;
-               default:
-                       printf("scope:   unknown\n");
-       }
-
-       // kind
-       switch ( atom->getDefinitinonKind() ) {
-               case ObjectFile::Atom::kRegularDefinition:
-                       printf("kind:     regular\n");
-                       break;
-               case ObjectFile::Atom::kWeakDefinition:
-                       printf("kind:     weak\n");
-                       break;
-               case ObjectFile::Atom::kTentativeDefinition:
-                       printf("kind:     tentative\n");
-                       break;
-               case ObjectFile::Atom::kExternalDefinition:
-                       printf("kind:     import\n");
-                       break;
-               case ObjectFile::Atom::kExternalWeakDefinition:
-                       printf("kind:     weak import\n");
-                       break;
-               default:
-                       printf("scope:   unknown\n");
-       }
-
-       // segment and section
-       printf("section: %s,%s\n", atom->getSegment().getName(), atom->getSectionName());
-
-       // attributes
-       printf("attrs:   ");
-       if ( atom->dontDeadStrip() )
-               printf("dont-dead-strip ");
-       if ( atom->isZeroFill() )
-               printf("zero-fill ");
-       printf("\n");
-
-       // size
-       printf("size:    0x%012llX\n", atom->getSize());
-
-       // content
-       uint8_t content[atom->getSize()];
-       atom->copyRawContent(content);
-       printf("content: ");
-       if ( strcmp(atom->getSectionName(), "__cstring") == 0 ) {
-               printf("\"%s\"", content);
-       }
-       else {
-               for (unsigned int i=0; i < sizeof(content); ++i)
-                       printf("%02X ", content[i]);
-       }
-       printf("\n");
+#define LLVM_SUPPORT 0
+#if LLVM_SUPPORT
+#include "LLVMReader.hpp"
+#endif
 
-       // references
-       std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
-       const int refCount = references.size();
-       printf("references: (%u)\n", refCount);
-       for (int i=0; i < refCount; ++i) {
-               ObjectFile::Reference* ref = references[i];
-               printf("   %s\n", ref->getDescription());
-       }
 
-       // attributes
+#include "OpaqueSection.hpp"
 
-}
-
-#endif
 
 class CStringComparor
 {
@@ -160,7 +83,7 @@ class Section : public ObjectFile::Section
 public:
        static Section* find(const char* sectionName, const char* segmentName, bool zeroFill);
        static void             assignIndexes();
-
+       const char*             getName() { return fSectionName; }
 private:
                                        Section(const char* sectionName, const char* segmentName, bool zeroFill);
 
@@ -169,6 +92,7 @@ private:
                bool operator()(Section* left, Section* right);
        };
 
+       typedef __gnu_cxx::hash_map<const char*, uint32_t, __gnu_cxx::hash<const char*>, CStringEquals> NameToOrdinal;
        typedef __gnu_cxx::hash_map<const char*, class Section*, __gnu_cxx::hash<const char*>, CStringEquals> NameToSection;
        //typedef std::map<const char*, class Section*, CStringComparor> NameToSection;
 
@@ -178,15 +102,18 @@ private:
 
        static NameToSection                    fgMapping;
        static std::vector<Section*>    fgSections;
+       static NameToOrdinal                    fgSegmentDiscoverOrder;
 };
 
 Section::NameToSection Section::fgMapping;
 std::vector<Section*>  Section::fgSections;
+Section::NameToOrdinal Section::fgSegmentDiscoverOrder;
 
 Section::Section(const char* sectionName, const char* segmentName, bool zeroFill)
  : fSectionName(sectionName), fSegmentName(segmentName), fZeroFill(zeroFill)
 {
-       //fprintf(stderr, "new Section(%s, %s)\n", sectionName, segmentName);
+       this->fIndex = fgSections.size();
+       //fprintf(stderr, "new Section(%s, %s) => %p, %u\n", sectionName, segmentName, this, this->getIndex());
 }
 
 Section* Section::find(const char* sectionName, const char* segmentName, bool zeroFill)
@@ -204,7 +131,6 @@ Section* Section::find(const char* sectionName, const char* segmentName, bool ze
 
        // does not exist, so make a new one
        Section* sect = new Section(sectionName, segmentName, zeroFill);
-       sect->fIndex = fgMapping.size();
        fgMapping[sectionName] = sect;
        fgSections.push_back(sect);
 
@@ -213,6 +139,10 @@ Section* Section::find(const char* sectionName, const char* segmentName, bool ze
                find("__textcoal_nt", "__TEXT", false);
        }
 
+       // remember segment discovery order
+       if ( fgSegmentDiscoverOrder.find(segmentName) == fgSegmentDiscoverOrder.end() ) 
+               fgSegmentDiscoverOrder[segmentName] = fgSegmentDiscoverOrder.size();
+
        return sect;
 }
 
@@ -226,29 +156,24 @@ int Section::Sorter::segmentOrdinal(const char* segName)
                return 3;
        if ( strcmp(segName, "__OBJC") == 0 )
                return 4;
+       if ( strcmp(segName, "__OBJC2") == 0 )
+               return 5;
        if ( strcmp(segName, "__LINKEDIT") == 0 )
                return INT_MAX; // linkedit segment should always sort last
        else
-               return 5;
+               return fgSegmentDiscoverOrder[segName]+6;
 }
 
 
 bool Section::Sorter::operator()(Section* left, Section* right)
 {
        // Segment is primary sort key
-       const char* leftSegName = left->fSegmentName;
-       const char* rightSegName = right->fSegmentName;
-       int segNameCmp = strcmp(leftSegName, rightSegName);
-       if ( segNameCmp != 0 )
-       {
-               int leftSegOrdinal = segmentOrdinal(leftSegName);
-               int rightSegOrdinal = segmentOrdinal(rightSegName);
-               if ( leftSegOrdinal < rightSegOrdinal )
-                       return true;
-               if ( leftSegOrdinal == rightSegOrdinal )
-                       return segNameCmp < 0;
+       int leftSegOrdinal = segmentOrdinal(left->fSegmentName);
+       int rightSegOrdinal = segmentOrdinal(right->fSegmentName);
+       if ( leftSegOrdinal < rightSegOrdinal )
+               return true;
+       if ( leftSegOrdinal > rightSegOrdinal )
                return false;
-       }
 
        // zerofill section sort to the end
        if ( !left->fZeroFill && right->fZeroFill )
@@ -261,8 +186,8 @@ bool Section::Sorter::operator()(Section* left, Section* right)
 }
 
 void Section::assignIndexes()
-{
-       //printf("unsorted:\n");
+{      
+       //printf("unsorted sections:\n");
        //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
        //      printf("section: name=%s, segment: name=%s, discovery order=%d\n", (*it)->fSectionName, (*it)->fSegmentName, (*it)->fIndex);
        //}
@@ -275,13 +200,13 @@ void Section::assignIndexes()
        for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++)
                (*it)->fIndex = newOrder++;
 
-       //printf("sorted:\n");
+       //printf("sorted sections:\n");
        //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
-       //      printf("section: name=%s\n", (*it)->fSectionName);
+       //      printf("section: index=%d, obj=%p, name=%s\n", (*it)->fIndex, (*it), (*it)->fSectionName);
        //}
 }
 
-class Linker {
+class Linker : public ObjectFile::Reader::DylibHander {
 public:
                                                Linker(int argc, const char* argv[]);
 
@@ -291,10 +216,13 @@ public:
        bool                            isInferredArchitecture();
        void                            createReaders();
        void                            createWriter();
-       void                            addInputFile(ObjectFile::Reader* reader);
+       void                            addInputFile(ObjectFile::Reader* reader, const Options::FileInfo& );
        void                            setOutputFile(ExecutableFile::Writer* writer);
        void                            link();
-
+       void                            optimize();
+       
+       // implemenation from ObjectFile::Reader::DylibHander
+       virtual ObjectFile::Reader* findDylib(const char* installPath, const char* fromPath);
 
 private:
        struct WhyLiveBackChain
@@ -307,13 +235,20 @@ private:
        void                            addAtom(ObjectFile::Atom& atom);
        void                            addAtoms(std::vector<class ObjectFile::Atom*>& atoms);
        void                            buildAtomList();
+       void                            processDylibs();
+       void                            updateContraints(ObjectFile::Reader* reader);
        void                            loadAndResolve();
+       void                            processDTrace();
+       void                            checkObjC();
        void                            loadUndefines();
        void                            checkUndefines();
        void                            addWeakAtomOverrides();
        void                            resolveReferences();
        void                            deadStripResolve();
        void                            addLiveRoot(const char* name);
+       ObjectFile::Atom*       findAtom(const Options::OrderedSymbol& pair);
+       void                            logArchive(ObjectFile::Reader* reader);
+       void                            sortSections();
        void                            sortAtoms();
        void                            tweakLayout();
        void                            writeDotOutput();
@@ -332,17 +267,18 @@ private:
        char*                           commatize(uint64_t in, char* out);
        void                            getVMInfo(vm_statistics_data_t& info);
        cpu_type_t                      inferArchitecture();
-
-       void                            resolve(ObjectFile::Reference* reference);
-       void                            resolveFrom(ObjectFile::Reference* reference);
-       void                            addJustInTimeAtoms(const char* name);
+       void                            addDtraceProbe(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* probeName);
+       void                            checkDylibClientRestrictions(ObjectFile::Reader* reader);
+       void                            logDylib(ObjectFile::Reader* reader, bool indirect);
+       
+       void                                                                    resolve(ObjectFile::Reference* reference);
+       void                                                                    resolveFrom(ObjectFile::Reference* reference);
+       std::vector<class ObjectFile::Atom*>*   addJustInTimeAtoms(const char* name);
+       void                                                                    addJustInTimeAtomsAndMarkLive(const char* name);
 
        ObjectFile::Reader*     addDylib(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
        ObjectFile::Reader*     addObject(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
        ObjectFile::Reader*     addArchive(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
-       void                            addIndirectLibraries(ObjectFile::Reader* reader);
-       bool                            haveIndirectLibrary(const char* path, ObjectFile::Reader* reader);
-       bool                            haveDirectLibrary(const char* path);
 
        void                            logTraceInfo(const char* format, ...);
 
@@ -356,20 +292,34 @@ private:
                ObjectFile::Atom*       find(const char* name);
                unsigned int            getRequireCount() { return fRequireCount; }
                void                            getNeededNames(bool andWeakDefintions, std::vector<const char*>& undefines);
-       private:
                typedef __gnu_cxx::hash_map<const char*, ObjectFile::Atom*, __gnu_cxx::hash<const char*>, CStringEquals> Mapper;
+       private:
                Linker&                         fOwner;
                Mapper                          fTable;
                unsigned int            fRequireCount;
        };
 
-       struct AtomSorter
+       class AtomSorter
        {
-               bool operator()(ObjectFile::Atom* left, ObjectFile::Atom* right);
+       public:
+               AtomSorter(std::map<const ObjectFile::Atom*, uint32_t>* map) : fOverriddenOrdinalMap(map) {}
+               bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right);
+       private:
+               std::map<const ObjectFile::Atom*, uint32_t>*    fOverriddenOrdinalMap;
        };
 
        typedef std::map<const char*, uint32_t, CStringComparor> SectionOrder;
 
+       struct DTraceProbeInfo {
+               DTraceProbeInfo(const ObjectFile::Atom* a, uint32_t o, const char* n) : atom(a), offset(o), probeName(n) {}
+               const ObjectFile::Atom*                 atom;
+               uint32_t                                                offset;
+               const char*                                             probeName;
+       };
+       typedef __gnu_cxx::hash_map<const char*, std::vector<DTraceProbeInfo>, __gnu_cxx::hash<const char*>, CStringEquals>     ProviderToProbes;
+       typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals>  CStringSet;
+       typedef __gnu_cxx::hash_map<const char*, ObjectFile::Reader*, __gnu_cxx::hash<const char*>, CStringEquals>      InstallNameToReader;
+
        struct IndirectLibrary {
                const char*                                                     path;
                uint64_t                                                        fileLen;
@@ -382,33 +332,42 @@ private:
 
        Options                                                                                         fOptions;
        SymbolTable                                                                                     fGlobalSymbolTable;
-       unsigned int                                                                            fWeakSymbolsAddedCount;
+       uint32_t                                                                                        fNextInputOrdinal;
        std::vector<class ObjectFile::Reader*>                          fInputFiles;
        ExecutableFile::Writer*                                                         fOutputFile;
-       std::vector<ExecutableFile::DyLibUsed>                          fDynamicLibraries;
-       std::list<IndirectLibrary>                                                      fIndirectDynamicLibraries;
+       InstallNameToReader                                                                     fDylibMap;
+       std::map<ObjectFile::Reader*,DynamicLibraryOptions> fDylibOptionsMap;
+       std::set<ObjectFile::Reader*>                                           fDylibsProcessed;
+       ObjectFile::Reader*                                                                     fBundleLoaderReader;
        std::vector<class ObjectFile::Reader*>                          fReadersThatHaveSuppliedAtoms;
        std::vector<class ObjectFile::Atom*>                            fAllAtoms;
+       std::set<class ObjectFile::Reader*>                                     fArchiveReaders;
+       std::set<class ObjectFile::Reader*>                                     fArchiveReadersLogged;
        std::set<class ObjectFile::Atom*>                                       fDeadAtoms;
        std::set<ObjectFile::Atom*>                                                     fLiveAtoms;
        std::set<ObjectFile::Atom*>                                                     fLiveRootAtoms;
        std::vector<class ObjectFile::Reader::Stab>                     fStabs;
        std::vector<class ObjectFile::Atom*>                            fAtomsWithUnresolvedReferences;
+       std::vector<DTraceProbeInfo>                                            fDtraceProbes;
+       std::vector<DTraceProbeInfo>                                            fDtraceProbeSites;
+       std::vector<DTraceProbeInfo>                                            fDtraceIsEnabledSites;
+       std::map<const ObjectFile::Atom*,CStringSet>            fDtraceAtomToTypes;
        bool                                                                                            fCreateUUID;
+       bool                                                                                            fCanScatter;
        SectionOrder                                                                            fSectionOrder;
-       unsigned int                                                                            fNextSortOrder;
-       unsigned int                                                                            fNextObjectFileOrder;
        cpu_type_t                                                                                      fArchitecture;
        const char*                                                                                     fArchitectureName;
        bool                                                                                            fArchitectureInferred;
        bool                                                                                            fDirectLibrariesComplete;
+       bool                                                                                            fBiggerThanTwoGigOutput;
        uint64_t                                                                                        fOutputFileSize;
+       uint64_t                                                                                        fTotalZeroFillSize;
+       uint64_t                                                                                        fTotalSize;
        uint64_t                                                                                        fStartTime;
        uint64_t                                                                                        fStartCreateReadersTime;
        uint64_t                                                                                        fStartCreateWriterTime;
        uint64_t                                                                                        fStartBuildAtomsTime;
-       uint64_t                                                                                        fStartLoadUndefinesTime;
-       uint64_t                                                                                        fStartResolveTime;
+       uint64_t                                                                                        fStartLoadAndResolveTime;
        uint64_t                                                                                        fStartSortTime;
        uint64_t                                                                                        fStartDebugTime;
        uint64_t                                                                                        fStartWriteTime;
@@ -419,14 +378,21 @@ private:
        uint32_t                                                                                        fTotalArchivesLoaded;
        uint32_t                                                                                        fTotalDylibsLoaded;
        vm_statistics_data_t                                                            fStartVMInfo;
+       ObjectFile::Reader::ObjcConstraint                                      fCurrentObjCConstraint;
+       ObjectFile::Reader::CpuConstraint                                       fCurrentCpuConstraint;
+       bool                                                                                            fObjcReplacmentClasses;
+       bool                                                                                            fAllDirectDylibsLoaded;
 };
 
 
 Linker::Linker(int argc, const char* argv[])
-       : fOptions(argc, argv), fGlobalSymbolTable(*this), fOutputFile(NULL), fCreateUUID(false), fNextSortOrder(1),
-         fNextObjectFileOrder(1), fArchitecture(0), fArchitectureInferred(false), fDirectLibrariesComplete(false),
-         fOutputFileSize(0), fTotalObjectSize(0),
-         fTotalArchiveSize(0),  fTotalObjectLoaded(0), fTotalArchivesLoaded(0), fTotalDylibsLoaded(0)
+       : fOptions(argc, argv), fGlobalSymbolTable(*this), fNextInputOrdinal(1), fOutputFile(NULL), fBundleLoaderReader(NULL), 
+         fCreateUUID(false), fCanScatter(true),
+         fArchitecture(0), fArchitectureInferred(false), fDirectLibrariesComplete(false), fBiggerThanTwoGigOutput(false),
+         fOutputFileSize(0), fTotalZeroFillSize(0), fTotalSize(0), fTotalObjectSize(0),
+         fTotalArchiveSize(0),  fTotalObjectLoaded(0), fTotalArchivesLoaded(0), fTotalDylibsLoaded(0),
+         fCurrentObjCConstraint(ObjectFile::Reader::kObjcNone), fCurrentCpuConstraint(ObjectFile::Reader::kCpuAny),
+         fObjcReplacmentClasses(false), fAllDirectDylibsLoaded(false)
 {
        fStartTime = mach_absolute_time();
        if ( fOptions.printStatistics() )
@@ -485,19 +451,19 @@ cpu_type_t Linker::inferArchitecture()
                        ::close(fd);
                        if ( amount >= (ssize_t)sizeof(buffer) ) {
                                if ( mach_o::relocatable::Reader<ppc>::validFile(buffer) ) {
-                                       //fprintf(stderr, "ld64 warning: -arch not used, infering -arch ppc based on %s\n", it->path);
+                                       //fprintf(stderr, "ld: warning -arch not used, infering -arch ppc based on %s\n", it->path);
                                        return CPU_TYPE_POWERPC;
                                }
                                else if ( mach_o::relocatable::Reader<ppc64>::validFile(buffer) ) {
-                                       //fprintf(stderr, "ld64 warning: -arch not used, infering -arch ppc64 based on %s\n", it->path);
+                                       //fprintf(stderr, "ld: warning -arch not used, infering -arch ppc64 based on %s\n", it->path);
                                        return CPU_TYPE_POWERPC64;
                                }
                                else if ( mach_o::relocatable::Reader<x86>::validFile(buffer) ) {
-                                       //fprintf(stderr, "ld64 warning: -arch not used, infering -arch i386 based on %s\n", it->path);
+                                       //fprintf(stderr, "ld: warning -arch not used, infering -arch i386 based on %s\n", it->path);
                                        return CPU_TYPE_I386;
                                }
                                else if ( mach_o::relocatable::Reader<x86_64>::validFile(buffer) ) {
-                                       //fprintf(stderr, "ld64 warning: -arch not used, infering -arch x86_64 based on %s\n", it->path);
+                                       //fprintf(stderr, "ld: warning -arch not used, infering -arch x86_64 based on %s\n", it->path);
                                        return CPU_TYPE_X86_64;
                                }
                        }
@@ -505,7 +471,7 @@ cpu_type_t Linker::inferArchitecture()
        }
 
        // no thin .o files found, so default to same architecture this was built as
-       fprintf(stderr, "ld64 warning: -arch not specified\n");
+       fprintf(stderr, "ld: warning -arch not specified\n");
 #if __ppc__
        return CPU_TYPE_POWERPC;
 #elif __i386__
@@ -520,10 +486,10 @@ cpu_type_t Linker::inferArchitecture()
 }
 
 
-void Linker::addInputFile(ObjectFile::Reader* reader)
+void Linker::addInputFile(ObjectFile::Reader* reader, const Options::FileInfo& info)
 {
-       reader->setSortOrder(fNextObjectFileOrder++);
        fInputFiles.push_back(reader);
+       fDylibOptionsMap[reader] = info.options;
 }
 
 void Linker::setOutputFile(ExecutableFile::Writer* writer)
@@ -546,6 +512,7 @@ private:
 
 void Linker::loadAndResolve()
 {
+       fStartLoadAndResolveTime = mach_absolute_time();
        if ( fOptions.deadStrip() == Options::kDeadStripOff ) {
                // without dead-code-stripping:
                // find atoms to resolve all undefines
@@ -566,12 +533,48 @@ void Linker::loadAndResolve()
        }
 }
 
+void Linker::optimize()
+{
+       std::vector<class ObjectFile::Atom*> newAtoms;
+
+       const int readerCount = fInputFiles.size();
+       for (int i=0; i < readerCount; ++i) {
+               fInputFiles[i]->optimize(fAllAtoms, newAtoms, fNextInputOrdinal);
+       }
+       // note: When writer start generating stubs and non-lazy-pointers for all architecture, do not insert
+       // newAtoms into fGlobalSymbolTable. Instead directly insert them in fAllAtoms and set their order appropriately.
+       this->addAtoms(newAtoms);
+
+       // Some of the optimized atoms may not have identified section properly, if they
+       // were created before optimizer produces corrosponding real atom. Here, input
+       // file readers are not able to patch it themselves because Section::find() is
+       // linker specific.
+       for(std::vector<class ObjectFile::Atom*>::iterator itr = fAllAtoms.begin();
+               itr != fAllAtoms.end(); ++itr) {
+
+               ObjectFile::Atom *atom = *itr;
+               if (atom->getSectionName() && !atom->getSection())
+                       atom->setSection(Section::find(atom->getSectionName(), atom->getSegment().getName(), atom->isZeroFill()));
+       }
+
+       if ( fOptions.deadStrip() != Options::kDeadStripOff ) {
+               fLiveAtoms.clear();
+        deadStripResolve();
+    }
+    else
+        resolveReferences();
+}
+
 void Linker::link()
 {
        this->buildAtomList();
        this->loadAndResolve();
-       this->sortAtoms();
+       this->optimize();
+       this->checkObjC();
+       this->processDTrace();
        this->tweakLayout();
+       this->sortSections();
+       this->sortAtoms();
        this->writeDotOutput();
        this->collectDebugInfo();
        this->writeOutput();
@@ -587,7 +590,7 @@ void Linker::printTime(const char* msg, uint64_t partTime, uint64_t totalTime)
        if ( sUnitsPerSecond == 0 ) {
                struct mach_timebase_info timeBaseInfo;
                if ( mach_timebase_info(&timeBaseInfo) == KERN_SUCCESS ) {
-                       sUnitsPerSecond = 1000000000LL * timeBaseInfo.denom / timeBaseInfo.numer;
+                       sUnitsPerSecond = 1000000000ULL * timeBaseInfo.denom / timeBaseInfo.numer;
                        //fprintf(stderr, "sUnitsPerSecond=%llu\n", sUnitsPerSecond);
                }
        }
@@ -641,13 +644,12 @@ void Linker::printStatistics()
                getVMInfo(endVMInfo);
 
                uint64_t totalTime = fEndTime - fStartTime;
-               printTime("ld64 total time", totalTime, totalTime);
+               printTime("ld total time", totalTime, totalTime);
                printTime(" option parsing time",       fStartCreateReadersTime -       fStartTime,                                     totalTime);
                printTime(" object file processing",fStartCreateWriterTime -    fStartCreateReadersTime,        totalTime);
                printTime(" output file setup",         fStartBuildAtomsTime -          fStartCreateWriterTime,         totalTime);
-               printTime(" build atom list",           fStartLoadUndefinesTime -       fStartBuildAtomsTime,           totalTime);
-               printTime(" load undefines",            fStartResolveTime -                     fStartLoadUndefinesTime,        totalTime);
-               printTime(" resolve references",        fStartSortTime -                        fStartResolveTime,                      totalTime);
+               printTime(" build atom list",           fStartLoadAndResolveTime -      fStartBuildAtomsTime,           totalTime);
+               printTime(" resolve references",        fStartSortTime -                        fStartLoadAndResolveTime,       totalTime);
                printTime(" sort output",                       fStartDebugTime -                       fStartSortTime,                         totalTime);
                printTime(" process debug info",        fStartWriteTime -                       fStartDebugTime,                        totalTime);
                printTime(" write output",                      fEndTime -                                      fStartWriteTime,                        totalTime);
@@ -671,11 +673,18 @@ inline void Linker::addAtom(ObjectFile::Atom& atom)
                std::vector<class ObjectFile::Reference*>& references = atom.getReferences();
                for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
                        ObjectFile::Reference* reference = *it;
-                       if ( reference->isTargetUnbound() ) {
+                       if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName )
                                fGlobalSymbolTable.require(reference->getTargetName());
-                       }
-                       if ( reference->hasFromTarget() && reference->isFromTargetUnbound() )
+                       if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName )
                                fGlobalSymbolTable.require(reference->getFromTargetName());
+                       if ( reference->getTargetBinding() == ObjectFile::Reference::kDontBind )
+                               addDtraceProbe(atom, reference->getFixUpOffset(), reference->getTargetName());
+               }
+               // update total size info (except for __ZEROPAGE atom)
+               if ( atom.getSegment().isContentReadable() ) {
+                       fTotalSize += atom.getSize();
+                       if ( atom.isZeroFill() )
+                               fTotalZeroFillSize += atom.getSize();
                }
        }
        else {
@@ -687,8 +696,6 @@ inline void Linker::addAtom(ObjectFile::Atom& atom)
        ObjectFile::Atom::Scope scope = atom.getScope();
        const char* name = atom.getName();
        if ( (scope != ObjectFile::Atom::scopeTranslationUnit) && (name != NULL) ) {
-               fGlobalSymbolTable.add(atom);
-
                // update scope based on export list (possible that globals are downgraded to private_extern)
                if ( (scope == ObjectFile::Atom::scopeGlobal) && fOptions.hasExportRestrictList() ) {
                        bool doExport = fOptions.shouldExport(name);
@@ -696,33 +703,107 @@ inline void Linker::addAtom(ObjectFile::Atom& atom)
                                atom.setScope(ObjectFile::Atom::scopeLinkageUnit);
                        }
                }
+               // add to symbol table
+               fGlobalSymbolTable.add(atom);
        }
 
        // record section orders so output file can have same order
-       atom.setSection(Section::find(atom.getSectionName(), atom.getSegment().getName(), atom.isZeroFill()));
+       if (atom.getSectionName())
+               atom.setSection(Section::find(atom.getSectionName(), atom.getSegment().getName(), atom.isZeroFill()));
+}
+
+void Linker::updateContraints(ObjectFile::Reader* reader)
+{
+       // check objc objects were compiled compatibly
+       ObjectFile::Reader::ObjcConstraint objcAddition = reader->getObjCConstraint();
+       if ( reader->getInstallPath() == NULL ) {
+               // adding a .o file
+               switch ( fCurrentObjCConstraint ) {
+                       case ObjectFile::Reader::kObjcNone:
+                               fCurrentObjCConstraint = objcAddition;
+                               break;
+                       case ObjectFile::Reader::kObjcRetainRelease:
+                       case ObjectFile::Reader::kObjcRetainReleaseOrGC:
+                       case ObjectFile::Reader::kObjcGC:
+                               if ( (fCurrentObjCConstraint != objcAddition) && (objcAddition != ObjectFile::Reader::kObjcNone) ) 
+                                       throwf("%s built with different Garbage Collection settings", reader->getPath());
+                               break;
+               }
+       }
+       if ( reader->objcReplacementClasses() )
+               fObjcReplacmentClasses = true;
 
-       // assign order in which this atom was originally seen
-       if ( atom.getSortOrder() == 0 )
-               fNextSortOrder = atom.setSortOrder(fNextSortOrder);
+       // check cpu sub-types
+       ObjectFile::Reader::CpuConstraint  cpuAddition = reader->getCpuConstraint();
+       switch ( fCurrentCpuConstraint ) {
+               case ObjectFile::Reader::kCpuAny:
+                       fCurrentCpuConstraint = cpuAddition;
+                       break;
+               case ObjectFile::Reader::kCpuG3:
+                       switch ( cpuAddition ) {
+                               case ObjectFile::Reader::kCpuAny:
+                               case ObjectFile::Reader::kCpuG3:
+                                       break;
+                               case ObjectFile::Reader::kCpuG4:
+                               case ObjectFile::Reader::kCpuG5:
+                                       // previous file for G3 this one is more contrained, use it
+                                       fCurrentCpuConstraint = cpuAddition;
+                                       break;
+                       }
+                       break;
+               case ObjectFile::Reader::kCpuG4:
+                       switch ( cpuAddition ) {
+                               case ObjectFile::Reader::kCpuAny:
+                               case ObjectFile::Reader::kCpuG3:
+                               case ObjectFile::Reader::kCpuG4:
+                                       break;
+                               case ObjectFile::Reader::kCpuG5:
+                                       // previous file for G5 this one is more contrained, use it
+                                       fCurrentCpuConstraint = cpuAddition;
+                                       break;
+                       }
+                       break;
+               case ObjectFile::Reader::kCpuG5:
+                       // G5 can run everything
+                       break;
+       }
 }
 
 inline void Linker::addAtoms(std::vector<class ObjectFile::Atom*>& atoms)
 {
-       bool first = true; // assume all atoms are from same reader
+       bool scanAll = fOptions.readerOptions().fFullyLoadArchives || fOptions.readerOptions().fLoadAllObjcObjectsFromArchives;
+       bool first = true; 
        for (std::vector<ObjectFile::Atom*>::iterator it=atoms.begin(); it != atoms.end(); it++) {
-               if ( first ) {
+               // usually we only need to get the first atom's reader, but
+               // with -all_load all atoms from all .o files come come back together
+               // so we need to scan all atoms
+               if ( first || scanAll ) {
                        // update fReadersThatHaveSuppliedAtoms
                        ObjectFile::Reader* reader = (*it)->getFile();
                        if ( std::find(fReadersThatHaveSuppliedAtoms.begin(), fReadersThatHaveSuppliedAtoms.end(), reader)
                                        == fReadersThatHaveSuppliedAtoms.end() ) {
                                fReadersThatHaveSuppliedAtoms.push_back(reader);
-                       }
+                               updateContraints(reader);                               
+                       }       
                }
                this->addAtom(**it);
                first = false;
        }
 }
 
+void Linker::logArchive(ObjectFile::Reader* reader)
+{
+       if ( (fArchiveReaders.count(reader) != 0) && (fArchiveReadersLogged.count(reader) == 0) ) {
+               fArchiveReadersLogged.insert(reader);
+               const char* fullPath = reader->getPath();
+               char realName[MAXPATHLEN];
+               if ( realpath(fullPath, realName) != NULL )
+                       fullPath = realName;
+               logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath);
+       }
+}
+
+
 void Linker::buildAtomList()
 {
        fStartBuildAtomsTime = mach_absolute_time();
@@ -736,15 +817,19 @@ void Linker::buildAtomList()
        this->addAtoms(fOutputFile->getAtoms());
 
        // each reader contributes atoms
-       const int readerCount = fInputFiles.size();
-       for (int i=0; i < readerCount; ++i) {
-               this->addAtoms(fInputFiles[i]->getAtoms());
+       for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
+               ObjectFile::Reader* reader = *it;
+               std::vector<class ObjectFile::Atom*>& atoms = reader->getAtoms();
+               this->addAtoms(atoms);
+               if ( fOptions.readerOptions().fTraceArchives && (atoms.size() != 0) ) 
+                       logArchive(reader);
        }
 
        // extra command line section always at end
        std::vector<Options::ExtraSection>& extraSections = fOptions.extraSections();
        for( std::vector<Options::ExtraSection>::iterator it=extraSections.begin(); it != extraSections.end(); ++it) {
-               this->addAtoms(SectCreate::MakeReader(it->segmentName, it->sectionName, it->path, it->data, it->dataLen)->getAtoms());
+               this->addAtoms((new opaque_section::Reader(it->segmentName, it->sectionName, it->path, it->data, it->dataLen, fNextInputOrdinal))->getAtoms());
+               fNextInputOrdinal += it->dataLen;
        }
 }
 
@@ -759,7 +844,6 @@ static const char* pathLeafName(const char* path)
 
 void Linker::loadUndefines()
 {
-       fStartLoadUndefinesTime = mach_absolute_time();
        // keep looping until no more undefines were added in last loop
        unsigned int undefineCount = 0xFFFFFFFF;
        while ( undefineCount != fGlobalSymbolTable.getRequireCount() ) {
@@ -770,134 +854,199 @@ void Linker::loadUndefines()
                        const char* name = *it;
                        ObjectFile::Atom* possibleAtom = fGlobalSymbolTable.find(name);
                        if ( (possibleAtom == NULL)
-                         || ((possibleAtom->getDefinitionKind()==ObjectFile::Atom::kWeakDefinition) && (fOptions.outputKind() != Options::kObjectFile) && (possibleAtom->getScope() == ObjectFile::Atom::scopeGlobal)) )
-                               this->addJustInTimeAtoms(name);
+                         || ((possibleAtom->getDefinitionKind()==ObjectFile::Atom::kWeakDefinition) 
+                         && (fOptions.outputKind() != Options::kObjectFile) 
+                         && (possibleAtom->getScope() == ObjectFile::Atom::scopeGlobal)) ) {
+                               std::vector<class ObjectFile::Atom*>* atoms = this->addJustInTimeAtoms(name);
+                               if ( atoms != NULL ) 
+                                       delete atoms;
+                       }
                }
        }
 }
 
-void Linker::checkUndefines()
+// temp hack for rdar://problem/4718189 map ObjC class names to new runtime names
+class ExportedObjcClass
 {
-       if ( fOptions.outputKind() != Options::kObjectFile ) {
-               // error out on any remaining undefines
-               bool doPrint = true;
-               bool doError = true;
-               switch ( fOptions.undefinedTreatment() ) {
-                       case Options::kUndefinedError:
-                               break;
-                       case Options::kUndefinedDynamicLookup:
-                               doError = false;
-                               break;
-                       case Options::kUndefinedWarning:
-                               doError = false;
-                               break;
-                       case Options::kUndefinedSuppress:
-                               doError = false;
-                               doPrint = false;
-                               break;
+public:
+       ExportedObjcClass(Options& opt) : fOptions(opt)  {}
+
+       bool operator()(const char* name) const {
+               if ( fOptions.shouldExport(name) ) {
+                       if ( strncmp(name, ".objc_class_name_", 17) == 0 )
+                               return true;
+                       if ( strncmp(name, "_OBJC_CLASS_$_", 14) == 0 )
+                               return true;
+                       if ( strncmp(name, "_OBJC_METACLASS_$_", 18) == 0 )
+                               return true;
                }
-               std::vector<const char*> unresolvableUndefines;
-               fGlobalSymbolTable.getNeededNames(false, unresolvableUndefines);
-               const int unresolvableCount = unresolvableUndefines.size();
-               int unresolvableExportsCount  = 0;
-               if ( unresolvableCount != 0 ) {
-                       if ( doPrint ) {
-                               if ( fOptions.printArchPrefix() )
-                                       fprintf(stderr, "Undefined symbols for architecture %s:\n", fArchitectureName);
-                               else
-                                       fprintf(stderr, "Undefined symbols:\n");
-                               for (int i=0; i < unresolvableCount; ++i) {
-                                       const char* name = unresolvableUndefines[i];
-                                       fprintf(stderr, "  %s, referenced from:\n", name);
-                                       // scan all atoms for references
-                                       bool foundAtomReference = false;
-                                       for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
-                                               ObjectFile::Atom* atom = *it;
-                                               std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
-                                               for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
-                                                       ObjectFile::Reference* reference = *rit;
-                                                       if ( reference->isTargetUnbound() ) {
-                                                               if ( strcmp(reference->getTargetName(), name) == 0 ) {
-                                                                       fprintf(stderr, "      %s in %s\n", atom->getDisplayName(), pathLeafName(atom->getFile()->getPath()));
-                                                                       foundAtomReference = true;
-                                                               }
+               //fprintf(stderr, "%s is not exported\n", name);
+               return false;
+       }
+private:
+       Options& fOptions;
+};
+
+
+void Linker::checkUndefines()
+{
+       // error out on any remaining undefines
+       bool doPrint = true;
+       bool doError = true;
+       switch ( fOptions.undefinedTreatment() ) {
+               case Options::kUndefinedError:
+                       break;
+               case Options::kUndefinedDynamicLookup:
+                       doError = false;
+                       break;
+               case Options::kUndefinedWarning:
+                       doError = false;
+                       break;
+               case Options::kUndefinedSuppress:
+                       doError = false;
+                       doPrint = false;
+                       break;
+       }
+       std::vector<const char*> unresolvableUndefines;
+       fGlobalSymbolTable.getNeededNames(false, unresolvableUndefines);
+
+       // temp hack for rdar://problem/4718189 map ObjC class names to new runtime names
+       // ignore unresolved references to Objc class names that are listed in -exported_symbols_list
+       if ( fOptions.hasExportRestrictList() )
+               unresolvableUndefines.erase(std::remove_if(unresolvableUndefines.begin(), unresolvableUndefines.end(), ExportedObjcClass(fOptions)), unresolvableUndefines.end());
+
+       const int unresolvableCount = unresolvableUndefines.size();
+       int unresolvableExportsCount  = 0;
+       if ( unresolvableCount != 0 ) {
+               if ( doPrint ) {
+                       if ( fOptions.printArchPrefix() )
+                               fprintf(stderr, "Undefined symbols for architecture %s:\n", fArchitectureName);
+                       else
+                               fprintf(stderr, "Undefined symbols:\n");
+                       for (int i=0; i < unresolvableCount; ++i) {
+                               const char* name = unresolvableUndefines[i];
+                               fprintf(stderr, "  \"%s\", referenced from:\n", name);
+                               // scan all atoms for references
+                               bool foundAtomReference = false;
+                               for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
+                                       ObjectFile::Atom* atom = *it;
+                                       std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
+                                       for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                                               ObjectFile::Reference* reference = *rit;
+                                               if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
+                                                       if ( strcmp(reference->getTargetName(), name) == 0 ) {
+                                                               fprintf(stderr, "      %s in %s\n", atom->getDisplayName(), pathLeafName(atom->getFile()->getPath()));
+                                                               foundAtomReference = true;
                                                        }
-                                                       if ( reference->hasFromTarget() && reference->isFromTargetUnbound() ) {
-                                                               if ( strcmp(reference->getFromTargetName(), name) == 0 ) {
-                                                                       fprintf(stderr, "      %s in %s\n", atom->getDisplayName(), pathLeafName(atom->getFile()->getPath()));
-                                                                       foundAtomReference = true;
-                                                               }
+                                               }
+                                               if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
+                                                       if ( strcmp(reference->getFromTargetName(), name) == 0 ) {
+                                                               fprintf(stderr, "      %s in %s\n", atom->getDisplayName(), pathLeafName(atom->getFile()->getPath()));
+                                                               foundAtomReference = true;
                                                        }
                                                }
                                        }
-                                       // scan command line options
-                                       if  ( !foundAtomReference && fOptions.hasExportRestrictList() && fOptions.shouldExport(name) ) {
-                                               fprintf(stderr, "     -exported_symbols_list command line option\n");
-                                               ++unresolvableExportsCount;
-                                       }
+                               }
+                               // scan command line options
+                               if  ( !foundAtomReference && fOptions.hasExportRestrictList() && fOptions.shouldExport(name) ) {
+                                       fprintf(stderr, "     -exported_symbols_list command line option\n");
+                                       ++unresolvableExportsCount;
                                }
                        }
-                       if ( doError && (unresolvableCount > unresolvableExportsCount) ) // last check should be removed.  It exists so broken projects still build
-                               throw "symbol(s) not found";
                }
+               if ( doError ) 
+                       throw "symbol(s) not found";
        }
 }
 
 
 
-void Linker::addJustInTimeAtoms(const char* name)
+std::vector<class ObjectFile::Atom*>* Linker::addJustInTimeAtoms(const char* name)
 {
        // when creating final linked image, writer gets first chance
        if ( fOptions.outputKind() != Options::kObjectFile ) {
                std::vector<class ObjectFile::Atom*>* atoms = fOutputFile->getJustInTimeAtomsFor(name);
                if ( atoms != NULL ) {
                        this->addAtoms(*atoms);
-                       delete atoms;
                        //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, fOutputFile->getPath() );
-                       return;  // found a definition, no need to search anymore
+                       return atoms;  // found a definition, no need to search anymore
                }
        }
 
-       // give direct readers a chance
+       // give readers a chance
        for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
                ObjectFile::Reader* reader = *it;
                if ( reader != NULL ) {
                        // if this reader is a static archive that has the symbol we need, pull in all atoms in that module
                        // if this reader is a dylib that exports the symbol we need, have it synthesize an atom for us.
+                       //fprintf(stderr, "addJustInTimeAtoms(%s), looking in reader %s\n", name, reader->getPath() );
                        std::vector<class ObjectFile::Atom*>* atoms = reader->getJustInTimeAtomsFor(name);
                        if ( atoms != NULL ) {
                                this->addAtoms(*atoms);
-                               delete atoms;
-                               //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, fInputFiles[i]->getPath() );
-                               return;  // found a definition, no need to search anymore
+                               //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
+                               if ( fOptions.readerOptions().fTraceArchives ) {
+                                       logArchive(reader);
+                               }
+                               // if this is a weak definition in a dylib
+                               if ( (atoms->size() == 1) && (reader->getInstallPath() != NULL) && (atoms->at(0)->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
+                                       // keep looking for a non-weak definition
+                               }
+                               else {
+                                       // found a definition, no need to search anymore
+                                       return atoms;  
+                               }
                        }
                }
        }
 
-       // give indirect readers a chance
-       for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
-               ObjectFile::Reader* reader = it->reader;
-               // for two-level namespace, only search re-exported indirect libraries
-               if ( (reader != NULL) && ((it->reExportedViaDirectLibrary != NULL) || (fOptions.nameSpace() != Options::kTwoLevelNameSpace)) ) {
-                       std::vector<class ObjectFile::Atom*>* atoms = reader->getJustInTimeAtomsFor(name);
-                       if ( atoms != NULL ) {
-                               this->addAtoms(*atoms);
-                               //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
-                               delete atoms;
-                               return;  // found a definition, no need to search anymore
+       // for two level namesapce, give all implicitly link dylibs a chance
+       if ( fOptions.nameSpace() == Options::kTwoLevelNameSpace ) {
+               for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
+                       if ( it->second->implicitlyLinked() ) {
+                               //fprintf(stderr, "addJustInTimeAtoms(%s), looking in implicitly linked %s\n", name, it->second->getPath() );
+                               std::vector<class ObjectFile::Atom*>* atoms = it->second->getJustInTimeAtomsFor(name);
+                               if ( atoms != NULL ) {
+                                       this->addAtoms(*atoms);
+                                       //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
+                                       // if this is a weak definition in a dylib
+                                       if ( (atoms->size() == 1) && (atoms->at(0)->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
+                                               // keep looking for a non-weak definition
+                                       }
+                                       else {
+                                               // found a definition, no need to search anymore
+                                               return atoms;  
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // for flat namespace, give indirect dylibs
+       if ( fOptions.nameSpace() != Options::kTwoLevelNameSpace ) {
+               for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
+                       if ( ! it->second->explicitlyLinked() ) {
+                               std::vector<class ObjectFile::Atom*>* atoms = it->second->getJustInTimeAtomsFor(name);
+                               if ( atoms != NULL ) {
+                                       this->addAtoms(*atoms);
+                                       //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
+                                       return atoms;  // found a definition, no need to search anymore
+                               }
                        }
                }
        }
 
        // when creating .o file, writer goes last (this is so any static archives will be searched above)
-       if ( (fOptions.outputKind() == Options::kObjectFile) || (fOptions.undefinedTreatment() != Options::kUndefinedError) ) {
+       if (    (fOptions.outputKind() == Options::kObjectFile) 
+               ||  (fOptions.undefinedTreatment() != Options::kUndefinedError)
+               ||      fOptions.someAllowedUndefines() ) {
                ObjectFile::Atom* atom = fOutputFile->getUndefinedProxyAtom(name);
                if ( atom != NULL ) {
                        this->addAtom(*atom);
-                       return;
+                       return NULL;
                }
        }
        //fprintf(stderr, "addJustInTimeAtoms(%s) => not found\n", name);
+       return NULL;
 }
 
 void Linker::resolve(ObjectFile::Reference* reference)
@@ -925,16 +1074,15 @@ void Linker::resolveFrom(ObjectFile::Reference* reference)
 
 void Linker::resolveReferences()
 {
-       fStartResolveTime = mach_absolute_time();
        // note: the atom list may grow during this loop as libraries supply needed atoms
        for (unsigned int j=0; j < fAllAtoms.size(); ++j) {
                ObjectFile::Atom* atom = fAllAtoms[j];
                std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
                for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
                        ObjectFile::Reference* reference = *it;
-                       if ( reference->isTargetUnbound() )
+                       if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName )
                                this->resolve(reference);
-                       if ( reference->hasFromTarget() && reference->isFromTargetUnbound() )
+                       if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName )
                                this->resolveFrom(reference);
                }
        }
@@ -974,6 +1122,24 @@ private:
 };
 
 
+void Linker::addJustInTimeAtomsAndMarkLive(const char* name)
+{
+       std::vector<class ObjectFile::Atom*>* atoms = this->addJustInTimeAtoms(name);
+       if ( atoms != NULL ) {
+               if ( fOptions.allGlobalsAreDeadStripRoots() ) {
+                       for (std::vector<ObjectFile::Atom*>::iterator it=atoms->begin(); it != atoms->end(); it++) {
+                               ObjectFile::Atom* atom = *it;
+                               if ( atom->getScope() ==  ObjectFile::Atom::scopeGlobal ) {
+                                       WhyLiveBackChain rootChain;
+                                       rootChain.previous = NULL;
+                                       rootChain.name = atom->getDisplayName();
+                                       this->markLive(*atom, &rootChain);
+                               }
+                       }
+               }
+               delete atoms;
+       }
+}
 
 void Linker::markLive(ObjectFile::Atom& atom, struct Linker::WhyLiveBackChain* previous)
 {
@@ -992,17 +1158,23 @@ void Linker::markLive(ObjectFile::Atom& atom, struct Linker::WhyLiveBackChain* p
                thisChain.previous = previous;
                // this atom is live
                fLiveAtoms.insert(&atom);
+               // update total size info (except for __ZEROPAGE atom)
+               if ( atom.getSegment().isContentReadable() ) {
+                       fTotalSize += atom.getSize();
+                       if ( atom.isZeroFill() )
+                               fTotalZeroFillSize += atom.getSize();
+               }
                // and all atoms it references
                std::vector<class ObjectFile::Reference*>& references = atom.getReferences();
                for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
                        ObjectFile::Reference* reference = *it;
-                       if ( reference->isTargetUnbound() ) {
+                       if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
                                // look in global symbol table
                                const char* targetName = reference->getTargetName();
                                ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
                                if ( target == NULL ) {
                                        // load archives or dylibs
-                                       this->addJustInTimeAtoms(targetName);
+                                       this->addJustInTimeAtomsAndMarkLive(targetName);
                                }
                                // look again
                                target = fGlobalSymbolTable.find(targetName);
@@ -1015,34 +1187,48 @@ void Linker::markLive(ObjectFile::Atom& atom, struct Linker::WhyLiveBackChain* p
                                        fGlobalSymbolTable.require(targetName);
                                }
                        }
-                       if ( ! reference->isTargetUnbound() ) {
-                               thisChain.name = reference->getTargetName();
-                               markLive(reference->getTarget(), &thisChain);
+                       switch ( reference->getTargetBinding() ) {
+                               case ObjectFile::Reference::kBoundDirectly:
+                               case ObjectFile::Reference::kBoundByName:
+                                       thisChain.name = reference->getTargetName();
+                                       markLive(reference->getTarget(), &thisChain);
+                                       break;
+                               case ObjectFile::Reference::kDontBind:
+                                       addDtraceProbe(atom, reference->getFixUpOffset(), reference->getTargetName());
+                                       break;
+                               case ObjectFile::Reference::kUnboundByName:
+                                       // do nothing
+                                       break;
                        }
-                       if ( reference->hasFromTarget() ) {
-                               // do the same as above, for from target
-                               if ( reference->isFromTargetUnbound() ) {
-                                       // look in global symbol table
-                                       const char* targetName = reference->getFromTargetName();
-                                       ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
-                                       if ( target == NULL ) {
-                                               // load archives or dylibs
-                                               this->addJustInTimeAtoms(targetName);
-                                       }
-                                       // look again
-                                       target = fGlobalSymbolTable.find(targetName);
-                                       if ( target != NULL ) {
-                                               reference->setFromTarget(*target);
-                                       }
-                                       else {
-                                               // mark as undefined, for later error processing
-                                               fGlobalSymbolTable.require(targetName);
-                                       }
+                       // do the same as above, for "from target"
+                       if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
+                               // look in global symbol table
+                               const char* targetName = reference->getFromTargetName();
+                               ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
+                               if ( target == NULL ) {
+                                       // load archives or dylibs
+                                       this->addJustInTimeAtomsAndMarkLive(targetName);
+                               }
+                               // look again
+                               target = fGlobalSymbolTable.find(targetName);
+                               if ( target != NULL ) {
+                                       reference->setFromTarget(*target);
+                               }
+                               else {
+                                       // mark as undefined, for later error processing
+                                       fGlobalSymbolTable.require(targetName);
                                }
-                               if ( ! reference->isFromTargetUnbound() ) {
+                       }
+                       switch ( reference->getFromTargetBinding() ) {
+                               case ObjectFile::Reference::kBoundDirectly:
+                               case ObjectFile::Reference::kBoundByName:
                                        thisChain.name = reference->getFromTargetName();
                                        markLive(reference->getFromTarget(), &thisChain);
-                               }
+                                       break;
+                               case ObjectFile::Reference::kUnboundByName:
+                               case ObjectFile::Reference::kDontBind:
+                                       // do nothing
+                                       break;
                        }
                }
        }
@@ -1053,7 +1239,7 @@ void Linker::addLiveRoot(const char* name)
 {
        ObjectFile::Atom* target = fGlobalSymbolTable.find(name);
        if ( target == NULL ) {
-               this->addJustInTimeAtoms(name);
+               this->addJustInTimeAtomsAndMarkLive(name);
                target = fGlobalSymbolTable.find(name);
        }
        if ( target != NULL )
@@ -1082,7 +1268,7 @@ void Linker::deadStripResolve()
        if ( fOptions.allGlobalsAreDeadStripRoots() ) {
                for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
                        ObjectFile::Atom* atom = *it;
-                       if ( atom->getScope() == ObjectFile::Atom::scopeGlobal )
+                       if ( (atom->getScope() == ObjectFile::Atom::scopeGlobal) && (fDeadAtoms.count(atom) == 0) )
                                fLiveRootAtoms.insert(atom);
                }
        }
@@ -1103,7 +1289,7 @@ void Linker::deadStripResolve()
                std::vector<class ObjectFile::Reference*>& references = (*it)->getReferences();
                for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
                        ObjectFile::Reference* reference = *rit;
-                       if ( reference->isTargetUnbound() ) {
+                       if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
                                ObjectFile::Atom* target = fGlobalSymbolTable.find(reference->getTargetName());
                                if ( target != NULL ) {
                                        reference->setTarget(*target, reference->getTargetOffset());
@@ -1114,32 +1300,607 @@ void Linker::deadStripResolve()
                                                fprintf(stderr, "warning: ld64 internal error %s is not a tentative definition\n", target->getDisplayName());
                                }
                        }
-                       if ( reference->hasFromTarget() && reference->isFromTargetUnbound() ) {
-                               ObjectFile::Atom* target = fGlobalSymbolTable.find(reference->getFromTargetName());
-                               if ( target != NULL ) {
-                                       reference->setFromTarget(*target);
-                                       fLiveAtoms.insert(target);
-                                       // by just adding this atom to fLiveAtoms set, we are assuming it has no
-                                       // references, which is true for commons.
-                                       if ( target->getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition )
-                                               fprintf(stderr, "warning: ld64 internal error %s is not a tentative definition\n", target->getDisplayName());
+                       if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
+                               ObjectFile::Atom* target = fGlobalSymbolTable.find(reference->getFromTargetName());
+                               if ( target != NULL ) {
+                                       reference->setFromTarget(*target);
+                                       fLiveAtoms.insert(target);
+                                       // by just adding this atom to fLiveAtoms set, we are assuming it has no
+                                       // references, which is true for commons.
+                                       if ( target->getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition )
+                                               fprintf(stderr, "warning: ld64 internal error %s is not a tentative definition\n", target->getDisplayName());
+                               }
+                       }
+               }
+       }
+
+       // now remove all non-live atoms from fAllAtoms
+       fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), NotLive(fLiveAtoms)), fAllAtoms.end());
+}
+
+void Linker::checkObjC()
+{
+       // check dylibs
+       switch ( fCurrentObjCConstraint ) {
+               case ObjectFile::Reader::kObjcNone:
+                       // can link against any dylib
+                       break;
+               case ObjectFile::Reader::kObjcRetainRelease:
+                       // cannot link against GC-only dylibs
+                       for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
+                               if ( it->second->explicitlyLinked() ) {
+                                       if ( it->second->getObjCConstraint() == ObjectFile::Reader::kObjcGC )
+                                               throwf("this linkage unit uses Retain/Release.  It cannot link against the GC-only dylib: %s", it->second->getPath());
+                               }
+                       }
+                       break;
+               case ObjectFile::Reader::kObjcRetainReleaseOrGC:
+                       // can link against GC or RR dylibs
+                       break;
+               case ObjectFile::Reader::kObjcGC:
+                       // cannot link against RR-only dylibs
+                       for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
+                               if ( it->second->explicitlyLinked() ) {
+                                       if ( it->second->getObjCConstraint() == ObjectFile::Reader::kObjcRetainRelease )
+                                               throwf("this linkage unit requires GC.  It cannot link against Retain/Release dylib: %s", it->second->getPath());
+                               }
+                       }
+                       break;
+       }
+       
+       // synthesize __OBJC __image_info atom if needed
+       if ( fCurrentObjCConstraint != ObjectFile::Reader::kObjcNone ) {
+               this->addAtom(fOutputFile->makeObjcInfoAtom(fCurrentObjCConstraint, fObjcReplacmentClasses));
+       }
+}
+
+void Linker::addDtraceProbe(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* probeName)
+{
+       if ( probeName != NULL ) {
+               if ( strncmp(probeName, "___dtrace_probe$", 16) == 0 ) 
+                       fDtraceProbeSites.push_back(DTraceProbeInfo(&atom, offsetInAtom, probeName));
+               else if ( strncmp(probeName, "___dtrace_isenabled$", 20) == 0 ) 
+                       fDtraceIsEnabledSites.push_back(DTraceProbeInfo(&atom, offsetInAtom, probeName));
+               else if ( strncmp(probeName, "___dtrace_", 10) == 0 )
+                       fDtraceAtomToTypes[&atom].insert(probeName);
+               else if ( fOptions.dTrace() && (strncmp(probeName, "__dtrace_probe$", 15) == 0) ) 
+                       fDtraceProbes.push_back(DTraceProbeInfo(&atom, offsetInAtom, probeName));
+       }
+}
+
+static uint8_t pointerKind(cpu_type_t arch)
+{
+       switch ( arch ) {
+               case CPU_TYPE_POWERPC:
+                       return ppc::kPointer;
+               case CPU_TYPE_POWERPC64:
+                       return ppc64::kPointer;
+               case CPU_TYPE_I386:
+                       return x86::kPointer;
+               case CPU_TYPE_X86_64:
+                       return x86_64::kPointer;
+       }
+       throw "uknown architecture";
+}
+
+static uint8_t pcRelKind(cpu_type_t arch)
+{
+       switch ( arch ) {
+               case CPU_TYPE_POWERPC:
+                       return ppc::kPointerDiff32;
+               case CPU_TYPE_POWERPC64:
+                       return ppc64::kPointerDiff32;
+               case CPU_TYPE_I386:
+                       return x86::kPointerDiff;
+               case CPU_TYPE_X86_64:
+                       return x86_64::kPointerDiff32;
+       }
+       throw "uknown architecture";
+}
+
+typedef uint8_t* (*oldcreatedof_func_t) (const char*, cpu_type_t, unsigned int, const char*[], const char*[], uint64_t offsetsInDOF[], size_t* size);
+typedef uint8_t* (*createdof_func_t)(cpu_type_t, unsigned int, const char*[], unsigned int, const char*[], const char*[], uint64_t offsetsInDOF[], size_t* size);
+
+
+void Linker::processDTrace()
+{
+       // handle dtrace 2.0 static probes
+       if ( (fOptions.outputKind() != Options::kObjectFile) && ((fDtraceProbeSites.size() != 0) || (fDtraceIsEnabledSites.size() != 0)) ) {
+               // partition probes by provider name
+               // The symbol names looks like:
+               //      "___dtrace_isenabled$" provider-name "$" probe-name [ "$"... ]
+               //      "___dtrace_probe$" provider-name "$" probe-name [ "$"... ]
+               ProviderToProbes providerToProbes;
+               std::vector<DTraceProbeInfo> emptyList;
+               for(std::vector<DTraceProbeInfo>::iterator it = fDtraceProbeSites.begin(); it != fDtraceProbeSites.end(); ++it) {
+                       const char* providerStart = &it->probeName[16];
+                       const char* providerEnd = strchr(providerStart, '$');
+                       if ( providerEnd != NULL ) {
+                               char providerName[providerEnd-providerStart+1];
+                               strlcpy(providerName, providerStart, providerEnd-providerStart+1);
+                               ProviderToProbes::iterator pos = providerToProbes.find(providerName);
+                               if ( pos == providerToProbes.end() ) {
+                                       const char* dup = strdup(providerName);
+                                       providerToProbes[dup] = emptyList;
+                               }
+                               providerToProbes[providerName].push_back(*it);
+                       }
+               }
+               for(std::vector<DTraceProbeInfo>::iterator it = fDtraceIsEnabledSites.begin(); it != fDtraceIsEnabledSites.end(); ++it) {
+                       const char* providerStart = &it->probeName[20];
+                       const char* providerEnd = strchr(providerStart, '$');
+                       if ( providerEnd != NULL ) {
+                               char providerName[providerEnd-providerStart+1];
+                               strlcpy(providerName, providerStart, providerEnd-providerStart+1);
+                               ProviderToProbes::iterator pos = providerToProbes.find(providerName);
+                               if ( pos == providerToProbes.end() ) {
+                                       const char* dup = strdup(providerName);
+                                       providerToProbes[dup] = emptyList;
+                               }
+                               providerToProbes[providerName].push_back(*it);
+                       }
+               }
+               
+               // create a DOF section for each provider
+               int dofIndex=1;
+               CStringSet sectionNamesUsed;
+               for(ProviderToProbes::iterator pit = providerToProbes.begin(); pit != providerToProbes.end(); ++pit, ++dofIndex) {
+                       const char* providerName = pit->first;
+                       const std::vector<DTraceProbeInfo>& probes = pit->second;
+
+                       // open library and find dtrace_create_dof()
+                       void* handle = dlopen("/usr/lib/libdtrace.dylib", RTLD_LAZY);
+                       if ( handle == NULL )
+                               throwf("couldn't dlopen() /usr/lib/libdtrace.dylib: %s\n", dlerror());
+                       createdof_func_t pCreateDOF = (createdof_func_t)dlsym(handle, "dtrace_ld_create_dof");
+                       if ( pCreateDOF == NULL )
+                               throwf("couldn't find \"dtrace_ld_create_dof\" in /usr/lib/libdtrace.dylib: %s\n", dlerror());
+                       // build list of typedefs/stability infos for this provider
+                       CStringSet types;
+                       for(std::vector<DTraceProbeInfo>::const_iterator it = probes.begin(); it != probes.end(); ++it) {
+                               std::map<const ObjectFile::Atom*,CStringSet>::iterator pos = fDtraceAtomToTypes.find(it->atom);
+                               if ( pos != fDtraceAtomToTypes.end() ) {
+                                       for(CStringSet::iterator sit = pos->second.begin(); sit != pos->second.end(); ++sit) {
+                                               const char* providerStart = strchr(*sit, '$')+1;
+                                               const char* providerEnd = strchr(providerStart, '$');
+                                               if ( providerEnd != NULL ) {
+                                                       char aProviderName[providerEnd-providerStart+1];
+                                                       strlcpy(aProviderName, providerStart, providerEnd-providerStart+1);
+                                                       if ( strcmp(aProviderName, providerName) == 0 )
+                                                               types.insert(*sit);
+                                               }
+                                       }
+                               }
+                       }
+                       int typeCount = types.size();
+                       const char* typeNames[typeCount];
+                       //fprintf(stderr, "types for %s:\n", providerName);
+                       uint32_t index = 0;
+                       for(CStringSet::iterator it = types.begin(); it != types.end(); ++it) {
+                               typeNames[index] = *it;
+                               //fprintf(stderr, "\t%s\n", *it);
+                               ++index;
+                       }
+                       
+                       // build list of probe/isenabled sites
+                       const uint32_t probeCount = probes.size();
+                       const char* probeNames[probeCount];
+                       const char* funtionNames[probeCount];
+                       uint64_t offsetsInDOF[probeCount];
+                       index = 0;
+                       for(std::vector<DTraceProbeInfo>::const_iterator it = probes.begin(); it != probes.end(); ++it) {
+                               probeNames[index] = it->probeName;
+                               funtionNames[index] = it->atom->getName();
+                               offsetsInDOF[index] = 0;
+                               ++index;
+                       }
+                       // call dtrace library to create DOF section
+                       size_t dofSectionSize;
+                       uint8_t* p = (*pCreateDOF)(fArchitecture, typeCount, typeNames, probeCount, probeNames, funtionNames, offsetsInDOF, &dofSectionSize);
+                       if ( p != NULL ) {
+                               char sectionName[18];
+                               strcpy(sectionName, "__dof_");
+                               strlcpy(&sectionName[6], providerName, 10);
+                               // create unique section name so each DOF is in its own section
+                               if ( sectionNamesUsed.count(sectionName) != 0 ) {
+                                       sectionName[15] = '0';
+                                       sectionName[16] = '\0';
+                                       while ( sectionNamesUsed.count(sectionName) != 0 )
+                                               ++sectionName[15];
+                               }
+                               sectionNamesUsed.insert(sectionName);
+                               char symbolName[strlen(providerName)+64];
+                               sprintf(symbolName, "__dtrace_dof_for_provider_%s", providerName);
+                               opaque_section::Reader* reader = new opaque_section::Reader("__TEXT", sectionName, 
+                                                                                                               "dtrace", p, dofSectionSize, fNextInputOrdinal, symbolName);
+                               fNextInputOrdinal += dofSectionSize;
+                               // add references
+                               for (uint32_t i=0; i < probeCount; ++i) {
+                                       uint64_t offset = offsetsInDOF[i];
+                                       //fprintf(stderr, "%s offset[%d]=0x%08llX\n", providerName, i, offset);
+                                       if ( offset > dofSectionSize )
+                                               throwf("offsetsInDOF[i]=%0llX > dofSectionSize=%0lX\n", i, offset, dofSectionSize);
+                                       reader->addSectionReference(pcRelKind(fArchitecture), offset, probes[i].atom, probes[i].offset, reader->getAtoms()[0], 0);
+                               }
+                               this->addAtoms(reader->getAtoms());
+                       }
+                       else {
+                               throw "error creating dtrace DOF section";
+                       }
+               }
+       }
+       // create a __DATA __dof section iff -dtrace option was used and static probes were found in .o files
+       else if ( fOptions.dTrace() && (fDtraceProbes.size() != 0) ) {
+               const uint32_t probeCount = fDtraceProbes.size();
+               const char* labels[probeCount];
+               const char* funtionNames[probeCount];
+               uint64_t offsetsInDOF[probeCount];
+
+               // open libray and find dtrace_ld64_create_dof()
+               void* handle = dlopen("/usr/lib/libdtrace.dylib", RTLD_LAZY);
+               if ( handle == NULL )
+                       throwf("couldn't dlopen() /usr/lib/libdtrace.dylib: %s\n", dlerror());
+               oldcreatedof_func_t pCreateDOF = (oldcreatedof_func_t)dlsym(handle, "dtrace_ld64_create_dof");
+               if ( pCreateDOF == NULL )
+                       throwf("couldn't find \"dtrace_ld64_create_dof\" in /usr/lib/libdtrace.dylib: %s\n", dlerror());
+
+               // build argument list
+               uint32_t index = 0;
+               for(std::vector<DTraceProbeInfo>::iterator it = fDtraceProbes.begin(); it != fDtraceProbes.end(); ++it) {
+                       labels[index] = it->probeName;
+                       funtionNames[index] = it->atom->getName();
+                       offsetsInDOF[index] = 0;
+                       ++index;
+               }
+               size_t dofSectionSize;
+               // call dtrace library to create DOF section
+               uint8_t* p = (*pCreateDOF)(fOptions.dTraceScriptName(), fArchitecture, probeCount, labels, funtionNames, offsetsInDOF, &dofSectionSize);
+               if ( p != NULL ) {
+                       opaque_section::Reader* reader = new opaque_section::Reader("__DATA", "__dof", "dtrace", p, dofSectionSize, fNextInputOrdinal);
+                       fNextInputOrdinal += dofSectionSize;
+                       // add references
+                       for (uint32_t i=0; i < probeCount; ++i) {
+                               uint64_t offset = offsetsInDOF[i];
+                               if ( offset > dofSectionSize )
+                                       throwf("offsetsInDOF[i]=%0llX > dofSectionSize=%0lX\n", i, offset, dofSectionSize);
+                               reader->addSectionReference(pointerKind(fArchitecture), offset, fDtraceProbes[i].atom, fDtraceProbes[i].offset);
+                       }
+                       this->addAtoms(reader->getAtoms());
+               }
+               else {
+                       throw "error created dtrace DOF section";
+               }
+       }
+}
+
+
+static bool matchesObjectFile(ObjectFile::Atom* atom, const char* objectFileLeafName)
+{
+       if ( objectFileLeafName == NULL )
+               return true;
+       const char* atomFullPath = atom->getFile()->getPath();
+       const char* lastSlash = strrchr(atomFullPath, '/');
+       if ( lastSlash != NULL ) {
+               if ( strcmp(&lastSlash[1], objectFileLeafName) == 0 )
+                       return true;
+       }
+       else {
+               if ( strcmp(atomFullPath, objectFileLeafName) == 0 )
+                       return true;
+       }
+       return false;
+}
+
+
+static bool usesAnonymousNamespace(const char* symbol)
+{
+       return ( (strncmp(symbol, "__Z", 3) == 0) && (strstr(symbol, "_GLOBAL__N_") != NULL) );
+}
+
+
+//
+//  convert:
+//             __ZN20_GLOBAL__N__Z5main2v3barEv                                        =>  _ZN-3barEv
+//             __ZN37_GLOBAL__N_main.cxx_00000000_493A01A33barEv       =>  _ZN-3barEv
+//
+static void canonicalizeAnonymousName(const char* inSymbol, char outSymbol[])
+{
+       const char* globPtr = strstr(inSymbol, "_GLOBAL__N_");
+       while ( isdigit(*(--globPtr)) )
+               ; // loop
+       char* endptr;
+       unsigned long length = strtoul(globPtr+1, &endptr, 10);
+       const char* globEndPtr = endptr + length;
+       int startLen = globPtr-inSymbol+1;
+       memcpy(outSymbol, inSymbol, startLen);
+       outSymbol[startLen] = '-';
+       strcpy(&outSymbol[startLen+1], globEndPtr);
+}
+
+
+ObjectFile::Atom* Linker::findAtom(const Options::OrderedSymbol& orderedSymbol)
+{
+       ObjectFile::Atom* atom = fGlobalSymbolTable.find(orderedSymbol.symbolName);
+       if ( atom != NULL ) {
+               if ( matchesObjectFile(atom, orderedSymbol.objectFileName) )
+                       return atom;
+       }
+       else {
+               // slow case.  The requested symbol is not in symbol table, so might be static function
+               static SymbolTable::Mapper hashTableOfTranslationUnitScopedSymbols;
+               static SymbolTable::Mapper hashTableOfSymbolsWithAnonymousNamespace;
+               static bool built = false;
+               // build a hash_map the first time
+               if ( !built ) {
+                       for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
+                               atom = *it;
+                               const char* name = atom->getName();
+                               if ( name != NULL) {
+                                       if ( usesAnonymousNamespace(name) ) {
+                                               // symbol that uses anonymous namespace
+                                               char canonicalName[strlen(name)+2];
+                                               canonicalizeAnonymousName(name, canonicalName);
+                                               const char* hashName = strdup(canonicalName);
+                                               SymbolTable::Mapper::iterator pos = hashTableOfSymbolsWithAnonymousNamespace.find(hashName);
+                                               if ( pos == hashTableOfSymbolsWithAnonymousNamespace.end() )
+                                                       hashTableOfSymbolsWithAnonymousNamespace[hashName] = atom;
+                                               else
+                                                       hashTableOfSymbolsWithAnonymousNamespace[hashName] = NULL;      // collision, denote with NULL
+                                       }
+                                       else if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
+                                               // static function or data
+                                               SymbolTable::Mapper::iterator pos = hashTableOfTranslationUnitScopedSymbols.find(name);
+                                               if ( pos == hashTableOfTranslationUnitScopedSymbols.end() )
+                                                       hashTableOfTranslationUnitScopedSymbols[name] = atom;
+                                               else
+                                                       hashTableOfTranslationUnitScopedSymbols[name] = NULL;   // collision, denote with NULL
+                                       }
+                               }
+                       }
+                       //fprintf(stderr, "built hash table of %lu static functions\n", hashTableOfTranslationUnitScopedSymbols.size());
+                       built = true;
+               }
+
+               // look for name in hashTableOfTranslationUnitScopedSymbols
+               SymbolTable::Mapper::iterator pos = hashTableOfTranslationUnitScopedSymbols.find(orderedSymbol.symbolName);
+               if ( pos != hashTableOfTranslationUnitScopedSymbols.end() ) {
+                       if ( (pos->second != NULL) && matchesObjectFile(pos->second, orderedSymbol.objectFileName) ) {
+                               //fprintf(stderr, "found %s in hash table\n", orderedSymbol.symbolName);
+                               return pos->second;
+                       }
+                       if ( pos->second == NULL )
+                       // name is in hash table, but atom is NULL, so that means there are duplicates, so we use super slow way
+                       for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
+                               atom = *it;
+                               if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
+                                       const char* name = atom->getName();
+                                       if ( (name != NULL) && (strcmp(name, orderedSymbol.symbolName) == 0) ) {
+                                               if ( matchesObjectFile(atom, orderedSymbol.objectFileName) ) {
+                                                       if ( fOptions.printOrderFileStatistics() )
+                                                               fprintf(stderr, "ld: warning %s specified in order_file but it exists in multiple .o files. "
+                                                                               "Prefix symbol with .o filename in order_file to disambiguate\n", orderedSymbol.symbolName);
+                                                       return atom;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               // look for name in hashTableOfSymbolsWithAnonymousNamespace
+               if ( usesAnonymousNamespace(orderedSymbol.symbolName) ) {
+                       // symbol that uses anonymous namespace
+                       char canonicalName[strlen(orderedSymbol.symbolName)+2];
+                       canonicalizeAnonymousName(orderedSymbol.symbolName, canonicalName);
+                       SymbolTable::Mapper::iterator pos = hashTableOfSymbolsWithAnonymousNamespace.find(canonicalName);
+                       if ( pos != hashTableOfSymbolsWithAnonymousNamespace.end() ) {
+                               if ( (pos->second != NULL) && matchesObjectFile(pos->second, orderedSymbol.objectFileName) ) {
+                                       //fprintf(stderr, "found %s in anonymous namespace hash table\n", canonicalName);
+                                       return pos->second;
+                               }
+                               if ( pos->second == NULL )
+                               // name is in hash table, but atom is NULL, so that means there are duplicates, so we use super slow way
+                               for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
+                                       atom = *it;
+                                       const char* name = atom->getName();
+                                       if ( (name != NULL) && usesAnonymousNamespace(name) ) {
+                                               char canonicalAtomName[strlen(name)+2];
+                                               canonicalizeAnonymousName(name, canonicalAtomName);
+                                               if ( strcmp(canonicalAtomName, canonicalName) == 0 ) {
+                                                       if ( matchesObjectFile(atom, orderedSymbol.objectFileName) ) {
+                                                               if ( fOptions.printOrderFileStatistics() )
+                                                                       fprintf(stderr, "ld: warning %s specified in order_file but it exists in multiple .o files. "
+                                                                               "Prefix symbol with .o filename in order_file to disambiguate\n", orderedSymbol.symbolName);
+                                                               return atom;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return NULL;
+}
+
+
+void Linker::sortSections()
+{
+       Section::assignIndexes();
+}
+
+
+//
+// Linker::sortAtoms()
+//
+// The purpose of this method is to take the graph of all Atoms and produce an ordered
+// sequence of atoms.  The constraints are that: 1) all Atoms of the same Segment must
+// be contiguous, 2)  all Atoms of the same Section must be contigous, 3) Atoms specified
+// in an order_file are seqenced as in the order_file and before Atoms not specified,
+// 4) Atoms in the same section from the same .o file should be contiguous and sequenced
+// in the same order they were in the .o file, 5) Atoms in the same Section but which came
+// from different .o files should be sequenced in the same order that the .o files
+// were passed to the linker (i.e. command line order).
+//
+// The way this is implemented is that the linker passes a "base ordinal" to each Reader
+// as it is constructed.  The reader should construct it Atoms so that calling getOrdinal()
+// on its atoms returns a contiguous range of values starting at the base ordinal.  Then
+// sorting is just sorting by section, then by ordinal.
+//
+// If an order_file is specified, it gets more complicated.  First, an override-ordinal map
+// is created.  It causes the sort routine to ignore the value returned by getOrdinal() and
+// use the override value instead.  Next some Atoms must be layed out consecutively
+// (e.g. hand written assembly that does not end with return, but rather falls into
+// the next label).  This is modeled in Readers via a "kFollowOn" reference.  The use of
+// kFollowOn refernces produces "clusters" of atoms that must stay together.
+// If an order_file tries to move one atom, it may need to move a whole cluster.  The
+// algorithm to do this models clusters using two maps.  The "starts" maps maps any
+// atom in a cluster to the first Atom in the cluster.  The "nexts" maps an Atom in a
+// cluster to the next Atom in the cluster.  With this in place, while processing an
+// order_file, if any entry is in a cluster (in "starts" map), then the entire cluster is
+// given ordinal overrides.
+//
+void Linker::sortAtoms()
+{
+       fStartSortTime = mach_absolute_time();
+       // if -order_file is used, build map of atom ordinal overrides
+       std::map<const ObjectFile::Atom*, uint32_t>* ordinalOverrideMap = NULL;
+       std::map<const ObjectFile::Atom*, uint32_t> theOrdinalOverrideMap;
+       const bool log = false;
+       if ( fOptions.orderedSymbols().size() != 0 ) {
+               // first make a pass to find all follow-on references and build start/next maps
+               // which are a way to represent clusters of atoms that must layout together
+               std::map<const ObjectFile::Atom*, const ObjectFile::Atom*> followOnStarts;
+               std::map<const ObjectFile::Atom*, const ObjectFile::Atom*> followOnNexts;
+               for (std::vector<ObjectFile::Atom*>::iterator ait=fAllAtoms.begin(); ait != fAllAtoms.end(); ait++) {
+                       ObjectFile::Atom* atom = *ait;
+                       std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
+                       for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
+                               ObjectFile::Reference* ref = *rit;
+                               if ( ref->getKind() == 1 ) {    // FIX FIX
+                                       ObjectFile::Atom* targetAtom = &ref->getTarget();
+                                       if ( log ) fprintf(stderr, "ref %s -> %s", atom->getDisplayName(), targetAtom->getDisplayName());
+                                       std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator startFrom = followOnStarts.find(atom);
+                                       std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator startTo = followOnStarts.find(targetAtom);
+                                       if ( (startFrom == followOnStarts.end()) && (startTo == followOnStarts.end()) ) {
+                                               // this is first time we've seen either atom, make simple cluster of the two
+                                               if ( log ) fprintf(stderr, "  new cluster\n");
+                                               followOnStarts[atom] = atom;
+                                               followOnStarts[targetAtom] = atom;
+                                               followOnNexts[atom] = targetAtom;
+                                               followOnNexts[targetAtom] = NULL;
+                                       }
+                                       else if ( (startFrom != followOnStarts.end()) && (startTo == followOnStarts.end()) && (followOnNexts[atom] == NULL) ) {
+                                               // atom is at end of an existing cluster, so append target to end of cluster
+                                               if ( log ) fprintf(stderr, "  end of cluster starting with %s\n", followOnStarts[atom]->getDisplayName());
+                                               followOnNexts[atom] = targetAtom;
+                                               followOnNexts[targetAtom] = NULL;
+                                               followOnStarts[targetAtom] = followOnStarts[atom];
+                                       }
+                                       else {
+                                               // gerneral case of inserting into an existing cluster
+                                               if ( followOnNexts[atom] != NULL ) {
+                                                       // an atom with two follow-ons is illegal
+                                                       fprintf(stderr, "ld: warning can't order %s because both %s and %s must follow it\n",
+                                                                               atom->getDisplayName(), targetAtom->getDisplayName(), followOnNexts[atom]->getDisplayName());
+                                               }
+                                               else {
+                                                       // there already exists an atom that says target must be its follow-on
+                                                       const ObjectFile::Atom* originalStart = startTo->second;
+                                                       const ObjectFile::Atom* originalPrevious = originalStart;
+                                                       while ( followOnNexts[originalPrevious] != targetAtom )
+                                                               originalPrevious = followOnNexts[originalPrevious];
+                                                       bool otherIsAlias = (originalPrevious->getSize() == 0);
+                                                       bool thisIsAlias = (atom->getSize() == 0);
+                                                       if ( !otherIsAlias && !thisIsAlias ) {
+                                                               fprintf(stderr, "ld: warning can't order %s because both %s and %s must preceed it\n",
+                                                                                       targetAtom->getDisplayName(), originalPrevious->getDisplayName(), atom->getDisplayName());
+                                                       }
+                                                       else if ( otherIsAlias ) {
+                                                               if ( originalPrevious == originalStart ) {
+                                                                       // other is alias at start of cluster, make this the new start of cluster
+                                                                       if ( log ) fprintf(stderr, "  becomes new start of cluster previous starting with %s\n", originalStart->getDisplayName());
+                                                                       followOnNexts[atom] = originalPrevious;
+                                                                       for(const ObjectFile::Atom* nextAtom = atom; nextAtom != NULL; nextAtom = followOnNexts[nextAtom])
+                                                                               followOnStarts[nextAtom] = atom;
+                                                               }
+                                                               else {
+                                                                       // other is alias in middle of cluster, insert new atom before it
+                                                                       if ( log ) fprintf(stderr, "  insert into cluster starting with %s before alias %s\n", originalStart->getDisplayName(), originalPrevious->getDisplayName());
+                                                                       followOnStarts[atom] = originalStart;
+                                                                       followOnNexts[atom] = originalPrevious;
+                                                                       for(const ObjectFile::Atom* a = originalStart; a != NULL; a = followOnNexts[a]) {
+                                                                               if ( followOnNexts[a] == originalPrevious ) {
+                                                                                       followOnNexts[a] = atom;
+                                                                                       break;
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                                       else {
+                                                               // this is alias, so it can go inbetween originalPrevious and targetAtom
+                                                               if ( log ) fprintf(stderr, "  insert into cluster starting with %s after %s\n", originalStart->getDisplayName(), originalPrevious->getDisplayName());
+                                                               followOnStarts[atom] = originalStart;
+                                                               followOnNexts[atom] = followOnNexts[originalPrevious];
+                                                               followOnNexts[originalPrevious] = atom;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if ( log ) {
+                       for(std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator it = followOnStarts.begin(); it != followOnStarts.end(); ++it)
+                               fprintf(stderr, "start %s -> %s\n", it->first->getDisplayName(), it->second->getDisplayName());
+
+                       for(std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator it = followOnNexts.begin(); it != followOnNexts.end(); ++it)
+                               fprintf(stderr, "next %s -> %s\n", it->first->getDisplayName(), (it->second != NULL) ? it->second->getDisplayName() : "null");
+               }
+
+               // with the start/next maps of follow-on atoms we can process the order file and produce override ordinals
+               ordinalOverrideMap = &theOrdinalOverrideMap;
+               uint32_t index = 0;
+               uint32_t matchCount = 0;
+               std::vector<Options::OrderedSymbol>& orderedSymbols = fOptions.orderedSymbols();
+               for(std::vector<Options::OrderedSymbol>::iterator it = orderedSymbols.begin(); it != orderedSymbols.end(); ++it) {
+                       ObjectFile::Atom* atom = this->findAtom(*it);
+                       if ( atom != NULL ) {
+                               std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator start = followOnStarts.find(atom);
+                               if ( start != followOnStarts.end() ) {
+                                       // this symbol for the order file corresponds to an atom that is in a cluster that must lay out together
+                                       for(const ObjectFile::Atom* nextAtom = start->second; nextAtom != NULL; nextAtom = followOnNexts[nextAtom]) {
+                                               std::map<const ObjectFile::Atom*, uint32_t>::iterator pos = theOrdinalOverrideMap.find(nextAtom);
+                                               if ( pos == theOrdinalOverrideMap.end() ) {
+                                                       theOrdinalOverrideMap[nextAtom] = index++;
+                                                       if (log ) fprintf(stderr, "override ordinal %u assigned to %s in cluster from %s\n", index, nextAtom->getDisplayName(), nextAtom->getFile()->getPath());
+                                               }
+                                               else {
+                                                       if (log ) fprintf(stderr, "could not order %s as %u because it was already laid out earlier by %s as %u\n",
+                                                                                       atom->getDisplayName(), index, followOnStarts[atom]->getDisplayName(), theOrdinalOverrideMap[atom] );
+                                               }
+                                       }
+                               }
+                               else {
+                                       theOrdinalOverrideMap[atom] = index;
+                                       if (log ) fprintf(stderr, "override ordinal %u assigned to %s from %s\n", index, atom->getDisplayName(), atom->getFile()->getPath());
                                }
                        }
+                       else {
+                               ++matchCount;
+                               //fprintf(stderr, "can't find match for order_file entry %s/%s\n", it->objectFileName, it->symbolName);
+                       }
+                        ++index;
+               }
+               if ( fOptions.printOrderFileStatistics() && (fOptions.orderedSymbols().size() != matchCount) ) {
+                       fprintf(stderr, "ld: warning only %u out of %lu order_file symbols were applicable\n", matchCount, fOptions.orderedSymbols().size() );
                }
        }
-       
-       // now remove all non-live atoms from fAllAtoms
-       fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), NotLive(fLiveAtoms)), fAllAtoms.end());
-}
 
-void Linker::sortAtoms()
-{
-       fStartSortTime = mach_absolute_time();
-       Section::assignIndexes();
-       std::sort(fAllAtoms.begin(), fAllAtoms.end(), Linker::AtomSorter());
+       // sort atoms
+       std::sort(fAllAtoms.begin(), fAllAtoms.end(), Linker::AtomSorter(ordinalOverrideMap));
+
        //fprintf(stderr, "Sorted atoms:\n");
        //for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
-       //      fprintf(stderr, "\t%s\n", (*it)->getDisplayName());
+       //      fprintf(stderr, "\t%p, %u  %s\n", (*it)->getSection(), (*it)->getSection()->getIndex(), (*it)->getDisplayName());
        //}
 }
 
@@ -1147,6 +1908,21 @@ void Linker::sortAtoms()
 // make sure given addresses are within reach of branches, etc
 void Linker::tweakLayout()
 {
+       // > 2GB images need their large zero fill atoms sorted to the end to keep access with +/- 2GB
+       if ( fTotalSize > 0x7F000000 ) {
+               fBiggerThanTwoGigOutput = true;
+
+               if ( (fTotalSize-fTotalZeroFillSize) > 0x7F000000 )
+                       throwf("total output size exceeds 2GB (%lldMB)", (fTotalSize-fTotalZeroFillSize)/(1024*1024));          
+
+               // move very large (>1MB) zero fill atoms to a new section at very end
+               Section* hugeZeroFills = Section::find("__huge", "__DATA", true);
+               for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
+                       ObjectFile::Atom* atom = *it;
+                       if ( atom->isZeroFill() && (atom->getSize() > 1024*1024) && atom->getSegment().isContentReadable() )
+                               atom->setSection(hugeZeroFills);
+               }
+       }
 }
 
 
@@ -1224,7 +2000,7 @@ void Linker::writeDotOutput()
                        fclose(out);
                }
                else {
-                       fprintf(stderr, "ld64 warning: could not write dot output file: %s\n", dotOutFilePath);
+                       fprintf(stderr, "ld: warning could not write dot output file: %s\n", dotOutFilePath);
                }
        }
 }
@@ -1402,7 +2178,7 @@ void Linker::collectStabs(ObjectFile::Reader* reader, std::map<const class Objec
                                break;
                        case N_EINCL:
                                if ( curRangeIndex == -1 ) {
-                                       fprintf(stderr, "ld64 warning: EINCL missing BINCL in %s\n", reader->getPath());
+                                       fprintf(stderr, "ld: warning EINCL missing BINCL in %s\n", reader->getPath());
                                }
                                else {
                                        ranges[curRangeIndex].end = it+1;
@@ -1436,7 +2212,7 @@ void Linker::collectStabs(ObjectFile::Reader* reader, std::map<const class Objec
                                if ( curRangeIndex != -1 ) {
                                        ranges[curRangeIndex].cannotEXCL = true;
                                        if ( fOptions.warnStabs() )
-                                               fprintf(stderr, "ld64: cannot do BINCL/EINCL optimzation because of stabs kinds in %s for %s\n", ranges[curRangeIndex].begin->string, reader->getPath());
+                                               fprintf(stderr, "ld: cannot do BINCL/EINCL optimzation because of stabs kinds in %s for %s\n", ranges[curRangeIndex].begin->string, reader->getPath());
                                }
                                break;
                        case N_SO:
@@ -1474,7 +2250,7 @@ void Linker::collectStabs(ObjectFile::Reader* reader, std::map<const class Objec
        }
        if ( log ) fprintf(stderr, "processesed %d stabs for %s\n", count, reader->getPath());
        if ( curRangeIndex != -1 )
-               fprintf(stderr, "ld64 warning: BINCL (%s) missing EINCL in %s\n", ranges[curRangeIndex].begin->string, reader->getPath());
+               fprintf(stderr, "ld: warning BINCL (%s) missing EINCL in %s\n", ranges[curRangeIndex].begin->string, reader->getPath());
 
        // if no BINCLs
        if ( ranges.size() == 0 ) {
@@ -1569,7 +2345,7 @@ void Linker::collectStabs(ObjectFile::Reader* reader, std::map<const class Objec
                                        ObjectFile::Reader::Stab stab = *it;
                                        if ( !minimal || minimizeStab(stab) ) {
                                                if ( stab.type == N_SO ) {
-                                                       if ( (stab.string != NULL) || (strlen(stab.string) > 0) ) {
+                                                       if ( (stab.string != NULL) && (strlen(stab.string) > 0) ) {
                                                                // starting SO is associated with first atom
                                                                stab.atom = soRanges[soIndex].first;
                                                        }
@@ -1592,7 +2368,7 @@ void Linker::collectStabs(ObjectFile::Reader* reader, std::map<const class Objec
 class NoDebugNoteAtom
 {
 public:
-       NoDebugNoteAtom(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals) 
+       NoDebugNoteAtom(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals)
                        : fReadersWithDwarfOrdinals(readersWithDwarfOrdinals) {}
 
        bool operator()(const ObjectFile::Atom* atom) const {
@@ -1613,8 +2389,8 @@ private:
 class ReadersWithDwarfSorter
 {
 public:
-       ReadersWithDwarfSorter(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals, 
-                                                  const std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals) 
+       ReadersWithDwarfSorter(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals,
+                                                  const std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals)
                        : fReadersWithDwarfOrdinals(readersWithDwarfOrdinals), fAtomOrdinals(atomOrdinals) {}
 
        bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right) const
@@ -1646,6 +2422,7 @@ void Linker::synthesizeDebugNotes(std::vector<class ObjectFile::Atom*>& allAtoms
        const char* dirPath = NULL;
        const char* filename = NULL;
        bool wroteStartSO = false;
+       bool useZeroOSOModTime = (getenv("RC_RELEASE") != NULL);
        __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals>  seenFiles;
        for (std::vector<ObjectFile::Atom*>::iterator it=allAtomsByReader.begin(); it != allAtomsByReader.end(); it++) {
                ObjectFile::Atom* atom = *it;
@@ -1692,7 +2469,7 @@ void Linker::synthesizeDebugNotes(std::vector<class ObjectFile::Atom*>& allAtoms
                                objStab.type            = N_OSO;
                                objStab.other           = 0;
                                objStab.desc            = 1;
-                               objStab.value           = atom->getFile()->getModificationTime();
+                               objStab.value           = useZeroOSOModTime ? 0 : atom->getFile()->getModificationTime();
                                objStab.string          = assureFullPath(atom->getFile()->getPath());
                                fStabs.push_back(objStab);
                                wroteStartSO = true;
@@ -1839,10 +2616,10 @@ void Linker::collectDebugInfo()
                                }
                        }
                }
-               
+
                if ( someDwarf || someStabs ) {
                        // try to minimize re-allocations
-                       fStabs.reserve(1024); 
+                       fStabs.reserve(1024);
 
                        // make mapping from atoms to ordinal
                        uint32_t ordinal = 1;
@@ -1850,7 +2627,7 @@ void Linker::collectDebugInfo()
                                atomOrdinals[*it] = ordinal++;
                        }
                }
-                       
+
                // process all dwarf .o files as a batch
                if ( someDwarf ) {
                        // make mapping from readers with dwarf to ordinal
@@ -1864,18 +2641,18 @@ void Linker::collectDebugInfo()
                                        readersWithDwarfOrdinals[reader] = readerOrdinal++;
                                }
                        }
-               
-                       // make a vector of atoms 
+
+                       // make a vector of atoms
                        std::vector<class ObjectFile::Atom*> allAtomsByReader(fAllAtoms.begin(), fAllAtoms.end());
                        // remove those not from a reader that has dwarf
-                       allAtomsByReader.erase(std::remove_if(allAtomsByReader.begin(), allAtomsByReader.end(), 
+                       allAtomsByReader.erase(std::remove_if(allAtomsByReader.begin(), allAtomsByReader.end(),
                                                                NoDebugNoteAtom(readersWithDwarfOrdinals)), allAtomsByReader.end());
                        // sort by reader then atom ordinal
                        std::sort(allAtomsByReader.begin(), allAtomsByReader.end(), ReadersWithDwarfSorter(readersWithDwarfOrdinals, atomOrdinals));
                        // add debug notes for each atom
                        this->synthesizeDebugNotes(allAtomsByReader);
                }
-               
+
                // process all stabs .o files one by one
                if ( someStabs ) {
                        // get stabs from each reader, in command line order
@@ -1908,9 +2685,14 @@ void Linker::collectDebugInfo()
 
 void Linker::writeOutput()
 {
+       if ( fOptions.forceCpuSubtypeAll() )
+               fCurrentCpuConstraint = ObjectFile::Reader::kCpuAny;
+               
        fStartWriteTime = mach_absolute_time();
        // tell writer about each segment's atoms
-       fOutputFileSize = fOutputFile->write(fAllAtoms, fStabs, this->entryPoint(), this->dyldHelper(), (fCreateUUID && fOptions.emitUUID()));
+       fOutputFileSize = fOutputFile->write(fAllAtoms, fStabs, this->entryPoint(), this->dyldHelper(),
+                                                                                       fCreateUUID, fCanScatter, 
+                                                                                       fCurrentCpuConstraint, fBiggerThanTwoGigOutput);
 }
 
 ObjectFile::Reader* Linker::createReader(const Options::FileInfo& info)
@@ -1957,38 +2739,43 @@ ObjectFile::Reader* Linker::createReader(const Options::FileInfo& info)
        switch (fArchitecture) {
                case CPU_TYPE_POWERPC:
                        if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
-                               return this->addObject(mach_o::relocatable::Reader<ppc>::make(p, info.path, info.modTime, fOptions.readerOptions()), info, len);
+                               return this->addObject(new mach_o::relocatable::Reader<ppc>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        else if ( mach_o::dylib::Reader<ppc>::validFile(p, info.options.fBundleLoader) )
-                               return this->addDylib(mach_o::dylib::Reader<ppc>::make(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions()), info, len);
+                               return this->addDylib(new mach_o::dylib::Reader<ppc>::Reader(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        else if ( mach_o::archive::Reader<ppc>::validFile(p, len) )
-                               return this->addArchive(mach_o::archive::Reader<ppc>::make(p, len, info.path, info.modTime, fOptions.readerOptions()), info, len);
+                               return this->addArchive(new mach_o::archive::Reader<ppc>::Reader(p, len, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        break;
                case CPU_TYPE_POWERPC64:
                        if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
-                               return this->addObject(mach_o::relocatable::Reader<ppc64>::make(p, info.path, info.modTime, fOptions.readerOptions()), info, len);
+                               return this->addObject(new mach_o::relocatable::Reader<ppc64>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        else if ( mach_o::dylib::Reader<ppc64>::validFile(p, info.options.fBundleLoader) )
-                               return this->addDylib(mach_o::dylib::Reader<ppc64>::make(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions()), info, len);
+                               return this->addDylib(new mach_o::dylib::Reader<ppc64>::Reader(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        else if ( mach_o::archive::Reader<ppc64>::validFile(p, len) )
-                               return this->addArchive(mach_o::archive::Reader<ppc64>::make(p, len, info.path, info.modTime, fOptions.readerOptions()), info, len);
+                               return this->addArchive(new mach_o::archive::Reader<ppc64>::Reader(p, len, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        break;
                case CPU_TYPE_I386:
                        if ( mach_o::relocatable::Reader<x86>::validFile(p) )
-                               return this->addObject(mach_o::relocatable::Reader<x86>::make(p, info.path, info.modTime, fOptions.readerOptions()), info, len);
+                               return this->addObject(new mach_o::relocatable::Reader<x86>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        else if ( mach_o::dylib::Reader<x86>::validFile(p, info.options.fBundleLoader) )
-                               return this->addDylib(mach_o::dylib::Reader<x86>::make(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions()), info, len);
+                               return this->addDylib(new mach_o::dylib::Reader<x86>::Reader(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        else if ( mach_o::archive::Reader<x86>::validFile(p, len) )
-                               return this->addArchive(mach_o::archive::Reader<x86>::make(p, len, info.path, info.modTime, fOptions.readerOptions()), info, len);
+                               return this->addArchive(new mach_o::archive::Reader<x86>::Reader(p, len, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        break;
                case CPU_TYPE_X86_64:
                        if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
-                               return this->addObject(mach_o::relocatable::Reader<x86_64>::make(p, info.path, info.modTime, fOptions.readerOptions()), info, len);
+                               return this->addObject(new mach_o::relocatable::Reader<x86_64>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        else if ( mach_o::dylib::Reader<x86_64>::validFile(p, info.options.fBundleLoader) )
-                               return this->addDylib(mach_o::dylib::Reader<x86_64>::make(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions()), info, len);
+                               return this->addDylib(new mach_o::dylib::Reader<x86_64>::Reader(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        else if ( mach_o::archive::Reader<x86_64>::validFile(p, len) )
-                               return this->addArchive(mach_o::archive::Reader<x86_64>::make(p, len, info.path, info.modTime, fOptions.readerOptions()), info, len);
+                               return this->addArchive(new mach_o::archive::Reader<x86_64>::Reader(p, len, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
                        break;
        }
 
+#if LLVM_SUPPORT
+       if ( LLVMReader::validFile(p, info.path, fArchitecture, fOptions) ) {
+               return this->addObject(LLVMReader::make(p, info.path, info.modTime, fOptions), info, len);
+       }
+#endif
        // error handling
        if ( ((fat_header*)p)->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
                throwf("missing required architecture %s in file", fArchitectureName);
@@ -1998,6 +2785,121 @@ ObjectFile::Reader* Linker::createReader(const Options::FileInfo& info)
        }
 }
 
+void Linker::logDylib(ObjectFile::Reader* reader, bool indirect)
+{
+       if ( fOptions.readerOptions().fTraceDylibs ) {
+               const char* fullPath = reader->getPath();
+               char realName[MAXPATHLEN];
+               if ( realpath(fullPath, realName) != NULL )
+                       fullPath = realName;
+               if ( indirect )
+                       logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath);
+               else
+                       logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
+       }
+}
+
+
+
+ObjectFile::Reader* Linker::findDylib(const char* installPath, const char* fromPath)
+{
+       //fprintf(stderr, "findDylib(%s, %s)\n", installPath, fromPath);
+       InstallNameToReader::iterator pos = fDylibMap.find(installPath);
+       if ( pos != fDylibMap.end() ) {
+               return pos->second;
+       }
+       else {
+               // allow -dylib_path option to override indirect library to use
+               for (std::vector<Options::DylibOverride>::iterator dit = fOptions.dylibOverrides().begin(); dit != fOptions.dylibOverrides().end(); ++dit) {
+                       if ( strcmp(dit->installName,installPath) == 0 ) {\
+                               try {
+                                       Options::FileInfo info = fOptions.findFile(dit->useInstead);
+                                       ObjectFile::Reader* reader = this->createReader(info);
+                                       fDylibMap[strdup(installPath)] = reader;
+                                       this->logDylib(reader, true);
+                                       return reader;
+                               }
+                               catch (const char* msg) {
+                                       fprintf(stderr, "ld: warning ignoring -dylib_file option, %s\n", msg);
+                               }
+                       }
+               }
+               char newPath[MAXPATHLEN];
+               // handle @loader_path
+               if ( strncmp(installPath, "@loader_path/", 13) == 0 ) {
+                       strcpy(newPath, fromPath);
+                       char* addPoint = strrchr(newPath,'/');
+                       if ( addPoint != NULL )
+                               strcpy(&addPoint[1], &installPath[13]);
+                       else
+                               strcpy(newPath, &installPath[13]);
+                       installPath = newPath;
+               }
+               // note: @executable_path case is handled inside findFileUsingPaths()
+               // search for dylib using -F and -L paths
+               Options::FileInfo info = fOptions.findFileUsingPaths(installPath);
+               try {
+                       ObjectFile::Reader* reader = this->createReader(info);
+                       fDylibMap[strdup(installPath)] = reader;
+                       this->logDylib(reader, true);
+                       return reader;
+               }
+               catch (const char* msg) {
+                       throwf("in %s, %s", info.path, msg);
+               }
+       }
+}
+
+
+void Linker::processDylibs()
+{
+       fAllDirectDylibsLoaded = true;
+
+       // mark all dylibs initially specified as required and check if they can be used
+       for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
+               it->second->setExplicitlyLinked();
+               this->checkDylibClientRestrictions(it->second);
+       }
+       
+       // keep processing dylibs until no more dylibs are added
+       unsigned long lastMapSize = 0;
+       while ( lastMapSize != fDylibMap.size() ) {
+               lastMapSize = fDylibMap.size();
+               // can't iterator fDylibMap while modifying it, so use temp buffer
+               std::vector<ObjectFile::Reader*> currentUnprocessedReaders;
+               for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
+                       if ( fDylibsProcessed.count(it->second) == 0 )
+                               currentUnprocessedReaders.push_back(it->second);
+               }
+               for (std::vector<ObjectFile::Reader*>::iterator it=currentUnprocessedReaders.begin(); it != currentUnprocessedReaders.end(); it++) {
+                       fDylibsProcessed.insert(*it);
+                       (*it)->processIndirectLibraries(this);
+               }
+       }
+       
+       // go back over original dylibs and mark sub frameworks as re-exported
+       if ( fOptions.outputKind() == Options::kDynamicLibrary ) {
+               const char* myLeaf = strrchr(fOptions.installPath(), '/');
+               if ( myLeaf != NULL ) {
+                       for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
+                               ObjectFile::Reader* reader = *it;
+                               const char* childParent = reader->parentUmbrella();
+                               if ( childParent != NULL ) {
+                                       if ( strcmp(childParent, &myLeaf[1]) == 0 ) {
+                                               // set re-export bit of info
+                                               std::map<ObjectFile::Reader*,DynamicLibraryOptions>::iterator pos = fDylibOptionsMap.find(reader);
+                                               if ( pos != fDylibOptionsMap.end() ) {
+                                                       pos->second.fReExport = true;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+}
+
+       
 
 void Linker::createReaders()
 {
@@ -2012,7 +2914,7 @@ void Linker::createReaders()
                // ignore /usr/lib/dyld on command line in crt.o build
                if ( strcmp(entry.path, "/usr/lib/dyld") != 0 ) {
                        try {
-                               this->addInputFile(this->createReader(entry));
+                               this->addInputFile(this->createReader(entry), entry);
                        }
                        catch (const char* msg) {
                                if ( strstr(msg, "architecture") != NULL ) {
@@ -2020,7 +2922,7 @@ void Linker::createReaders()
                                                // ignore, because this is about an architecture not in use
                                        }
                                        else {
-                                               fprintf(stderr, "ld64 warning: in %s, %s\n", entry.path, msg);
+                                               fprintf(stderr, "ld: warning in %s, %s\n", entry.path, msg);
                                        }
                                }
                                else {
@@ -2030,115 +2932,16 @@ void Linker::createReaders()
                }
        }
 
-       // add first level of indirect dylibs
-       fDirectLibrariesComplete = true;
-       for (std::vector<ExecutableFile::DyLibUsed>::iterator it=fDynamicLibraries.begin(); it != fDynamicLibraries.end(); it++) {
-               this->addIndirectLibraries(it->reader);
-       }
-
-       // indirect handling depends on namespace
-       switch ( fOptions.nameSpace() ) {
-               case Options::kFlatNameSpace:
-               case Options::kForceFlatNameSpace:
-                       // with flat namespace, blindly load all indirect libraries
-                       // the indirect list will grow as indirect libraries are loaded
-                       for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
-                               try {
-                                       it->reader = this->createReader(fOptions.findFile(it->path));
-                                       it->reader->setSortOrder(fNextObjectFileOrder++);
-                               }
-                               catch (const char* msg) {
-                                       fprintf(stderr, "ld64 warning: indirect library %s could not be loaded: %s\n", it->path, msg);
-                               }
-                       }
-                       break;
-
-               case Options::kTwoLevelNameSpace:
-                       // with two-level namespace we only want to use indirect libraries that are re-exported through a library that is used
-                       {
-                               bool indirectAdded = true;
-                               while ( indirectAdded ) {
-                                       indirectAdded = false;
-                                       // instantiate a reader for each indirect library and try to find parent that re-exports it
-                                       for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
-                                               if ( it->reader == NULL ) {
-                                                       try {
-                                                               it->reader = this->createReader(fOptions.findFile(it->path));
-                                                               it->reader->setSortOrder(fNextObjectFileOrder++);
-                                                               indirectAdded = true;
-                                                       }
-                                                       catch (const char* msg) {
-                                                               fprintf(stderr, "ld64 warning: indirect library %s could not be loaded: %s\n", it->path, msg);
-                                                       }
-                                               }
-                                               // if an indirect library does not have an assigned parent, look for one
-                                               if ( (it->reader != NULL) && (it->reExportedViaDirectLibrary == NULL) ) {
-                                                       it->reExportedViaDirectLibrary = this->findDirectLibraryWhichReExports(*it);
-                                               }
-                                       }
-                               }
-                       }
-                       break;
-       }
-
-       // add relevant indirect libraries to the end of fDynamicLibraries
-       for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
-               if ( (it->reader != NULL) && (it->reExportedViaDirectLibrary != NULL) || (fOptions.nameSpace() != Options::kTwoLevelNameSpace) ) {
-                       ExecutableFile::DyLibUsed dylibInfo;
-                       dylibInfo.reader = it->reader;
-                       dylibInfo.options.fWeakImport = false;
-                       dylibInfo.options.fReExport = false;
-                       dylibInfo.options.fInstallPathOverride = NULL;
-                       dylibInfo.indirect = true;
-                       dylibInfo.directReader = it->reExportedViaDirectLibrary;
-                       fDynamicLibraries.push_back(dylibInfo);
-                       if ( fOptions.readerOptions().fTraceIndirectDylibs ) {
-                               const char* fullPath = it->reader->getPath();
-                               char realName[MAXPATHLEN];
-                               if ( realpath(fullPath, realName) != NULL )
-                                       fullPath = realName;
-                               logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath);
-                       }
-               }
-       }
-}
-
-
-ObjectFile::Reader* Linker::findDirectLibraryWhichReExports(IndirectLibrary& indirectLib)
-{
-       // ask each parent if they re-export this dylib
-       for (std::set<ObjectFile::Reader*>::iterator pit=indirectLib.parents.begin(); pit != indirectLib.parents.end(); pit++) {
-               if ( (*pit)->reExports(indirectLib.reader) ) {
-                       ObjectFile::Reader* lib = *pit;
-                       // first check if we found a direct library, if so return it
-                       for (std::vector<ExecutableFile::DyLibUsed>::iterator dit=fDynamicLibraries.begin(); dit != fDynamicLibraries.end(); dit++) {
-                               if ( dit->reader == lib && dit->indirect == false )
-                                       return lib;
-                       }
-                       // otherwise search indirects for parent and see how it is reexported
-                       for (std::list<IndirectLibrary>::iterator iit=fIndirectDynamicLibraries.begin(); iit != fIndirectDynamicLibraries.end(); iit++) {
-                               if ( iit->reader == lib ) {
-                                       ObjectFile::Reader* lib2 = this->findDirectLibraryWhichReExports(*iit);
-                                       if ( lib2 != NULL )
-                                               return lib2;
-                               }
-                       }
-               }
-       }
-       return NULL;
+       this->processDylibs();
 }
 
 
 
 ObjectFile::Reader* Linker::addArchive(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
 {
-       if (fOptions.readerOptions().fTraceArchives) {
-               const char* fullPath = reader->getPath();
-               char realName[MAXPATHLEN];
-               if ( realpath(fullPath, realName) != NULL )
-                       fullPath = realName;
-               logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath);
-       }
+       fNextInputOrdinal += mappedLen;
+       // remember which readers are archives because they are logged differently
+       fArchiveReaders.insert(reader);
 
        // update stats
        fTotalArchiveSize += mappedLen;
@@ -2148,57 +2951,49 @@ ObjectFile::Reader* Linker::addArchive(ObjectFile::Reader* reader, const Options
 
 ObjectFile::Reader* Linker::addObject(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
 {
+       fNextInputOrdinal += mappedLen;
+       // any .o files that don't have MH_SUBSECTIONS_VIA_SYMBOLS, that means a generated .o file can't
+       if ( (fOptions.outputKind() == Options::kObjectFile) && !reader->canScatterAtoms() )
+               fCanScatter = false;
+
        // update stats
        fTotalObjectSize += mappedLen;
        ++fTotalObjectLoaded;
        return reader;
 }
 
-ObjectFile::Reader* Linker::addDylib(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
-{
-       if ( (reader->getInstallPath() == NULL) && !info.options.fBundleLoader ) {
-               // this is a "blank" stub
-               // silently ignore it
-               return reader;
-       }
 
-       if ( fDirectLibrariesComplete ) {
-               this->addIndirectLibraries(reader);
-       }
-       else {
-               if ( fOptions.readerOptions().fTraceDylibs ) {
-                       const char* fullPath = reader->getPath();
-                       char realName[MAXPATHLEN];
-                       if ( realpath(fullPath, realName) != NULL )
-                               fullPath = realName;
-                       logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
-               }
-               ExecutableFile::DyLibUsed dylibInfo;
-               dylibInfo.reader = reader;
-               dylibInfo.options = info.options;
-               dylibInfo.indirect = false;
-               dylibInfo.directReader = NULL;
-               fDynamicLibraries.push_back(dylibInfo);
-
-
-               // Verify that a client is allowed to link to this dylib.  There are three cases.
-               bool okToLink = true;
-               const char* outputFilePath = fOptions.installPath();
-               const char* outputFilePathLastSlash = strrchr(outputFilePath, '/');
-               if ( reader->parentUmbrella() != NULL ) {
+void Linker::checkDylibClientRestrictions(ObjectFile::Reader* reader)
+{
+       // Check for any restrictions on who can link with this dylib  
+       const char* readerParentName = reader->parentUmbrella() ;
+       std::vector<const char*>* clients = reader->getAllowableClients();
+       if ( (readerParentName != NULL) || (clients != NULL) ) {
+               // only dylibs that are in an umbrella or have a client list need verification
+               const char* installName = fOptions.installPath();
+               const char* installNameLastSlash = strrchr(installName, '/');
+               bool isParent = false;
+               bool isSibling = false;
+               bool isAllowableClient = false;
+               // There are three cases:
+               if ( (readerParentName != NULL) && (installNameLastSlash != NULL) ) {
                        // case 1) The dylib has a parent umbrella, and we are creating the parent umbrella
-                       okToLink = ( (outputFilePathLastSlash != NULL) && (strcmp(&outputFilePathLastSlash[1], reader->parentUmbrella()) == 0) );
-               }
-
-               if ( !okToLink && (reader->parentUmbrella() != NULL) ) {
+                       isParent = ( strcmp(&installNameLastSlash[1], readerParentName) == 0 );
+                       
+                       // hack to support umbrella variants that encode the variant name in the install name 
+                       // e.g. CoreServices_profile
+                       if ( !isParent ) {
+                               const char* underscore = strchr(&installNameLastSlash[1], '_');
+                               if ( underscore != NULL ) {
+                                       isParent = ( strncmp(&installNameLastSlash[1], readerParentName, underscore-installNameLastSlash-1) == 0 );
+                               }
+                       }
+                       
                        // case 2) The dylib has a parent umbrella, and we are creating a sibling with the same parent
-                       okToLink = ( (outputFilePathLastSlash != NULL)
-                                       && (fOptions.umbrellaName() != NULL)
-                                       && (strcmp(fOptions.umbrellaName(), reader->parentUmbrella()) == 0) );
+                       isSibling = ( (fOptions.umbrellaName() != NULL) && (strcmp(fOptions.umbrellaName(), readerParentName) == 0) );
                }
 
-               std::vector<const char*>* clients = reader->getAllowableClients();
-               if ( !okToLink && (clients != NULL) ) {
+               if ( !isParent && !isSibling && (clients != NULL) ) {
                        // case 3) the dylib has a list of allowable clients, and we are creating one of them
                        const char* clientName = fOptions.clientName();
                        int clientNameLen = 0;
@@ -2207,96 +3002,82 @@ ObjectFile::Reader* Linker::addDylib(ObjectFile::Reader* reader, const Options::
                                clientNameLen = strlen(clientName);
                        }
                        else {
-                               // infer client name from output path (e.g. xxx/libfoo.A.dylib --> foo, Bar.framework/Bar --> Bar)
-                               clientName = outputFilePath;
+                               // infer client name from output path (e.g. xxx/libfoo_variant.A.dylib --> foo, Bar.framework/Bar_variant --> Bar)
+                               clientName = installName;
+                               clientNameLen = strlen(clientName);
                                // starts after last slash
-                               if ( outputFilePathLastSlash != NULL )
-                                       clientName = &outputFilePathLastSlash[1];
+                               if ( installNameLastSlash != NULL )
+                                       clientName = &installNameLastSlash[1];
                                if ( strncmp(clientName, "lib", 3) == 0 )
                                        clientName = &clientName[3];
                                // up to first dot
                                const char* firstDot = strchr(clientName, '.');
-                               if ( firstDot == NULL )
-                                       clientNameLen = strlen(clientName);
-                               else
+                               if ( firstDot != NULL )
                                        clientNameLen = firstDot - clientName;
+                               // up to first underscore
+                               const char* firstUnderscore = strchr(clientName, '_');
+                               if ( (firstUnderscore != NULL) && ((firstUnderscore - clientName) < clientNameLen) )
+                                       clientNameLen = firstUnderscore - clientName;
                        }
 
                        // Use clientName to check if this dylib is able to link against the allowable clients.
                        for (std::vector<const char*>::iterator it = clients->begin(); it != clients->end(); it++) {
                                if ( strncmp(*it, clientName, clientNameLen) == 0 )
-                                       okToLink = true;
+                                       isAllowableClient = true;
                        }
                }
-
-               // error out if we are not allowed to link
-               if ( ! okToLink )
-                       //throwf("'%s' is a subframework. Link against the umbrella framework '%s.framework' instead.",
-                       fprintf(stderr, "'%s' is a subframework. Link against the umbrella framework '%s.framework' instead.",
-                                       reader->getPath(), reader->parentUmbrella());
-       }
-
-       // update stats
-       ++fTotalDylibsLoaded;
-
-       return reader;
-}
-
-
-void Linker::addIndirectLibraries(ObjectFile::Reader* reader)
-{
-       std::vector<const char*>* dependentLibs = reader->getDependentLibraryPaths();
-       if ( dependentLibs != NULL ) {
-               for (std::vector<const char*>::iterator it=dependentLibs->begin(); it != dependentLibs->end(); it++) {
-                       if ( this->haveDirectLibrary(*it) ) {
-                               // do nothing, direct library already exists
-                       }
-                       else if ( this->haveIndirectLibrary(*it, reader) ) {
-                               // side effect of haveIndirectLibrary() added reader to parent list
+       
+               if ( !isParent && !isSibling && !isAllowableClient ) {
+                       if ( readerParentName != NULL ) {
+                               throwf("cannot link directly with %s.  Link against the umbrella framework '%s.framework' instead.", 
+                                       reader->getPath(), readerParentName);
                        }
                        else {
-                               // add to list of indirect libraries
-                               IndirectLibrary indirectLib;
-                               indirectLib.path = *it;
-                               indirectLib.fileLen = 0;
-                               indirectLib.reader = NULL;
-                               indirectLib.parents.insert(reader);
-                               indirectLib.reExportedViaDirectLibrary = NULL;
-                               fIndirectDynamicLibraries.push_back(indirectLib);
-                               //fprintf(stderr, "add indirect library: %s\n", *it);
+                               throwf("cannot link directly with %s", reader->getPath());
                        }
                }
        }
+
+
 }
 
-bool Linker::haveIndirectLibrary(const char* path, ObjectFile::Reader* parentReader)
+ObjectFile::Reader* Linker::addDylib(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
 {
-       for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
-               if ( strcmp(path, it->path) == 0 ) {
-                       it->parents.insert(parentReader);
-                       return true;
+       fNextInputOrdinal += mappedLen;
+       if ( (reader->getInstallPath() == NULL) && !info.options.fBundleLoader ) {
+               // this is a "blank" stub
+               // silently ignore it
+               return reader;
+       }
+       // add to map of loaded dylibs
+       const char* installPath = reader->getInstallPath();
+       if ( installPath != NULL ) {
+               InstallNameToReader::iterator pos = fDylibMap.find(installPath);
+               if ( pos == fDylibMap.end() ) {
+                       fDylibMap[strdup(installPath)] = reader;
                }
-               if ( it->reader != NULL ) {
-                       const char* installPath = it->reader->getInstallPath();
-                       if ( (installPath != NULL) && (strcmp(path, installPath) == 0) )
-                               return true;
+               else {
+                       InstallNameToReader::iterator pos2 = fDylibMap.find(reader->getPath());
+                       if ( pos2 == fDylibMap.end() ) 
+                               fDylibMap[strdup(reader->getPath())] = reader;
+                       else
+                               fprintf(stderr, "ld: warning, duplicate dylib %s\n", reader->getPath());
                }
        }
-       return false;
-}
+       else if ( info.options.fBundleLoader )
+               fBundleLoaderReader = reader;
 
-bool Linker::haveDirectLibrary(const char* path)
-{
-       for (std::vector<ExecutableFile::DyLibUsed>::iterator it=fDynamicLibraries.begin(); it != fDynamicLibraries.end(); it++) {
-               if ( strcmp(path, it->reader->getPath()) == 0 )
-                       return true;
-               const char* installPath = it->reader->getInstallPath();
-               if ( (installPath != NULL) && (strcmp(path, installPath) == 0) )
-                       return true;
-       }
-       return false;
+       // log direct readers
+       if ( !fAllDirectDylibsLoaded ) 
+               this->logDylib(reader, false);
+
+       // update stats
+       ++fTotalDylibsLoaded;
+
+       return reader;
 }
 
+
 void Linker::logTraceInfo (const char* format, ...)
 {
        static int trace_file = -1;
@@ -2338,19 +3119,71 @@ void Linker::logTraceInfo (const char* format, ...)
 void Linker::createWriter()
 {
        fStartCreateWriterTime = mach_absolute_time();
+
+       // make a vector out of all required dylibs in fDylibMap
+       std::vector<ExecutableFile::DyLibUsed>  dynamicLibraries;
+       // need to preserve command line order 
+       for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
+               ObjectFile::Reader* reader = *it;
+               for (InstallNameToReader::iterator mit=fDylibMap.begin(); mit != fDylibMap.end(); mit++) {
+                       if ( reader == mit->second ) {
+                               ExecutableFile::DyLibUsed dylibInfo;
+                               dylibInfo.reader = reader;
+                               dylibInfo.options = fDylibOptionsMap[reader];
+                               dynamicLibraries.push_back(dylibInfo);
+                               break;
+                       }
+               }
+       }
+       // then add any other dylibs
+       for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
+               if ( it->second->implicitlyLinked()  ) {
+                       // if not already in dynamicLibraries
+                       bool alreadyInDynamicLibraries = false;
+                       for (std::vector<ExecutableFile::DyLibUsed>::iterator dit=dynamicLibraries.begin(); dit != dynamicLibraries.end(); dit++) {
+                               if ( dit->reader == it->second ) {
+                                       alreadyInDynamicLibraries = true;
+                                       break;
+                               }
+                       }
+                       if ( ! alreadyInDynamicLibraries ) {    
+                               ExecutableFile::DyLibUsed dylibInfo;
+                               dylibInfo.reader = it->second;
+                               std::map<ObjectFile::Reader*,DynamicLibraryOptions>::iterator pos = fDylibOptionsMap.find(it->second);
+                               if ( pos != fDylibOptionsMap.end() ) {
+                                       dylibInfo.options = pos->second;
+                               }
+                               else {
+                                       dylibInfo.options.fWeakImport = false;          // FIX ME
+                                       dylibInfo.options.fReExport = false;
+                                       dylibInfo.options.fBundleLoader = false;
+                               }
+                               dynamicLibraries.push_back(dylibInfo);
+                       }
+               }
+       }
+       if ( fBundleLoaderReader != NULL ) {
+               ExecutableFile::DyLibUsed dylibInfo;
+               dylibInfo.reader = fBundleLoaderReader;
+               dylibInfo.options.fWeakImport = false;          
+               dylibInfo.options.fReExport = false;
+               dylibInfo.options.fBundleLoader = true;
+               dynamicLibraries.push_back(dylibInfo);
+       }
+
        const char* path = fOptions.getOutputFilePath();
        switch ( fArchitecture ) {
                case CPU_TYPE_POWERPC:
-                       this->setOutputFile(new mach_o::executable::Writer<ppc>(path, fOptions, fDynamicLibraries));
+                       this->setOutputFile(new mach_o::executable::Writer<ppc>(path, fOptions, dynamicLibraries));
                        break;
                case CPU_TYPE_POWERPC64:
-                       this->setOutputFile(new mach_o::executable::Writer<ppc64>(path, fOptions, fDynamicLibraries));
+                       this->setOutputFile(new mach_o::executable::Writer<ppc64>(path, fOptions, dynamicLibraries));
                        break;
                case CPU_TYPE_I386:
-                       this->setOutputFile(new mach_o::executable::Writer<x86>(path, fOptions, fDynamicLibraries));
+                       this->setOutputFile(new mach_o::executable::Writer<x86>(path, fOptions, dynamicLibraries));
                        break;
                case CPU_TYPE_X86_64:
-                       this->setOutputFile(new mach_o::executable::Writer<x86_64>(path, fOptions, fDynamicLibraries));
+                       this->setOutputFile(new mach_o::executable::Writer<x86_64>(path, fOptions, dynamicLibraries));
                        break;
                default:
                        throw "unknown architecture";
@@ -2374,32 +3207,43 @@ void Linker::SymbolTable::require(const char* name)
 }
 
 // convenience labels for 2-dimensional switch statement
-enum {
+enum AllDefinitionCombinations {
        kRegAndReg                              = (ObjectFile::Atom::kRegularDefinition << 3)   | ObjectFile::Atom::kRegularDefinition,
        kRegAndWeak                             = (ObjectFile::Atom::kRegularDefinition << 3)   | ObjectFile::Atom::kWeakDefinition,
        kRegAndTent                             = (ObjectFile::Atom::kRegularDefinition << 3)   | ObjectFile::Atom::kTentativeDefinition,
        kRegAndExtern                   = (ObjectFile::Atom::kRegularDefinition << 3)   | ObjectFile::Atom::kExternalDefinition,
        kRegAndExternWeak               = (ObjectFile::Atom::kRegularDefinition << 3)   | ObjectFile::Atom::kExternalWeakDefinition,
+       kRegAndAbsolute                 = (ObjectFile::Atom::kRegularDefinition << 3)   | ObjectFile::Atom::kAbsoluteSymbol,
        kWeakAndReg                             = (ObjectFile::Atom::kWeakDefinition << 3)              | ObjectFile::Atom::kRegularDefinition,
        kWeakAndWeak                    = (ObjectFile::Atom::kWeakDefinition << 3)              | ObjectFile::Atom::kWeakDefinition,
        kWeakAndTent                    = (ObjectFile::Atom::kWeakDefinition << 3)              | ObjectFile::Atom::kTentativeDefinition,
        kWeakAndExtern                  = (ObjectFile::Atom::kWeakDefinition << 3)              | ObjectFile::Atom::kExternalDefinition,
        kWeakAndExternWeak              = (ObjectFile::Atom::kWeakDefinition << 3)              | ObjectFile::Atom::kExternalWeakDefinition,
+       kWeakAndAbsolute                = (ObjectFile::Atom::kWeakDefinition << 3)              | ObjectFile::Atom::kAbsoluteSymbol,
        kTentAndReg                             = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
        kTentAndWeak                    = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
        kTentAndTent                    = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
        kTentAndExtern                  = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
        kTentAndExternWeak              = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
+       kTentAndAbsolute                = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
        kExternAndReg                   = (ObjectFile::Atom::kExternalDefinition << 3)  | ObjectFile::Atom::kRegularDefinition,
        kExternAndWeak                  = (ObjectFile::Atom::kExternalDefinition << 3)  | ObjectFile::Atom::kWeakDefinition,
        kExternAndTent                  = (ObjectFile::Atom::kExternalDefinition << 3)  | ObjectFile::Atom::kTentativeDefinition,
        kExternAndExtern                = (ObjectFile::Atom::kExternalDefinition << 3)  | ObjectFile::Atom::kExternalDefinition,
        kExternAndExternWeak    = (ObjectFile::Atom::kExternalDefinition << 3)  | ObjectFile::Atom::kExternalWeakDefinition,
+       kExternAndAbsolute              = (ObjectFile::Atom::kExternalDefinition << 3)  | ObjectFile::Atom::kAbsoluteSymbol,
        kExternWeakAndReg               = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
        kExternWeakAndWeak              = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
        kExternWeakAndTent              = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
        kExternWeakAndExtern    = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
-       kExternWeakAndExternWeak= (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition
+       kExternWeakAndExternWeak= (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
+       kExternWeakAndAbsolute  = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
+       kAbsoluteAndReg                 = (ObjectFile::Atom::kAbsoluteSymbol << 3)              | ObjectFile::Atom::kRegularDefinition,
+       kAbsoluteAndWeak                = (ObjectFile::Atom::kAbsoluteSymbol << 3)              | ObjectFile::Atom::kWeakDefinition,
+       kAbsoluteAndTent                = (ObjectFile::Atom::kAbsoluteSymbol << 3)              | ObjectFile::Atom::kTentativeDefinition,
+       kAbsoluteAndExtern              = (ObjectFile::Atom::kAbsoluteSymbol << 3)              | ObjectFile::Atom::kExternalDefinition,
+       kAbsoluteAndExternWeak  = (ObjectFile::Atom::kAbsoluteSymbol << 3)              | ObjectFile::Atom::kExternalWeakDefinition,
+       kAbsoluteAndAbsolute    = (ObjectFile::Atom::kAbsoluteSymbol << 3)              | ObjectFile::Atom::kAbsoluteSymbol
 };
 
 bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
@@ -2413,7 +3257,7 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                existingAtom = pos->second;
        if ( existingAtom != NULL ) {
                // already have atom with same name in symbol table
-               switch ( (existingAtom->getDefinitionKind() << 3) | newAtom.getDefinitionKind() ) {
+               switch ( (AllDefinitionCombinations)((existingAtom->getDefinitionKind() << 3) | newAtom.getDefinitionKind()) ) {
                        case kRegAndReg:
                                throwf("duplicate symbol %s in %s and %s\n", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
                        case kRegAndWeak:
@@ -2423,6 +3267,12 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                        case kRegAndTent:
                                // ignore new tentative atom, because we already have a regular one
                                useNew = false;
+                               if ( newAtom.getSize() > existingAtom->getSize() ) {
+                                       fprintf(stderr, "ld: warning for symbol %s tentative definition of size %llu from %s is "
+                                                                       "is smaller than the real definition of size %llu from %s\n",
+                                                                       newAtom.getDisplayName(), newAtom.getSize(), newAtom.getFile()->getPath(),
+                                                                       existingAtom->getSize(), existingAtom->getFile()->getPath());
+                               }
                                break;
                        case kRegAndExtern:
                                // ignore external atom, because we already have a one
@@ -2432,13 +3282,16 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                // ignore external atom, because we already have a one
                                useNew = false;
                                break;
+                       case kRegAndAbsolute:
+                               throwf("duplicate symbol %s in %s and %s\n", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
+                               break;
                        case kWeakAndReg:
                                // replace existing weak atom with regular one
                                break;
                        case kWeakAndWeak:
                                // have another weak atom, use whichever has largest alignment requirement
                                // because codegen of some client may require alignment
-                               useNew = ( newAtom.getAlignment().leadingZeros() > existingAtom->getAlignment().leadingZeros() );
+                               useNew = ( newAtom.getAlignment().trailingZeros() > existingAtom->getAlignment().trailingZeros() );
                                break;
                        case kWeakAndTent:
                                // replace existing weak atom with tentative one ???
@@ -2451,8 +3304,17 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                // keep weak atom, at runtime external one may override
                                useNew = false;
                                break;
+                       case kWeakAndAbsolute:
+                               // replace existing weak atom with absolute one
+                               break;
                        case kTentAndReg:
                                // replace existing tentative atom with regular one
+                               if ( newAtom.getSize() < existingAtom->getSize() ) {
+                                       fprintf(stderr, "ld: warning for symbol %s tentative definition of size %llu from %s is "
+                                                                       "being replaced by a real definition of size %llu from %s\n",
+                                                                       newAtom.getDisplayName(), existingAtom->getSize(), existingAtom->getFile()->getPath(),
+                                                                       newAtom.getSize(), newAtom.getFile()->getPath());
+                               }
                                break;
                        case kTentAndWeak:
                                // replace existing tentative atom with weak one ???
@@ -2461,9 +3323,10 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                // use largest
                                if ( newAtom.getSize() < existingAtom->getSize() ) {
                                        useNew = false;
-                               } else {
-                                       if ( newAtom.getAlignment().leadingZeros() < existingAtom->getAlignment().leadingZeros() )
-                                               fprintf(stderr, "ld64 warning: alignment lost in merging tentative definition %s\n", newAtom.getDisplayName());
+                               } 
+                               else {
+                                       if ( newAtom.getAlignment().trailingZeros() < existingAtom->getAlignment().trailingZeros() )
+                                               fprintf(stderr, "ld: warning alignment lost in merging tentative definition %s\n", newAtom.getDisplayName());
                                }
                                break;
                        case kTentAndExtern:
@@ -2472,13 +3335,13 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                switch ( fOwner.fOptions.commonsMode() ) {
                                        case Options::kCommonsIgnoreDylibs:
                                                if ( fOwner.fOptions.warnCommons() )
-                                                       fprintf(stderr, "ld64: using common symbol %s from %s and ignoring defintion from dylib %s\n",
+                                                       fprintf(stderr, "ld: using common symbol %s from %s and ignoring defintion from dylib %s\n",
                                                                        existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
                                                useNew = false;
                                                break;
                                        case Options::kCommonsOverriddenByDylibs:
                                                if ( fOwner.fOptions.warnCommons() )
-                                                       fprintf(stderr, "ld64: replacing common symbol %s from %s with true definition from dylib %s\n",
+                                                       fprintf(stderr, "ld: replacing common symbol %s from %s with true definition from dylib %s\n",
                                                                        existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
                                                break;
                                        case Options::kCommonsConflictsDylibsError:
@@ -2486,6 +3349,9 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                                                existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
                                }
                                break;
+                       case kTentAndAbsolute:
+                               // replace tentative with absolute (can't size check because absolutes have no size)
+                               break;
                        case kExternAndReg:
                                // replace external atom with regular one
                                break;
@@ -2497,12 +3363,12 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                switch ( fOwner.fOptions.commonsMode() ) {
                                        case Options::kCommonsIgnoreDylibs:
                                                if ( fOwner.fOptions.warnCommons() )
-                                                       fprintf(stderr, "ld64: using common symbol %s from %s and ignoring defintion from dylib %s\n",
+                                                       fprintf(stderr, "ld: using common symbol %s from %s and ignoring defintion from dylib %s\n",
                                                                        newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
                                                break;
                                        case Options::kCommonsOverriddenByDylibs:
                                                if ( fOwner.fOptions.warnCommons() )
-                                                       fprintf(stderr, "ld64: replacing defintion of %s from dylib %s with common symbol from %s\n",
+                                                       fprintf(stderr, "ld: replacing defintion of %s from dylib %s with common symbol from %s\n",
                                                                        newAtom.getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
                                                useNew = false;
                                                break;
@@ -2517,6 +3383,9 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                // keep strong dylib atom, ignore weak one
                                useNew = false;
                                break;
+                       case kExternAndAbsolute:
+                               // replace external atom with absolute one
+                               break;
                        case kExternWeakAndReg:
                                // replace existing weak external with regular
                                break;
@@ -2528,12 +3397,12 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                switch ( fOwner.fOptions.commonsMode() ) {
                                        case Options::kCommonsIgnoreDylibs:
                                                if ( fOwner.fOptions.warnCommons() )
-                                                       fprintf(stderr, "ld64: using common symbol %s from %s and ignoring defintion from dylib %s\n",
+                                                       fprintf(stderr, "ld: using common symbol %s from %s and ignoring defintion from dylib %s\n",
                                                                        newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
                                                break;
                                        case Options::kCommonsOverriddenByDylibs:
                                                if ( fOwner.fOptions.warnCommons() )
-                                                       fprintf(stderr, "ld64: replacing defintion of %s from dylib %s with common symbol from %s\n",
+                                                       fprintf(stderr, "ld: replacing defintion of %s from dylib %s with common symbol from %s\n",
                                                                        newAtom.getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
                                                useNew = false;
                                                break;
@@ -2549,8 +3418,36 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                // keep existing external weak
                                useNew = false;
                                break;
+                       case kExternWeakAndAbsolute:
+                               // replace existing weak external with absolute
+                               break;
+                       case kAbsoluteAndReg:
+                               throwf("duplicate symbol %s in %s and %s\n", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
+                       case kAbsoluteAndWeak:
+                               // ignore new weak atom, because we already have a non-weak one
+                               useNew = false;
+                               break;
+                       case kAbsoluteAndTent:
+                               // ignore new tentative atom, because we already have a regular one
+                               useNew = false;
+                               break;
+                       case kAbsoluteAndExtern:
+                               // ignore external atom, because we already have a one
+                               useNew = false;
+                               break;
+                       case kAbsoluteAndExternWeak:
+                               // ignore external atom, because we already have a one
+                               useNew = false;
+                               break;
+                       case kAbsoluteAndAbsolute:
+                               throwf("duplicate symbol %s in %s and %s\n", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
+                               break;
                }
        }
+       if ( (existingAtom != NULL) && (newAtom.getScope() != existingAtom->getScope()) ) {
+               fprintf(stderr, "ld: warning %s has different visibility (%d) in %s and (%d) in %s\n", 
+                       newAtom.getDisplayName(), newAtom.getScope(), newAtom.getFile()->getPath(), existingAtom->getScope(), existingAtom->getFile()->getPath());
+       }
        if ( useNew ) {
                fTable[name] = &newAtom;
                if ( existingAtom != NULL )
@@ -2586,22 +3483,53 @@ void Linker::SymbolTable::getNeededNames(bool andWeakDefintions, std::vector<con
 
 
 
-bool Linker::AtomSorter::operator()(ObjectFile::Atom* left, ObjectFile::Atom* right)
+bool Linker::AtomSorter::operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right)
 {
+       if ( left == right )
+               return false;
+
        // first sort by section order (which is already sorted by segment)
        unsigned int leftSectionIndex  =  left->getSection()->getIndex();
        unsigned int rightSectionIndex = right->getSection()->getIndex();
        if ( leftSectionIndex != rightSectionIndex)
                return (leftSectionIndex < rightSectionIndex);
 
-       // then sort by .o file order
-       ObjectFile::Reader* leftReader = left->getFile();
-       ObjectFile::Reader* rightReader = right->getFile();
-       if ( leftReader !=  rightReader )
-               return leftReader->getSortOrder() < rightReader->getSortOrder();
-
-       // lastly sort by atom within a .o file
-       return left->getSortOrder() < right->getSortOrder();
+       // if a -order_file is specified, then sorting is altered to sort those symbols first
+       if ( fOverriddenOrdinalMap != NULL ) {
+               std::map<const ObjectFile::Atom*, uint32_t>::iterator leftPos  = fOverriddenOrdinalMap->find(left);
+               std::map<const ObjectFile::Atom*, uint32_t>::iterator rightPos = fOverriddenOrdinalMap->find(right);
+               std::map<const ObjectFile::Atom*, uint32_t>::iterator end = fOverriddenOrdinalMap->end();
+               if ( leftPos != end ) {
+                       if ( rightPos != end ) {
+                               // both left and right are overridden, so compare overridden ordinals
+                               return leftPos->second < rightPos->second;
+                       }
+                       else {
+                               // left is overridden and right is not, so left < right
+                               return true;
+                       }
+               }
+               else {
+                       if ( rightPos != end ) {
+                               // right is overridden and left is not, so right < left
+                               return false;
+                       }
+                       else {
+                               // neither are overridden, do default sort
+                               // fall into default sorting below
+                       }
+               }
+       }
+       
+       // the __common section can have real or tentative definitions
+       // we want the real ones to sort before tentative ones
+       bool leftIsTent  =  (left->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition);
+       bool rightIsTent =  (right->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition);
+       if ( leftIsTent != rightIsTent )
+               return rightIsTent; 
+       
+       // lastly sort by atom ordinal.  this is already sorted by .o order
+       return left->getOrdinal() < right->getOrdinal();
 }
 
 
@@ -2629,13 +3557,12 @@ int main(int argc, const char* argv[])
                ld.link();
        }
        catch (const char* msg) {
-               extern const double ld64VersionNumber;
                if ( archInferred )
-                       fprintf(stderr, "ld64-%g failed: %s for inferred architecture %s\n", ld64VersionNumber, msg, archName);
+                       fprintf(stderr, "ld: %s for inferred architecture %s\n", msg, archName);
                else if ( showArch )
-                       fprintf(stderr, "ld64-%g failed: %s for architecture %s\n", ld64VersionNumber, msg, archName);
+                       fprintf(stderr, "ld: %s for architecture %s\n", msg, archName);
                else
-                       fprintf(stderr, "ld64-%g failed: %s\n", ld64VersionNumber, msg);
+                       fprintf(stderr, "ld: %s\n", msg);
                return 1;
        }
 
index 1d7aec59e42d130626b2b3b62ed8af1d8c0cb099..7f0e134b0649a02748ec7f78d7342ff728d357c8 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
  *
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2006-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -37,6 +37,8 @@
 #include <mach-o/x86_64/reloc.h>
 
 #include <vector>
+#include <set>
+#include <ext/hash_set>
 
 #include "MachOFileAbstraction.hpp"
 #include "Architectures.hpp"
@@ -71,11 +73,20 @@ private:
        typedef typename A::P::E                                E;
        typedef typename A::P::uint_t                   pint_t;
        
+       class CStringEquals
+       {
+       public:
+               bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
+       };
+
+       typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals>  StringSet;
+
                                                                                                MachOChecker(const uint8_t* fileContent, uint32_t fileLength, const char* path);
        void                                                                            checkMachHeader();
        void                                                                            checkLoadCommands();
        void                                                                            checkSection(const macho_segment_command<P>* segCmd, const macho_section<P>* sect);
        uint8_t                                                                         loadCommandSizeMask();
+       void                                                                            checkSymbolTable();
        void                                                                            checkIndirectSymbolTable();
        void                                                                            checkRelocations();
        void                                                                            checkExternalReloation(const macho_relocation_info<P>* reloc);
@@ -90,13 +101,13 @@ private:
        const char*                                                                     fStringsEnd;
        const macho_nlist<P>*                                           fSymbols;
        uint32_t                                                                        fSymbolCount;
+       const macho_dysymtab_command<P>*                        fDynamicSymbolTable;
        const uint32_t*                                                         fIndirectTable;
        uint32_t                                                                        fIndirectTableCount;
        const macho_relocation_info<P>*                         fLocalRelocations;
        uint32_t                                                                        fLocalRelocationsCount;
        const macho_relocation_info<P>*                         fExternalRelocations;
        uint32_t                                                                        fExternalRelocationsCount;
-       pint_t                                                                          fRelocBase;
        bool                                                                            fWriteableSegmentWithAddrOver4G;
        const macho_segment_command<P>*                         fFirstSegment;
        const macho_segment_command<P>*                         fFirstWritableSegment;
@@ -185,9 +196,9 @@ template <> uint8_t MachOChecker<x86_64>::loadCommandSizeMask() { return 0x07; }
 
 template <typename A>
 MachOChecker<A>::MachOChecker(const uint8_t* fileContent, uint32_t fileLength, const char* path)
- : fHeader(NULL), fLength(fileLength), fStrings(NULL), fSymbols(NULL), fSymbolCount(0), fIndirectTableCount(0),
+ : fHeader(NULL), fLength(fileLength), fStrings(NULL), fSymbols(NULL), fSymbolCount(0), fDynamicSymbolTable(NULL), fIndirectTableCount(0),
  fLocalRelocations(NULL),  fLocalRelocationsCount(0),  fExternalRelocations(NULL),  fExternalRelocationsCount(0),
- fRelocBase(0), fWriteableSegmentWithAddrOver4G(false), fFirstSegment(NULL), fFirstWritableSegment(NULL)
+ fWriteableSegmentWithAddrOver4G(false), fFirstSegment(NULL), fFirstWritableSegment(NULL)
 {
        // sanity check
        if ( ! validFile(fileContent) )
@@ -205,6 +216,8 @@ MachOChecker<A>::MachOChecker(const uint8_t* fileContent, uint32_t fileLength, c
        checkIndirectSymbolTable();
 
        checkRelocations();
+       
+       checkSymbolTable();
 }
 
 
@@ -215,10 +228,11 @@ void MachOChecker<A>::checkMachHeader()
                throw "sizeofcmds in mach_header is larger than file";
        
        uint32_t flags = fHeader->flags();
-       uint32_t invalidBits = MH_INCRLINK | MH_LAZY_INIT | 0xFFFC0000;
+       const uint32_t invalidBits = MH_INCRLINK | MH_LAZY_INIT | 0xFFE00000;
        if ( flags & invalidBits )
                throw "invalid bits in mach_header flags";
-               
+       if ( (flags & MH_NO_REEXPORTED_DYLIBS) && (fHeader->filetype() != MH_DYLIB) ) 
+               throw "MH_NO_REEXPORTED_DYLIBS bit of mach_header flags only valid for dylibs";
 }
 
 template <typename A>
@@ -250,12 +264,18 @@ void MachOChecker<A>::checkLoadCommands()
                        case LC_ID_DYLINKER:
                        case macho_routines_command<P>::CMD:
                        case LC_SUB_FRAMEWORK:
-                       case LC_SUB_UMBRELLA:
                        case LC_SUB_CLIENT:
                        case LC_TWOLEVEL_HINTS:
                        case LC_PREBIND_CKSUM:
                        case LC_LOAD_WEAK_DYLIB:
                        case LC_UUID:
+                       case LC_REEXPORT_DYLIB:
+                       case LC_SEGMENT_SPLIT_INFO:
+                               break;
+                       case LC_SUB_UMBRELLA:
+                       case LC_SUB_LIBRARY:
+                               if ( fHeader->flags() & MH_NO_REEXPORTED_DYLIBS )
+                                       throw "MH_NO_REEXPORTED_DYLIBS bit of mach_header flags should not be set in an image with LC_SUB_LIBRARY or LC_SUB_UMBRELLA";
                                break;
                        default:
                                throwf("load command #%d is an unknown kind 0x%X", i, cmd->cmd());
@@ -324,9 +344,13 @@ void MachOChecker<A>::checkLoadCommands()
                        // cache interesting segments
                        if ( fFirstSegment == NULL )
                                fFirstSegment = segCmd;
-                       if ( (fFirstWritableSegment == NULL) && ((segCmd->initprot() & VM_PROT_WRITE) != 0) )
-                               fFirstWritableSegment = segCmd;
-                               
+                       if ( (segCmd->initprot() & VM_PROT_WRITE) != 0 ) {
+                               if ( fFirstWritableSegment == NULL )
+                                       fFirstWritableSegment = segCmd;
+                               if ( segCmd->vmaddr() > 0x100000000ULL )
+                                       fWriteableSegmentWithAddrOver4G = true;
+                       }
+       
                        // check section ranges
                        const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)segCmd + sizeof(macho_segment_command<P>));
                        const macho_section<P>* const sectionsEnd = &sectionsStart[segCmd->nsects()];
@@ -372,7 +396,7 @@ void MachOChecker<A>::checkLoadCommands()
                }
        }
 
-       // check LC_SYMTAB and LC_DYSYMTAB
+       // check LC_SYMTAB, LC_DYSYMTAB, and LC_SEGMENT_SPLIT_INFO
        cmd = cmds;
        bool foundDynamicSymTab = false;
        for (uint32_t i = 0; i < cmd_count; ++i) {
@@ -386,12 +410,18 @@ void MachOChecker<A>::checkLoadCommands()
                                                throw "symbol table not in __LINKEDIT";
                                        if ( (symtab->symoff() + fSymbolCount*sizeof(macho_nlist<P>*)) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
                                                throw "symbol table end not in __LINKEDIT";
+                                       if ( (symtab->symoff() % sizeof(pint_t)) != 0 )
+                                               throw "symbol table start not pointer aligned";
                                        fStrings = (char*)fHeader + symtab->stroff();
                                        fStringsEnd = fStrings + symtab->strsize();
                                        if ( symtab->stroff() < linkEditSegment->fileoff() )
                                                throw "string pool not in __LINKEDIT";
                                        if ( (symtab->stroff()+symtab->strsize()) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
                                                throw "string pool extends beyond __LINKEDIT";
+                                       if ( (symtab->stroff() % 4) != 0 ) // work around until rdar://problem/4737991 is fixed
+                                               throw "string pool start not pointer aligned";
+                                       if ( (symtab->strsize() % sizeof(pint_t)) != 0 )        
+                                               throw "string pool size not a multiple of pointer size";
                                }
                                break;
                        case LC_DYSYMTAB:
@@ -399,33 +429,54 @@ void MachOChecker<A>::checkLoadCommands()
                                        if ( isStaticExecutable )
                                                throw "LC_DYSYMTAB should not be used in static executable";
                                        foundDynamicSymTab = true;
-                                       const macho_dysymtab_command<P>* dsymtab = (struct macho_dysymtab_command<P>*)cmd;
-                                       fIndirectTable = (uint32_t*)((char*)fHeader + dsymtab->indirectsymoff());
-                                       fIndirectTableCount = dsymtab->nindirectsyms();
+                                       fDynamicSymbolTable = (struct macho_dysymtab_command<P>*)cmd;
+                                       fIndirectTable = (uint32_t*)((char*)fHeader + fDynamicSymbolTable->indirectsymoff());
+                                       fIndirectTableCount = fDynamicSymbolTable->nindirectsyms();
                                        if ( fIndirectTableCount != 0  ) {
-                                               if ( dsymtab->indirectsymoff() < linkEditSegment->fileoff() )
+                                               if ( fDynamicSymbolTable->indirectsymoff() < linkEditSegment->fileoff() )
                                                        throw "indirect symbol table not in __LINKEDIT";
-                                               if ( (dsymtab->indirectsymoff()+fIndirectTableCount*8) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
+                                               if ( (fDynamicSymbolTable->indirectsymoff()+fIndirectTableCount*8) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
                                                        throw "indirect symbol table not in __LINKEDIT";
+                                               if ( (fDynamicSymbolTable->indirectsymoff() % sizeof(pint_t)) != 0 )
+                                                       throw "indirect symbol table not pointer aligned";
                                        }
-                                       fLocalRelocationsCount = dsymtab->nlocrel();
+                                       fLocalRelocationsCount = fDynamicSymbolTable->nlocrel();
                                        if ( fLocalRelocationsCount != 0 ) {
-                                               fLocalRelocations = (const macho_relocation_info<P>*)((char*)fHeader + dsymtab->locreloff());
-                                               if ( dsymtab->locreloff() < linkEditSegment->fileoff() )
+                                               fLocalRelocations = (const macho_relocation_info<P>*)((char*)fHeader + fDynamicSymbolTable->locreloff());
+                                               if ( fDynamicSymbolTable->locreloff() < linkEditSegment->fileoff() )
                                                        throw "local relocations not in __LINKEDIT";
-                                               if ( (dsymtab->locreloff()+fLocalRelocationsCount*sizeof(macho_relocation_info<P>)) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
+                                               if ( (fDynamicSymbolTable->locreloff()+fLocalRelocationsCount*sizeof(macho_relocation_info<P>)) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
                                                        throw "local relocations not in __LINKEDIT";
+                                               if ( (fDynamicSymbolTable->locreloff() % sizeof(pint_t)) != 0 )
+                                                       throw "local relocations table not pointer aligned";
                                        }
-                                       fExternalRelocationsCount = dsymtab->nextrel();
+                                       fExternalRelocationsCount = fDynamicSymbolTable->nextrel();
                                        if ( fExternalRelocationsCount != 0 ) {
-                                               fExternalRelocations = (const macho_relocation_info<P>*)((char*)fHeader + dsymtab->extreloff());
-                                               if ( dsymtab->extreloff() < linkEditSegment->fileoff() )
-                                                       throw "local relocations not in __LINKEDIT";
-                                               if ( (dsymtab->extreloff()+fExternalRelocationsCount*sizeof(macho_relocation_info<P>)) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
-                                                       throw "local relocations not in __LINKEDIT";
+                                               fExternalRelocations = (const macho_relocation_info<P>*)((char*)fHeader + fDynamicSymbolTable->extreloff());
+                                               if ( fDynamicSymbolTable->extreloff() < linkEditSegment->fileoff() )
+                                                       throw "external relocations not in __LINKEDIT";
+                                               if ( (fDynamicSymbolTable->extreloff()+fExternalRelocationsCount*sizeof(macho_relocation_info<P>)) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
+                                                       throw "external relocations not in __LINKEDIT";
+                                               if ( (fDynamicSymbolTable->extreloff() % sizeof(pint_t)) != 0 )
+                                                       throw "external relocations table not pointer aligned";
                                        }
                                }
                                break;
+                       case LC_SEGMENT_SPLIT_INFO:
+                               {
+                                       if ( isStaticExecutable )
+                                               throw "LC_SEGMENT_SPLIT_INFO should not be used in static executable";
+                                       const macho_linkedit_data_command<P>* info = (struct macho_linkedit_data_command<P>*)cmd;
+                                       if ( info->dataoff() < linkEditSegment->fileoff() )
+                                               throw "split seg info not in __LINKEDIT";
+                                       if ( (info->dataoff()+info->datasize()) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) )
+                                               throw "split seg info not in __LINKEDIT";
+                                       if ( (info->dataoff() % sizeof(pint_t)) != 0 )
+                                               throw "split seg info table not pointer aligned";
+                                       if ( (info->datasize() % sizeof(pint_t)) != 0 )
+                                               throw "split seg info size not a multiple of pointer size";
+                               }
+                               break;
                }
                cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
        }
@@ -433,9 +484,7 @@ void MachOChecker<A>::checkLoadCommands()
                throw "missing dynamic symbol table";
        if ( fStrings == NULL )
                throw "missing symbol table";
-       
-       fRelocBase = this->relocBase();
-       
+               
 }
 
 template <typename A>
@@ -490,6 +539,23 @@ void MachOChecker<A>::checkIndirectSymbolTable()
 }
 
 
+template <typename A>
+void MachOChecker<A>::checkSymbolTable()
+{
+       // verify no duplicate external symbol names
+       if ( fDynamicSymbolTable != NULL ) {
+               StringSet externalNames;
+               const macho_nlist<P>* const     exportedStart = &fSymbols[fDynamicSymbolTable->iextdefsym()];
+               const macho_nlist<P>* const exportedEnd = &exportedStart[fDynamicSymbolTable->nextdefsym()];
+               for(const macho_nlist<P>* p = exportedStart; p < exportedEnd; ++p) {
+                       const char* symName = &fStrings[p->n_strx()];
+                       if ( externalNames.find(symName) != externalNames.end() )
+                               throwf("duplicate external symbol: %s", symName);
+                       externalNames.insert(symName);
+               }
+       }
+}
+
 
 template <>
 ppc::P::uint_t MachOChecker<ppc>::relocBase()
@@ -549,7 +615,17 @@ bool MachOChecker<A>::addressInWritableSegment(pint_t address)
 template <>
 void MachOChecker<ppc>::checkExternalReloation(const macho_relocation_info<P>* reloc)
 {
-       // FIX
+       if ( reloc->r_length() != 2 ) 
+               throw "bad external relocation length";
+       if ( reloc->r_type() != GENERIC_RELOC_VANILLA ) 
+               throw "unknown external relocation type";
+       if ( reloc->r_pcrel() != 0 ) 
+               throw "bad external relocation pc_rel";
+       if ( reloc->r_extern() == 0 )
+               throw "local relocation found with external relocations";
+       if ( ! this->addressInWritableSegment(reloc->r_address() + this->relocBase()) )
+               throw "external relocation address not in writable segment";
+       // FIX: check r_symbol
 }
 
 template <>
@@ -564,14 +640,24 @@ void MachOChecker<ppc64>::checkExternalReloation(const macho_relocation_info<P>*
        if ( reloc->r_extern() == 0 )
                throw "local relocation found with external relocations";
        if ( ! this->addressInWritableSegment(reloc->r_address() + this->relocBase()) )
-               throw "local relocation address not in writable segment";
+               throw "external relocation address not in writable segment";
        // FIX: check r_symbol
 }
 
 template <>
 void MachOChecker<x86>::checkExternalReloation(const macho_relocation_info<P>* reloc)
 {
-       // FIX
+       if ( reloc->r_length() != 2 ) 
+               throw "bad external relocation length";
+       if ( reloc->r_type() != GENERIC_RELOC_VANILLA ) 
+               throw "unknown external relocation type";
+       if ( reloc->r_pcrel() != 0 ) 
+               throw "bad external relocation pc_rel";
+       if ( reloc->r_extern() == 0 )
+               throw "local relocation found with external relocations";
+       if ( ! this->addressInWritableSegment(reloc->r_address() + this->relocBase()) )
+               throw "external relocation address not in writable segment";
+       // FIX: check r_symbol
 }
 
 
@@ -649,9 +735,19 @@ void MachOChecker<x86_64>::checkLocalReloation(const macho_relocation_info<P>* r
 template <typename A>
 void MachOChecker<A>::checkRelocations()
 {
+       // external relocations should be sorted to minimize dyld symbol lookups
+       // therefore every reloc with the same r_symbolnum value should be contiguous 
+       std::set<uint32_t> previouslySeenSymbolIndexes;
+       uint32_t lastSymbolIndex = 0xFFFFFFFF;
        const macho_relocation_info<P>* const externRelocsEnd = &fExternalRelocations[fExternalRelocationsCount];
        for (const macho_relocation_info<P>* reloc = fExternalRelocations; reloc < externRelocsEnd; ++reloc) {
                this->checkExternalReloation(reloc);
+               if ( reloc->r_symbolnum() != lastSymbolIndex ) {
+                       if ( previouslySeenSymbolIndexes.count(reloc->r_symbolnum()) != 0 )
+                               throw "external relocations not sorted";
+                       previouslySeenSymbolIndexes.insert(lastSymbolIndex);
+                       lastSymbolIndex = reloc->r_symbolnum();
+               }
        }
        
        const macho_relocation_info<P>* const localRelocsEnd = &fLocalRelocations[fLocalRelocationsCount];
@@ -679,33 +775,38 @@ static void check(const char* path)
                if ( mh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
                        const struct fat_header* fh = (struct fat_header*)p;
                        const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
-                       for (unsigned long i=0; i < fh->nfat_arch; ++i) {
-                               if ( archs[i].cputype == CPU_TYPE_POWERPC ) {
-                                       if ( MachOChecker<ppc>::validFile(p + archs[i].offset) )
-                                               MachOChecker<ppc>::make(p + archs[i].offset, archs[i].size, path);
+                       for (unsigned long i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
+                               size_t offset = OSSwapBigToHostInt32(archs[i].offset);
+                               size_t size = OSSwapBigToHostInt32(archs[i].size);
+                               unsigned int cputype = OSSwapBigToHostInt32(archs[i].cputype);
+
+                               switch(cputype) {
+                               case CPU_TYPE_POWERPC:
+                                       if ( MachOChecker<ppc>::validFile(p + offset) )
+                                               MachOChecker<ppc>::make(p + offset, size, path);
                                        else
                                                throw "in universal file, ppc slice does not contain ppc mach-o";
-                               }
-                               else if ( archs[i].cputype == CPU_TYPE_I386 ) {
-                                       if ( MachOChecker<x86>::validFile(p + archs[i].offset) )
-                                               MachOChecker<x86>::make(p + archs[i].offset, archs[i].size, path);
+                                       break;
+                               case CPU_TYPE_I386:
+                                       if ( MachOChecker<x86>::validFile(p + offset) )
+                                               MachOChecker<x86>::make(p + offset, size, path);
                                        else
                                                throw "in universal file, i386 slice does not contain i386 mach-o";
-                               }
-                               else if ( archs[i].cputype == CPU_TYPE_POWERPC64 ) {
-                                       if ( MachOChecker<ppc64>::validFile(p + archs[i].offset) )
-                                               MachOChecker<ppc64>::make(p + archs[i].offset, archs[i].size, path);
+                                       break;
+                               case CPU_TYPE_POWERPC64:
+                                       if ( MachOChecker<ppc64>::validFile(p + offset) )
+                                               MachOChecker<ppc64>::make(p + offset, size, path);
                                        else
                                                throw "in universal file, ppc64 slice does not contain ppc64 mach-o";
-                               }
-                               else if ( archs[i].cputype == CPU_TYPE_X86_64 ) {
-                                       if ( MachOChecker<x86_64>::validFile(p + archs[i].offset) )
-                                               MachOChecker<x86_64>::make(p + archs[i].offset, archs[i].size, path);
+                                       break;
+                               case CPU_TYPE_X86_64:
+                                       if ( MachOChecker<x86_64>::validFile(p + offset) )
+                                               MachOChecker<x86_64>::make(p + offset, size, path);
                                        else
                                                throw "in universal file, x86_64 slice does not contain x86_64 mach-o";
-                               }
-                               else {
-                                               throw "in universal file, unknown architecture slice";
+                                       break;
+                               default:
+                                               throwf("in universal file, unknown architecture slice 0x%x\n", cputype);
                                }
                        }
                }
index dd4c3e5b7cbf06b8b2e03a5605d1533c1b87b7d7..fcc65eb9b54c1e676188686d0b6c48cd62de4d6f 100755 (executable)
@@ -9,8 +9,13 @@
 use strict;
 
 my $string = shift @ARGV;
+my $ret = system(@ARGV);
+my $exit_value  = $ret >> 8;
+my $signal_num  = $ret & 127;
+my $dumped_core = $ret & 128;
+my $crashed  = $signal_num + $dumped_core;
 
-if(0 == system(@ARGV))
+if(0 == $exit_value || 0 != $crashed)
 {
     printf("FAIL $string\n");
 }
@@ -18,5 +23,5 @@ else
 {
     printf("PASS $string\n");
 }
-exit 0;
 
+exit 0;
index 24ca8956a491094a03ae6df5571d19b3dce4f98b..7fb54b25a4bcde5f18e2e1b74e68e7750afc0ae0 100755 (executable)
@@ -10,12 +10,7 @@ if ( exists $ENV{UNIT_TEST_NAME} ) {
 if(system(@ARGV) != 0)
 {
     printf("FAIL $test_name\n");
-       exit 1;
+    exit 1;
 }
-else 
-{
-       exit 0;
-}
-
-
 
+exit 0;
index f1610c99598581488b97d590bfcfca34a8c311f0..7859888f88dd3dba4b853b0f591bf634d2ec4b4e 100755 (executable)
@@ -7,12 +7,16 @@ if ( exists $ENV{UNIT_TEST_NAME} ) {
     $test_name = $ENV{UNIT_TEST_NAME};
 }
 
-if(system(@ARGV) == 0)
+my $ret = system(@ARGV);
+my $exit_value  = $ret >> 8;
+my $signal_num  = $ret & 127;
+my $dumped_core = $ret & 128;
+my $crashed  = $signal_num + $dumped_core;
+
+if(0 == $exit_value || 0 != $crashed)
 {
     printf("FAIL $test_name\n");
     exit 1;
 }
-else
-{
-    exit 0;
-}
+
+exit 0;
index 0c8ae66cd9984bd1478fab9de148353c0df9ac07..a44f5d3e52cc9179dcdb2f263a15f02c59bcddc2 100755 (executable)
@@ -16,5 +16,7 @@ if ( exists $ENV{UNIT_TEST_NAME} ) {
 if( eof STDIN )
 {
     printf("FAIL $test_name\n");
+    exit 1;
 }
+
 exit 0;
index f5e2fdfa221a696a33a2ac856e2e5ee156780d78..c0bf2903f808d40640bc36e5269e0583c1d9935a 100755 (executable)
@@ -15,10 +15,8 @@ if ( exists $ENV{UNIT_TEST_NAME} ) {
 
 if( eof STDIN )
 {
-
-}
-else
-{
-    printf("FAIL $test_name\n");
+    exit 0;
 }
-exit 0;
+
+printf("FAIL $test_name\n");
+exit 1;
index f62b7975292533ffb35b8822abe101a2d48618f7..6d49a25a3968257b4f09f1859fa4e8c6efac843e 100755 (executable)
@@ -13,13 +13,17 @@ if ( exists $ENV{UNIT_TEST_NAME} ) {
        $test_name = $ENV{UNIT_TEST_NAME};
 }
 
-if(0 == system(@ARGV))
+my $ret = system(@ARGV);
+my $exit_value  = $ret >> 8;
+my $signal_num  = $ret & 127;
+my $dumped_core = $ret & 128;
+my $crashed  = $signal_num + $dumped_core;
+
+if(0 == $exit_value || 0 != $crashed)
 {
     printf("FAIL $test_name\n");
+    exit 1;
 }
-else
-{
-    printf("PASS $test_name\n");
-}
-exit 0;
 
+printf("PASS $test_name\n");
+exit 0;
diff --git a/unit-tests/bin/make-recursive-newtest.pl b/unit-tests/bin/make-recursive-newtest.pl
new file mode 100755 (executable)
index 0000000..031a45d
--- /dev/null
@@ -0,0 +1,127 @@
+#!/usr/bin/perl 
+
+use strict;
+use Data::Dumper;
+use File::Find;
+use Cwd qw(realpath);
+
+my @args = @ARGV;
+
+$ENV{'LD_NO_CLASSSIC_LINKER'} = '1';
+$ENV{'LD_NO_CLASSSIC_LINKER_STATIC'} = '1';
+
+my $makefiles =
+{
+    'makefile' => undef,
+    'Makefile' => undef,
+    'makefile.newtest' => undef,
+    'Makefile.newtest' => undef,
+};
+
+my $find_opts =
+{
+    'wanted' => \&find_callback,
+};
+
+my $keywords =
+{
+    'root'   => '',
+    'cwd'    => '',
+    'cmd'    => '',
+    'exit'   => '',
+    'stdout' => [],
+    'stderr' => [],
+};
+
+my $keyword;
+my $max_keyword_len = 0;
+foreach $keyword (keys %$keywords)
+{ if($max_keyword_len < length($keyword)) { $max_keyword_len = length($keyword); } }
+my $delim = ':';
+$max_keyword_len += length($delim) + length(' ');
+
+my $last_keyword = '';
+
+sub print_line
+{
+    my ($keyword, $val) = @_;
+
+    if(!exists($$keywords{$keyword}))
+    {
+       print STDERR "error: keyword $keyword not in \$keywords set\n";
+       exit(1);
+    }
+
+    my $keyword_len = 0;
+
+    if($keyword ne $last_keyword)
+    {
+       print("$keyword"); print($delim);
+       $keyword_len = length($keyword) + length($delim);
+    }
+    if($max_keyword_len > $keyword_len)
+    {
+       my $num_spaces = $max_keyword_len - $keyword_len;
+       print(' ' x $num_spaces);
+    }
+    print("$val");
+    if(0)
+    {
+       $last_keyword = $keyword;
+    }
+}
+
+my $root = '.';
+$root = &realpath($root);
+print_line("root", "$root\n");
+
+find($find_opts, $root);
+
+sub find_callback
+{
+    if(exists($$makefiles{$_}))
+    {
+       my $makefile = $_;
+       my $reldir = $File::Find::dir;
+       $reldir =~ s|^$root/||;
+       
+       &print_line("cwd", "\$root/$reldir\n");
+       my $cmd = [ "make" ];
+       
+       push @$cmd, "-f";
+       push @$cmd, $makefile;
+       my $arg; foreach $arg (@ARGV) { push @$cmd, $arg; } # better way to do this?
+       &print_line("cmd", "@$cmd\n");
+
+        open(SAVEOUT, ">&STDOUT") || die("$!");
+        open(SAVEERR, ">&STDERR") || die("$!");
+       open(STDOUT, ">/tmp/unit-tests-stdout") || die("$!");
+       open(STDERR, ">/tmp/unit-tests-stderr") || die("$!");
+
+       $ENV{UNIT_TEST_NAME} = $reldir;
+       my $exit = system(@$cmd);
+
+       close(STDOUT) || die("$!");
+       close(STDERR) || die("$!");
+        open(STDOUT, ">&SAVEOUT") || die("$!");
+        open(STDERR, ">&SAVEERR") || die("$!");
+
+       &print_line("exit", "$exit\n");
+
+       open(OUT, "</tmp/unit-tests-stdout") || die("$!");
+       while(<OUT>)
+       {
+           &print_line("stdout", "$_");
+       }
+       close(OUT) || die("$!");
+       unlink("/tmp/unit-tests-stdout");
+       
+       open(ERR, "</tmp/unit-tests-stderr") || die("$!");
+       while(<ERR>)
+       {
+           &print_line("stderr", "$_");
+       }
+       close(ERR) || die("$!");
+    }
+       unlink("/tmp/unit-tests-stderr");
+}
index a44135022ed41a585c88ef7b62ccf33b2ffa6daa..f860985b8de5b3c9ec94ce19f2698a758ec428a5 100755 (executable)
@@ -7,6 +7,9 @@ use Cwd qw(realpath);
 
 my @args = @ARGV;
 
+$ENV{'LD_NO_CLASSSIC_LINKER'} = '1';
+$ENV{'LD_NO_CLASSSIC_LINKER_STATIC'} = '1';
+
 my $makefiles =
 {
     'makefile' => undef,
diff --git a/unit-tests/bin/mkld b/unit-tests/bin/mkld
new file mode 100755 (executable)
index 0000000..33aacc1
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+hide()
+{
+       $PROCTOR set_hidden $1 1 >/dev/null
+}
+
+if [ -z "$1" ]
+       then echo "Usage: mkld HOST [ DBPATH ]" >&2
+       exit 1
+fi
+
+if [ -z "$PROCTOR" ]
+       then PROCTOR=proctor
+fi
+
+DBNAME="$2"
+[ -z "$DBNAME" ] && DBNAME=ld
+PROCTOR="$PROCTOR $1 $DBNAME"
+
+$PROCTOR tools gcc g++ objc obj-c++ libstdc++ ld ld ld_classic cctools
+$PROCTOR sysattrs \
+ ld64="ld64" \
+ ld="ld (ld_classic)" \
+ gcc="GCC" \
+ cctools="cctools" \
+ os="OS Build" \
+ processor=Processor \
+ platform=Platform \
+ hostname="Hostname" \
+ gcc_opts="gcc options" \
+ g++_opts="g++ options" \
+ objc_opts="objc options" \
+ obj-c++_opts="obj-c++ options" \
+ libstdc++_opts="libstdc++ options" \
+ LANG="LANG environment variable" \
+ LC_CTYPE="LC_CTYPE environment variable" \
+ LC_MESSAGES="LC_MESSAGES environment variable" \
+ LC_ALL="LC_ALL environment variable" \
+ TMPDIR="TMPDIR environment variable" \
+ GCC_EXEC_PREFIX="GCC_EXEC_PREFIX environment variable" \
+ COMPILER_PATH="COMPILER_PATH environment variable" \
+ LIBRARY_PATH="LIBRARY_PATH environment variable" \
+ LANG="LANG environment variable" \
+ CPATH="CPATH environment variable" \
+ C_INCLUDE_PATH="C_INCLUDE_PATH environment variable" \
+ CPLUS_INCLUDE_PATH="CPLUS_INCLUDE_PATH environment variable" \
+ OBJC_INCLUDE_PATH="OBJC_INCLUDE_PATH environment variable" \
+ DEPENDENCIES_OUTPUT="DEPENDENCIES_OUTPUT environment variable" \
+ SUNPRO_DEPENDENCIES="SUNPRO_DEPENDENCIES environment variable" \
+
+for TOOL in gcc g++ objc obj-c++ libstdc++
+       do hide ${TOOL}_opts
+done
+
+hide LANG
+hide LC_CTYPE
+hide LC_MESSAGES
+hide LC_ALL
+hide TMPDIR
+hide GCC_EXEC_PREFIX
+hide COMPILER_PATH
+hide LIBRARY_PATH
+hide LANG
+hide CPATH
+hide C_INCLUDE_PATH
+hide CPLUS_INCLUDE_PATH
+hide OBJC_INCLUDE_PATH
+hide DEPENDENCIES_OUTPUT
+hide SUNPRO_DEPENDENCIES
+
+$PROCTOR results PASS=1 XFAIL=1 KFAIL=1 FAIL=0 XPASS=0 KPASS=0 UNRESOLVED=0 TIMEDOUT=0 UNSUPPORTED=0 UNTESTED=0
+$PROCTOR severities logline NOTE WARNING ERROR
diff --git a/unit-tests/bin/pass-iff-exit-non-zero.pl b/unit-tests/bin/pass-iff-exit-non-zero.pl
new file mode 100755 (executable)
index 0000000..beb76a9
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/perl -w
+
+#
+# Usage:
+#
+#              ${PASS_IFF} command
+#
+
+use strict;
+
+my $test_name = "";
+if ( exists $ENV{UNIT_TEST_NAME} ) {
+       $test_name = $ENV{UNIT_TEST_NAME};
+}
+
+my $ret = system(@ARGV);
+my $exit_value  = $ret >> 8;
+my $signal_num  = $ret & 127;
+my $dumped_core = $ret & 128;
+my $crashed  = $signal_num + $dumped_core;
+
+if(0 == $exit_value || 0 != $crashed)
+{
+    printf("FAIL $test_name\n");
+    exit 1;
+}
+
+printf("PASS $test_name\n");
+exit 0;
index ff0f1ed529129227c837849ed967205b7d53e0c7..07854b554bebed94820812d1592dfa39a29a778a 100755 (executable)
@@ -13,13 +13,11 @@ if ( exists $ENV{UNIT_TEST_NAME} ) {
        $test_name = $ENV{UNIT_TEST_NAME};
 }
 
-if(0 == system(@ARGV))
-{
-    printf("PASS $test_name\n");
-}
-else
+if(0 != system(@ARGV))
 {
     printf("FAIL $test_name\n");
+    exit 1;
 }
-exit 0;
 
+printf("PASS $test_name\n");
+exit 0;
index 08903f678555bdfb8496a7690b3fffcc5e5a135c..19b98b4a652a8923638bb3b3d99e2d37bd95f593 100755 (executable)
@@ -16,10 +16,8 @@ if ( exists $ENV{UNIT_TEST_NAME} ) {
 if( eof STDIN )
 {
     printf("PASS $test_name\n");
+    exit 0;
 }
-else
-{
-    printf("FAIL $test_name\n");
-}
-exit 0;
 
+printf("FAIL $test_name\n");
+exit 1;
index 0b56925faf5aef7d1422b44ce957269e325ae1d2..d5ee99fdb75bc21cdee3668d70f8f831e2b5980a 100755 (executable)
@@ -16,10 +16,9 @@ if ( exists $ENV{UNIT_TEST_NAME} ) {
 if( eof STDIN )
 {
     printf("FAIL $test_name\n");
+    exit 1
 }
-else
-{
-    printf("PASS $test_name\n");
-}
+
+printf("PASS $test_name\n");
 exit 0;
 
index 94434521b7297363b778fa58d3c5745deb5f5816..8168e794f181fabaaf4038b9dbd7085c778dc4c8 100755 (executable)
@@ -110,12 +110,16 @@ sub process_entry
     {
        if($line =~ m/^(PASS|XPASS|FAIL|XFAIL).+/)
        {
-           printf "%-40s %s\n", $test_name, $line;
            $total_count++;
            if($line =~ m/^PASS.+/)
            {
                $pass_count++;
            }
+           else
+           {
+               # only print failure lines
+               printf "%-40s %s\n", $test_name, $line;
+           }
            $seen_result = 1;
        }
     }
diff --git a/unit-tests/bin/rm-stale-test-logs b/unit-tests/bin/rm-stale-test-logs
new file mode 100755 (executable)
index 0000000..936dec1
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+usage() {
+       echo Usage: $0 number-of-tests-logs-to-keep
+       echo where number-of-tests-logs-to-keep must be a non-zero integer
+       exit
+}
+
+# Usage: if no arguments
+[ -z "$1" ] && usage
+
+# Check if requesting 0 tests to remain!
+[ "$1" -ne 0 ]
+
+# don't test directly--use the result value
+# because the command can fail for badly formed integers
+[ $? -ne 0 ] && usage
+
+# get the dir names of all tests in date order
+ls -1dtr /tmp/proctor*>/tmp/all$$ 2>/dev/null
+
+# select the last few to keep
+tail -$1 /tmp/all$$>/tmp/keep$$
+
+# get a list of the others
+DELLIST=`diff /tmp/all$$ /tmp/keep$$|grep '^<'|sed -e 's/^< //'`
+
+# any work to do?
+if [ "$DELLIST" ]
+then
+       echo rm -rf $DELLIST
+       rm -rf $DELLIST
+fi
+
+# rm the temps
+rm /tmp/all$$ /tmp/keep$$
diff --git a/unit-tests/clean-tests b/unit-tests/clean-tests
new file mode 100755 (executable)
index 0000000..4c38b4e
--- /dev/null
@@ -0,0 +1,63 @@
+find_makefile()
+{
+       local j
+
+       MF=""
+
+       if [ ! -d $1 ]
+       then
+               return 1
+       fi
+
+       for j in Makefile makefile Makefile.newtest makefile.newtest
+       do
+               [ -f $1/$j ] && MF=$j
+       done
+
+       [ "$MF" ] && return 0
+       return 1
+}
+
+find_path_to_test_dir()
+{
+       # FIND THE PATH TO THE TEST DIR
+       # SO THAT WE CAN ADD THE BIN DIR INTO
+       # THE SEARCH PATH
+
+       # remember the top level execution dir
+       chmod +x "$0"   # just in case
+
+       #add path to $0 into search
+       savedir=$PWD
+               DIRNAME=`dirname $0`
+               [ -d "$DIRNAME" ] && cd "$DIRNAME"
+               PATH=$PATH:$PWD
+       cd "$savedir"
+
+       chmod +x "$0"   # just in case
+       EXECNAME=`which $0`
+       DIRNAME=`dirname "$EXECNAME"`
+       if [ -d "$DIRNAME" ]
+       then
+               TEST_HOME_DIR="$DIRNAME"
+       else
+               TEST_HOME_DIR="$savedir" # Give up and assume current dir
+       fi
+
+       PATH="$PATH":"$TEST_HOME_DIR"/bin:"$savedir"
+}
+
+find_path_to_test_dir
+
+cd "$TEST_HOME_DIR/test-cases"
+
+for i in *
+do
+       [ -d "$i" ] &&
+       (
+               if find_makefile $i
+               then
+                       make -C $i -f $MF -s -k clean >/dev/null 2>/dev/null
+               fi
+       )
+done
index 266eb8502a3627bc256ea429356be82b12eeadff..8462385b354a72471396ea6f5017431fefa15c0e 100644 (file)
@@ -6,25 +6,25 @@ SHELL = /bin/sh
 ARCH ?= $(shell arch)
 
 # set default to be all
-VALID_ARCHS ?= "ppc ppc64 i386"
+VALID_ARCHS ?= "ppc ppc64 i386 x86_64"
+
+MYDIR=$(shell cd ../../bin;pwd)
 
 # if run within Xcode, add the just built tools to the command path
 ifdef BUILT_PRODUCTS_DIR
-       PATH := ${BUILT_PRODUCTS_DIR}:${PATH}
+       PATH := ${BUILT_PRODUCTS_DIR}:${MYDIR}:${PATH}
+       COMPILER_PATH := ${BUILT_PRODUCTS_DIR}:${MYDIR}:${COMPILER_PATH}
+else
+       PATH := ${MYDIR}:${PATH}:
+       COMPILER_PATH := ${MYDIR}:${COMPILER_PATH}:
 endif
+export PATH
+export COMPILER_PATH
 
 LD                     = ld
 OBJECTDUMP     = ObjectDump
 MACHOCHECK     = machocheck
-
 OTOOL = otool
-ifeq (${ARCH},ppc64)
-OTOOL = otool64
-endif
-ifeq (${ARCH},x86_64)
-OTOOL = otool64
-endif
-
 
 CC              = gcc-4.0 -arch ${ARCH}
 CCFLAGS = -Wall -std=c99
@@ -37,12 +37,17 @@ RM      = rm
 RMFLAGS = -rf
 
 # utilites for Makefiles
-PASS_IFF                       = ${TESTROOT}/bin/pass-iff-exit-zero.pl
-PASS_IFF_EMPTY         = ${TESTROOT}/bin/pass-iff-no-stdin.pl
-PASS_IFF_STDIN         = ${TESTROOT}/bin/pass-iff-stdin.pl
-PASS_IFF_GOOD_MACHO    = ${TESTROOT}/bin/pass-iff-exit-zero.pl ${MACHOCHECK}
-FAIL_IFF                       = ${TESTROOT}/bin/fail-iff-exit-zero.pl
-FAIL_IF_BAD_MACHO      = ${TESTROOT}/bin/fail-if-exit-non-zero.pl ${MACHOCHECK}
-FAIL_IF_SUCCESS         = ${TESTROOT}/bin/fail-if-exit-zero.pl
-FAIL_IF_EMPTY          = ${TESTROOT}/bin/fail-if-no-stdin.pl
-FAIL_IF_STDIN          = ${TESTROOT}/bin/fail-if-stdin.pl
+PASS_IFF                       = pass-iff-exit-zero.pl
+PASS_IFF_SUCCESS       = ${PASS_IFF}
+PASS_IFF_EMPTY         = pass-iff-no-stdin.pl
+PASS_IFF_STDIN         = pass-iff-stdin.pl
+FAIL_IFF                       = fail-iff-exit-zero.pl
+FAIL_IFF_SUCCESS       = ${FAIL_IFF}
+PASS_IFF_ERROR         = pass-iff-exit-non-zero.pl
+FAIL_IF_ERROR          = fail-if-exit-non-zero.pl
+FAIL_IF_SUCCESS     = fail-if-exit-zero.pl
+FAIL_IF_EMPTY          = fail-if-no-stdin.pl
+FAIL_IF_STDIN          = fail-if-stdin.pl
+PASS_IFF_GOOD_MACHO    = ${PASS_IFF} ${MACHOCHECK}
+FAIL_IF_BAD_MACHO      = ${FAIL_IF_ERROR} ${MACHOCHECK}
+FAIL_IF_BAD_OBJ                = ${FAIL_IF_ERROR} ${OBJECTDUMP} >/dev/null
diff --git a/unit-tests/proctor-run b/unit-tests/proctor-run
new file mode 100755 (executable)
index 0000000..e7bdea4
--- /dev/null
@@ -0,0 +1,204 @@
+#!/bin/sh
+
+all_archs="ppc ppc64 i386 x86_64"
+
+sysattr()
+{
+       echo "    <sysattr name=\"$1\" value=\"$2\" />"
+}
+
+doresults()
+{
+       local ver
+
+       echo "<tests end_time=\"`date +%s`\" start_time=\"$start_time\" comment=\""$comment"\">"
+
+       echo "  <sysattrs>"
+       sysattr cctools "`as</dev/null -v 2>&1 |sed 's/.*cctools-//;s/,.*//'`"
+       sysattr hostname "`hostname`"
+       sysattr os "`uname -r`"
+       sysattr platform "`uname -m`"
+       sysattr ld64 "`ld64 -v 2>&1|sed 's/.*PROJECT://;s/ .*//'`"
+       sysattr ld "`ld_classic -v 2>&1|sed 's/.*cctools-//;s/ .*//'`"
+       sysattr gcc "`gcc --version|head -1`"
+       sysattr processor "`uname -p`"
+       sysattr LANG "$LANG"
+       sysattr LC_CTYPE "$LC_CTYPE"
+       sysattr LC_MESSAGES "$LC_MESSAGES"
+       sysattr LC_ALL "$LC_ALL"
+       sysattr TMPDIR "$TMPDIR"
+       sysattr GCC_EXEC_PREFIX "$GCC_EXEC_PREFIX"
+       sysattr COMPILER_PATH "$COMPILER_PATH"
+       sysattr LIBRARY_PATH "$LIBRARY_PATH"
+       sysattr LANG "$LANG"
+       sysattr CPATH "$CPATH"
+       sysattr C_INCLUDE_PATH "$C_INCLUDE_PATH"
+       sysattr CPLUS_INCLUDE_PATH "$CPLUS_INCLUDE_PATH"
+       sysattr OBJC_INCLUDE_PATH "$OBJC_INCLUDE_PATH"
+       sysattr DEPENDENCIES_OUTPUT "$DEPENDENCIES_OUTPUT"
+       sysattr SUNPRO_DEPENDENCIES "$SUNPRO_DEPENDENCIES"
+       echo "  </sysattrs>"
+
+       echo "<tools>"
+       echo "<tool name=\"ld\">"
+       echo "  <results incomplete=\"0\">"
+       for i in $*
+       do
+               echo "    <testgroup name=\"$i\">"
+               cat $i
+               echo "    </testgroup>"
+       done
+
+       echo "  </results>"
+       echo "</tool>"
+       echo "</tools>"
+       echo "</tests>"
+
+       #rm $*
+}
+
+find_path_to_test_dir()
+{
+       # FIND THE PATH TO THE TEST DIR
+       # SO THAT WE CAN ADD THE BIN DIR INTO
+       # THE SEARCH PATH
+
+       # remember the top level execution dir
+       chmod +x "$0"   # just in case
+
+       #add path to $0 into search
+       local savedir
+       savedir=$PWD
+               DIRNAME=`dirname $0`
+               [ -d "$DIRNAME" ] && cd "$DIRNAME"
+               PATH=$PATH:$PWD
+       cd "$savedir"
+
+       chmod +x "$0"   # just in case
+       EXECNAME=`which $0`
+       DIRNAME=`dirname "$EXECNAME"`
+       if [ -d "$DIRNAME" ]
+       then
+               TEST_HOME_DIR=`cd "$DIRNAME";pwd`
+       fi
+
+       if [ -z "$TEST_HOME_DIR" ]
+       then
+               TEST_HOME_DIR="$savedir" # Give up and assume current dir
+       fi
+
+       cd "$TEST_HOME_DIR"
+       cd ../build/Release
+
+       PATH="$PWD":"$TEST_HOME_DIR/bin":"$PATH"
+       cd "$savedir"
+}
+
+start_time=`date +%s`
+
+find_path_to_test_dir
+
+# Execute from the location of the script; or if not found the current loc
+[ -d $TEST_HOME_DIR/test-cases ] && cd $TEST_HOME_DIR/test-cases || cd test-cases
+
+rm-stale-test-logs 3 >/dev/null &
+
+make -C ../src # make sure the binaries are available
+
+DATEFORMAT=`date +%F-%H%M | sed -e 's/ //'`
+tmpdir=/tmp/proctor$DATEFORMAT
+
+if ! mkdir $tmpdir >/dev/null 2>/dev/null
+then
+       rm -rf $tmpdir
+       mkdir $tmpdir
+fi
+
+
+linestart=0
+if [ x$1 = x-comment ]
+then
+       shift
+       comment="$1"
+       shift
+fi
+
+find_makefile()
+{
+       local j
+
+       MF=""
+
+       if [ ! -d $1 ]
+       then
+               return 1
+       fi
+
+       for j in Makefile makefile
+       do
+               [ -f $1/$j ] && MF=$j
+       done
+
+       if [ "$NEWTEST" ]
+       then
+               for j in Makefile.newtest makefile.newtest
+               do
+                       [ -f $1/$j ] && MF=$j
+               done
+       fi
+
+       [ "$MF" ] && return 0
+       return 1
+}
+
+one_test()
+{
+       echo cwd: $1
+       echo cmd: $1 ARCH="$arch"
+       make -f "$MF" -C $1 ARCH="$arch" 2>$tmpdir/stderr >$tmpdir/stdout
+       result=$?
+       sed 's/^/stdout: /'<$tmpdir/stdout
+       sed 's/^/stderr: /'<$tmpdir/stderr
+       echo exit: $?
+}
+
+if [ "$1" ]
+then
+       i="$1"
+       for arch in $all_archs
+       do
+               rm -f $tmpdir/$arch
+               if find_makefile $i
+               then
+                       one_test $i
+               fi
+               #fi | tee -a $tmpdir/raw | ../bin/results-to-xml $linestart>>$tmpdir/$arch
+               linestart=`expr $linestart + 10000`
+       done | tee -a $tmpdir/raw | ../bin/results-to-xml $linestart>>$tmpdir/$arch
+else
+       for arch in $all_archs
+       do
+               rm -f $tmpdir/$arch
+               for i in *
+               do
+                       if find_makefile $i
+                       then
+                               one_test $i
+                       fi
+               done | tee -a $tmpdir/raw | ../bin/results-to-xml $linestart>>$tmpdir/$arch
+               linestart=`expr $linestart + 10000`
+       done
+fi
+
+(cd $tmpdir; doresults $all_archs)>$tmpdir/o.xml
+../bin/xmlparser $tmpdir/o.xml >/dev/null
+if [ $? = 0 ]
+then
+       if ! proctor localhost ld import $tmpdir/o.xml
+       then
+               proctor database load failed!
+       fi
+else
+       echo Test results not loaded: internal xml error!
+       exit 1
+fi
index 3756bd156c928d4d189b248d66b6941e7057f20d..945df480e82852770d610fc6dfb64153485624c3 100755 (executable)
@@ -3,21 +3,23 @@
 # cd into test-cases directory
 cd `echo "$0" | sed 's/run-all-unit-tests/test-cases/'`
 
+[ "$PROCTORRUN" ] && exec ../proctor-run
+
 all_archs="ppc ppc64 i386 x86_64"
 
+mkdir /tmp/$$
 for arch in $all_archs
 do
        echo ""
        echo " * * * Running all unit tests for architecture $arch * * *"
 
        # build architecture
-       ../bin/make-recursive.pl ARCH=$arch VALID_ARCHS="$all_archs" | ../bin/result-filter.pl
+       [ "$NEWTEST" ] && NT=-newtest
+
+       ../bin/make-recursive$NT.pl ARCH=$arch VALID_ARCHS="$all_archs" | ../bin/result-filter.pl
 
        # clean up so svn is happy
        ../bin/make-recursive.pl ARCH=$arch clean > /dev/null
 
        echo ""
 done
-
-
-
diff --git a/unit-tests/run-all-unit-tests-debug b/unit-tests/run-all-unit-tests-debug
new file mode 100755 (executable)
index 0000000..a239748
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# cd into test-cases directory
+cd `echo "$0" | sed 's/run-all-unit-tests/test-cases/'`
+
+[ "$PROCTORRUN" ] && exec ../proctor-run
+
+all_archs="ppc ppc64 i386 x86_64"
+
+mkdir /tmp/$$
+for arch in $all_archs
+do
+       echo ""
+       echo " * * * Running all unit tests for architecture $arch * * *"
+
+       # build architecture
+       [ "$NEWTEST" ] && NT=-newtest
+
+       mkdir /tmp/$$
+       ../bin/make-recursive$NT.pl ARCH=$arch VALID_ARCHS="$all_archs" | tee /tmp/$$/raw | ../bin/result-filter.pl | tee /tmp/$$/sum
+
+       # clean up so svn is happy
+       ../bin/make-recursive.pl ARCH=$arch clean > /dev/null
+
+       echo ""
+done
diff --git a/unit-tests/src/Makefile b/unit-tests/src/Makefile
new file mode 100644 (file)
index 0000000..d3bdeab
--- /dev/null
@@ -0,0 +1,9 @@
+
+all: ../bin/results-to-xml ../bin/xmlparser
+
+../bin/results-to-xml: results-to-xml.cpp
+       g++ -g -O -Wall $< -o ../bin/results-to-xml
+
+../bin/xmlparser:
+       cd xmlparser; xcodebuild -alltargets
+       cp -p xmlparser/build/Release/xmlparser ../bin/.
diff --git a/unit-tests/src/results-to-xml.cpp b/unit-tests/src/results-to-xml.cpp
new file mode 100644 (file)
index 0000000..a305347
--- /dev/null
@@ -0,0 +1,260 @@
+#include <string>
+#include <sstream>
+#include <iostream>
+
+using namespace std;
+
+#define        NELEMENTS(a)    (sizeof (a)/sizeof *(a))
+
+#define        NO_RESULT       (-1)
+#define        PASS            1
+#define        FAIL            0
+
+#define        DBG     bhole
+
+void
+bhole(...)
+{
+}
+
+class line_category
+{
+public:
+       const char *key;
+       char line[99999];
+       void (*test)(line_category &);
+       int test_result;
+} lc;
+
+void
+deft(line_category &l)
+{
+       l.test_result = PASS;
+}
+
+void
+pass_fail(line_category &l)
+{
+       if(FAIL!=l.test_result)
+               l.test_result = strnstr(l.line, "FAIL", 4)? FAIL: PASS;
+}
+
+void
+stderr_output(line_category &l)
+{
+       if(FAIL==l.test_result)
+               return;
+
+       if(l.line[0])
+               l.test_result = FAIL;
+}
+
+void
+exit_test(line_category &l)
+{
+       if(!atoi(l.line)) {
+               DBG("exit_test(%s)==%d\n", l.line, atoi(l.line));
+               l.test_result = PASS;
+       }
+}
+
+#define        STDOUT  "stdout: "
+#define        STDERR  "stderr: "
+#define        CWD     "cwd: "
+#define        CMD     "cmd: "
+#define        SEXIT   "exit: "
+line_category line_categories[] = {
+       { CWD, "" , deft, NO_RESULT},   /* must be first */
+       { CMD, "", deft, NO_RESULT},
+       { STDOUT, "", pass_fail, NO_RESULT},
+       { STDERR, "", stderr_output, NO_RESULT },
+       { SEXIT, "", exit_test, NO_RESULT },
+};
+
+static line_category no_line_category = { "none", "no test", deft, NO_RESULT };
+
+line_category &
+retrieve(line_category &l, const char *s)
+{
+       unsigned j;
+       line_category *lp = &l;
+       //int final_result = PASS;
+
+       for(j=0; j<NELEMENTS(line_categories); ++j,++lp) {//TODO: remove NELEMENTS
+               if(!strcmp(lp->key, s)) {
+                       char *p;
+
+                       for(p=(char *)lp->line; *p; ++p) {
+                               switch(*p) {
+                               case '\0':
+                                       break;
+                               case '"':
+                               case '<':
+                                       *p = ' ';
+                                       // fall thru
+                               default:
+                                       continue;
+                               }
+                       }
+DBG("FOUND line_categories[j].line==%s\n", lp->line);
+                       return line_categories[j];
+               }
+       }
+
+       return no_line_category;
+}
+
+void
+xml_string_print(FILE *strm, const char *s)
+{
+       fputc('"', strm);
+       for( ; ; ++s) {
+               switch(*s) {
+               case '\0':
+                       break;
+               case '&':
+                       fputs("&amp;", strm);
+                       continue;
+               default:
+                       fputc(*s, strm);
+                       continue;
+               }
+               break;
+       }
+       fputc('"', strm);
+}
+
+//     
+//     FAIL if stderr non-zero
+//     FAIL if stdout=="FAIL"
+//     UNRESOLVED if make exit non-zero
+//     PASS otherwise
+//     
+
+static int cnt;
+void
+dump_test(void)
+{
+       unsigned j;
+       int final_result = PASS;
+
+       for(j=0; j<NELEMENTS(line_categories); ++j) {
+               if(line_categories[j].line[0]) {
+                       line_categories[j].line[strlen(line_categories[j].line)-1] = '\0';
+                       DBG("%s%s RESULT %d\n"
+                               , line_categories[j].key
+                               , line_categories[j].line
+                               , line_categories[j].test_result
+                               );
+
+                       if(PASS==final_result) {
+                               final_result = line_categories[j].test_result;
+                               if(NO_RESULT==line_categories[j].test_result) {
+                                       final_result = NO_RESULT;
+                               } else if(FAIL==line_categories[j].test_result) {
+                                       final_result = FAIL;
+                               }
+                       }
+               }
+       }
+
+       printf("<test name=");
+       xml_string_print(stdout, retrieve(line_categories[0], CMD).line);
+       printf(" result=\"");
+       if(NO_RESULT==final_result) {
+               printf("UNRESOLVED");
+       } else if(FAIL==final_result) {
+               printf("FAIL");
+       } else {
+               printf("PASS");
+       }
+       printf("\" ");
+
+       char *s = retrieve(line_categories[0], CWD).line;
+       if(*s) {
+               char detail[9999];
+               char fn[9999];
+               FILE *strm;
+
+               strncpy(fn, s, sizeof fn);
+               strncat(fn, "/comment.txt", sizeof fn);
+               strm = fopen(fn, "r");
+               if(strm) {
+                       if(fgets(detail, -1+sizeof detail, strm)) {
+                               detail[strlen(detail)-1] = '\0';
+                               printf("detail=");
+                               xml_string_print(stdout, detail);
+                       }
+               }
+       }
+       printf(">\n");
+
+       printf("    <diagnostics>\n");
+       s = retrieve(line_categories[0], STDERR).line;
+       if(*s) {
+               printf("      <diagnostic line=\"%d\" message=", ++cnt);
+               xml_string_print(stdout, s);
+               printf(" severity=\"ERROR\"/>\n");
+       }
+#if 1
+       s = retrieve(line_categories[0], STDOUT).line;
+       if(*s) {
+               printf("      <diagnostic line=\"%d\" message=", ++cnt);
+               xml_string_print(stdout, s);
+               printf(" severity=\"note\"/>\n");
+       }
+#endif
+       printf("    </diagnostics>\n");
+       printf("</test>\n\n");
+
+       for(j=0; j<NELEMENTS(line_categories); ++j) {
+               line_categories[j].line[0] = '\0';
+               line_categories[j].test_result = NO_RESULT;
+       }
+}
+
+int
+main(int argc, char **argv)
+{
+       int firsttime = 1;
+
+
+       if(argc>1)
+               cnt = atoi(argv[1]);
+
+       for(;;) {
+               char line[99999];
+               int i;
+
+               line[0] = '\0';
+               fgets(line, sizeof line, stdin);
+               if(feof(stdin)) {
+                       dump_test();
+                       break;
+               }
+
+               for(i=0; ; ++i) {
+                       size_t len = strlen(line_categories[i].key);
+
+                       //DBG("strnstr(%s, %s, %u)\n", line, line_categories[i].key, len);
+                       if(strnstr(line, line_categories[i].key, len)) {
+                               if(firsttime)
+                                       firsttime = 0;
+                               else if(0==i)
+                                       dump_test();
+
+                               char *lp = &line[len];
+                               //DBG("%s%s", line_categories[i].key, lp);
+                               strncpy(line_categories[i].line, lp, sizeof line_categories[i].line);
+                               line_categories[i].test(line_categories[i]);
+                               break;
+                       }
+
+                       if(i==NELEMENTS(line_categories)-1) {
+                               DBG("BADLINE:%s", line);
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
diff --git a/unit-tests/src/xmlparser/xmlparser.1 b/unit-tests/src/xmlparser/xmlparser.1
new file mode 100644 (file)
index 0000000..6eab06a
--- /dev/null
@@ -0,0 +1,79 @@
+.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.\r
+.\"See Also:\r
+.\"man mdoc.samples for a complete listing of options\r
+.\"man mdoc for the short list of editing options\r
+.\"/usr/share/misc/mdoc.template\r
+.Dd 9/18/06               \" DATE \r
+.Dt xmlparser 1      \" Program name and manual section number \r
+.Os Darwin\r
+.Sh NAME                 \" Section Header - required - don't modify \r
+.Nm xmlparser,\r
+.\" The following lines are read in generating the apropos(man -k) database. Use only key\r
+.\" words here as the database is built based on the words here and in the .ND line. \r
+.Nm Other_name_for_same_program(),\r
+.Nm Yet another name for the same program.\r
+.\" Use .Nm macro to designate other names for the documented program.\r
+.Nd This line parsed for whatis database.\r
+.Sh SYNOPSIS             \" Section Header - required - don't modify\r
+.Nm\r
+.Op Fl abcd              \" [-abcd]\r
+.Op Fl a Ar path         \" [-a path] \r
+.Op Ar file              \" [file]\r
+.Op Ar                   \" [file ...]\r
+.Ar arg0                 \" Underlined argument - use .Ar anywhere to underline\r
+arg2 ...                 \" Arguments\r
+.Sh DESCRIPTION          \" Section Header - required - don't modify\r
+Use the .Nm macro to refer to your program throughout the man page like such:\r
+.Nm\r
+Underlining is accomplished with the .Ar macro like this:\r
+.Ar underlined text .\r
+.Pp                      \" Inserts a space\r
+A list of items with descriptions:\r
+.Bl -tag -width -indent  \" Begins a tagged list \r
+.It item a               \" Each item preceded by .It macro\r
+Description of item a\r
+.It item b\r
+Description of item b\r
+.El                      \" Ends the list\r
+.Pp\r
+A list of flags and their descriptions:\r
+.Bl -tag -width -indent  \" Differs from above in tag removed \r
+.It Fl a                 \"-a flag as a list item\r
+Description of -a flag\r
+.It Fl b\r
+Description of -b flag\r
+.El                      \" Ends the list\r
+.Pp\r
+.\" .Sh ENVIRONMENT      \" May not be needed\r
+.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1\r
+.\" .It Ev ENV_VAR_1\r
+.\" Description of ENV_VAR_1\r
+.\" .It Ev ENV_VAR_2\r
+.\" Description of ENV_VAR_2\r
+.\" .El                      \r
+.Sh FILES                \" File used or created by the topic of the man page\r
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact\r
+.It Pa /usr/share/file_name\r
+FILE_1 description\r
+.It Pa /Users/joeuser/Library/really_long_file_name\r
+FILE_2 description\r
+.El                      \" Ends the list\r
+.\" .Sh DIAGNOSTICS       \" May not be needed\r
+.\" .Bl -diag\r
+.\" .It Diagnostic Tag\r
+.\" Diagnostic informtion here.\r
+.\" .It Diagnostic Tag\r
+.\" Diagnostic informtion here.\r
+.\" .El\r
+.Sh SEE ALSO \r
+.\" List links in ascending order by section, alphabetically within a section.\r
+.\" Please do not reference files that do not exist without filing a bug report\r
+.Xr a 1 , \r
+.Xr b 1 ,\r
+.Xr c 1 ,\r
+.Xr a 2 ,\r
+.Xr b 2 ,\r
+.Xr a 3 ,\r
+.Xr b 3 \r
+.\" .Sh BUGS              \" Document known, unremedied bugs \r
+.\" .Sh HISTORY           \" Document history if command behaves in a unique manner
\ No newline at end of file
diff --git a/unit-tests/src/xmlparser/xmlparser.m b/unit-tests/src/xmlparser/xmlparser.m
new file mode 100644 (file)
index 0000000..a9c82fc
--- /dev/null
@@ -0,0 +1,25 @@
+#import <Foundation/Foundation.h>\r
+\r
+int main(int argc, char *argv[]) {\r
+       [[NSAutoreleasePool alloc] init];\r
+\r
+       if(argc != 2) {\r
+               NSLog(@"Usage: %s path-to-XML\n", argv[0]);\r
+               return 1;\r
+       }\r
+       NSString *path = [NSString stringWithUTF8String:argv[1]];\r
+\r
+       NSError *err = nil;\r
+       NSXMLDocument *doc = [[NSXMLDocument alloc]\r
+               initWithContentsOfURL:[NSURL\r
+                       fileURLWithPath:path]\r
+               options:0\r
+               error:&err];\r
+       if(err) {\r
+               NSLog(@"ERROR: %@", err);\r
+               return 1;\r
+       } else {\r
+               NSLog(@"Parsed!");\r
+               return 0;\r
+       }\r
+}\r
diff --git a/unit-tests/src/xmlparser/xmlparser.xcodeproj/project.pbxproj b/unit-tests/src/xmlparser/xmlparser.xcodeproj/project.pbxproj
new file mode 100644 (file)
index 0000000..9492293
--- /dev/null
@@ -0,0 +1,218 @@
+// !$*UTF8*$!
+{
+       archiveVersion = 1;
+       classes = {
+       };
+       objectVersion = 42;
+       objects = {
+
+/* Begin PBXBuildFile section */
+               8DD76F9A0486AA7600D96B5E /* xmlparser.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* xmlparser.m */; settings = {ATTRIBUTES = (); }; };
+               8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
+               8DD76F9F0486AA7600D96B5E /* xmlparser.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6859EA3029092ED04C91782 /* xmlparser.1 */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+               8DD76F9E0486AA7600D96B5E /* CopyFiles */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 8;
+                       dstPath = /usr/share/man/man1/;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               8DD76F9F0486AA7600D96B5E /* xmlparser.1 in CopyFiles */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+               08FB7796FE84155DC02AAC07 /* xmlparser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = xmlparser.m; sourceTree = "<group>"; };
+               08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+               32A70AAB03705E1F00C91783 /* xmlparser_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xmlparser_Prefix.pch; sourceTree = "<group>"; };
+               8DD76FA10486AA7600D96B5E /* xmlparser */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xmlparser; sourceTree = BUILT_PRODUCTS_DIR; };
+               C6859EA3029092ED04C91782 /* xmlparser.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = xmlparser.1; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+               8DD76F9B0486AA7600D96B5E /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+               08FB7794FE84155DC02AAC07 /* xmlparser */ = {
+                       isa = PBXGroup;
+                       children = (
+                               08FB7795FE84155DC02AAC07 /* Source */,
+                               C6859EA2029092E104C91782 /* Documentation */,
+                               08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
+                               1AB674ADFE9D54B511CA2CBB /* Products */,
+                       );
+                       name = xmlparser;
+                       sourceTree = "<group>";
+               };
+               08FB7795FE84155DC02AAC07 /* Source */ = {
+                       isa = PBXGroup;
+                       children = (
+                               32A70AAB03705E1F00C91783 /* xmlparser_Prefix.pch */,
+                               08FB7796FE84155DC02AAC07 /* xmlparser.m */,
+                       );
+                       name = Source;
+                       sourceTree = "<group>";
+               };
+               08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
+                       isa = PBXGroup;
+                       children = (
+                               08FB779EFE84155DC02AAC07 /* Foundation.framework */,
+                       );
+                       name = "External Frameworks and Libraries";
+                       sourceTree = "<group>";
+               };
+               1AB674ADFE9D54B511CA2CBB /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               8DD76FA10486AA7600D96B5E /* xmlparser */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+               C6859EA2029092E104C91782 /* Documentation */ = {
+                       isa = PBXGroup;
+                       children = (
+                               C6859EA3029092ED04C91782 /* xmlparser.1 */,
+                       );
+                       name = Documentation;
+                       sourceTree = "<group>";
+               };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+               8DD76F960486AA7600D96B5E /* xmlparser */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "xmlparser" */;
+                       buildPhases = (
+                               8DD76F990486AA7600D96B5E /* Sources */,
+                               8DD76F9B0486AA7600D96B5E /* Frameworks */,
+                               8DD76F9E0486AA7600D96B5E /* CopyFiles */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = xmlparser;
+                       productInstallPath = "$(HOME)/bin";
+                       productName = xmlparser;
+                       productReference = 8DD76FA10486AA7600D96B5E /* xmlparser */;
+                       productType = "com.apple.product-type.tool";
+               };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+               08FB7793FE84155DC02AAC07 /* Project object */ = {
+                       isa = PBXProject;
+                       buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "xmlparser" */;
+                       hasScannedForEncodings = 1;
+                       mainGroup = 08FB7794FE84155DC02AAC07 /* xmlparser */;
+                       projectDirPath = "";
+                       targets = (
+                               8DD76F960486AA7600D96B5E /* xmlparser */,
+                       );
+               };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+               8DD76F990486AA7600D96B5E /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               8DD76F9A0486AA7600D96B5E /* xmlparser.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+               1DEB927508733DD40010E9CD /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               COPY_PHASE_STRIP = NO;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_MODEL_TUNING = G5;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PRECOMPILE_PREFIX_HEADER = YES;
+                               GCC_PREFIX_HEADER = xmlparser_Prefix.pch;
+                               INSTALL_PATH = "$(HOME)/bin";
+                               PRODUCT_NAME = xmlparser;
+                               ZERO_LINK = YES;
+                       };
+                       name = Debug;
+               };
+               1DEB927608733DD40010E9CD /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ARCHS = (
+                                       ppc,
+                                       i386,
+                               );
+                               GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+                               GCC_MODEL_TUNING = G5;
+                               GCC_PRECOMPILE_PREFIX_HEADER = YES;
+                               GCC_PREFIX_HEADER = xmlparser_Prefix.pch;
+                               INSTALL_PATH = "$(HOME)/bin";
+                               PRODUCT_NAME = xmlparser;
+                       };
+                       name = Release;
+               };
+               1DEB927908733DD40010E9CD /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               PREBINDING = NO;
+                               SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+                               ZERO_LINK = YES;
+                       };
+                       name = Debug;
+               };
+               1DEB927A08733DD40010E9CD /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               PREBINDING = NO;
+                               SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+                               ZERO_LINK = NO;
+                       };
+                       name = Release;
+               };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+               1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "xmlparser" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               1DEB927508733DD40010E9CD /* Debug */,
+                               1DEB927608733DD40010E9CD /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "xmlparser" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               1DEB927908733DD40010E9CD /* Debug */,
+                               1DEB927A08733DD40010E9CD /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+/* End XCConfigurationList section */
+       };
+       rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/unit-tests/src/xmlparser/xmlparser_Prefix.pch b/unit-tests/src/xmlparser/xmlparser_Prefix.pch
new file mode 100644 (file)
index 0000000..530e057
--- /dev/null
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'xmlparser' target in the 'xmlparser' project.
+//
+
+#ifdef __OBJC__
+    #import <Foundation/Foundation.h>
+#endif
diff --git a/unit-tests/test-cases/16-byte-alignment/Makefile b/unit-tests/test-cases/16-byte-alignment/Makefile
new file mode 100644 (file)
index 0000000..a3a256f
--- /dev/null
@@ -0,0 +1,44 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# Test that -O2 optimization fails when trying to make a long 16-byte aligned.
+#
+
+run: all
+
+all:
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -arch ${ARCH} -c -O2 tl_test2.c -o tl_test2-${ARCH}.o
+
+       # verify that the alignment is correct in the .o
+       ObjectDump -only _ai -align -no_content tl_test2-${ARCH}.o|${FAIL_IF_ERROR} grep '\<0 mod 16\>' >/dev/null
+
+       # now verify the executable
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -arch ${ARCH} -O2 tl_test2-${ARCH}.o -o tl_test2-${ARCH}
+       ${FAIL_IF_ERROR} sh -c "nm tl_test2-${ARCH}|grep '0 D _ai\>' >/dev/null"
+       ${PASS_IFF_GOOD_MACHO} tl_test2-${ARCH}
+
+clean:
+       rm -rf tl_test2-*
diff --git a/unit-tests/test-cases/16-byte-alignment/comment.txt b/unit-tests/test-cases/16-byte-alignment/comment.txt
new file mode 100644 (file)
index 0000000..eb9eaf5
--- /dev/null
@@ -0,0 +1 @@
+Test 16 byte alignment with -O2 optimization. Radar #4662185
diff --git a/unit-tests/test-cases/16-byte-alignment/tl_test2.c b/unit-tests/test-cases/16-byte-alignment/tl_test2.c
new file mode 100644 (file)
index 0000000..ff27fec
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <stdio.h>
+
+int i = 1;
+int ai __attribute__ ((aligned (16))) = 1;
+
+int main() {
+
+       long addr = (long)&ai;
+       i = ai;
+       if (addr & 0xf) {
+               printf("failed: ai = %p\n", (void *)addr);
+               return 1;
+       }
+       printf("passed: ai = %p\n", (void *)addr);
+       return 0;
+}
diff --git a/unit-tests/test-cases/absolute-symbol/Makefile b/unit-tests/test-cases/absolute-symbol/Makefile
new file mode 100644 (file)
index 0000000..065b6f3
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Validate linker processing of absolute symbols
+#
+
+all:
+       ${CC} ${CCFLAGS} main.c -static -c
+       ${CC} ${CCFLAGS} abs.s -static -c
+       ${LD} -arch ${ARCH} -static main.o abs.o -e _main -o main
+       ${LD} -arch ${ARCH} -static -r main.o abs.o -o all.o
+       nm -m all.o | grep _myAbs | grep absolute | ${FAIL_IF_EMPTY}
+       ${LD} -arch ${ARCH} -static all.o -e _main -o main2
+       ${PASS_IFF_GOOD_MACHO} main2
+       
+clean:
+       rm -rf main.o abs.o all.o main main2
diff --git a/unit-tests/test-cases/absolute-symbol/abs.s b/unit-tests/test-cases/absolute-symbol/abs.s
new file mode 100644 (file)
index 0000000..216867c
--- /dev/null
@@ -0,0 +1,3 @@
+
+  .globl _myAbs
+  .set _myAbs, 0xfe000000
diff --git a/unit-tests/test-cases/absolute-symbol/main.c b/unit-tests/test-cases/absolute-symbol/main.c
new file mode 100644 (file)
index 0000000..eec3f61
--- /dev/null
@@ -0,0 +1,5 @@
+
+extern int* myAbs;
+
+int main() { return *myAbs; }
+
diff --git a/unit-tests/test-cases/alias-command-line/Makefile b/unit-tests/test-cases/alias-command-line/Makefile
new file mode 100644 (file)
index 0000000..9e87329
--- /dev/null
@@ -0,0 +1,53 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is to verify that added aliases to a .o
+# file via the command line is the same as doing so in the sources.
+# The ObjectDump utility is used
+# dump a "canonical" textual representation of a .o file.
+# The before and after .o files are then diff'ed.
+# No differences means this test passes
+#
+
+run: all
+
+all:
+       ${CC} ${ASMFLAGS} aliases.s -DALIASES=1 -c -o aliases.source.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content -no_sort aliases.source.${ARCH}.o > aliases.source.${ARCH}.o.dump
+
+       ${CC} ${ASMFLAGS} aliases.s -c -o aliases.tmp.${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} aliases.tmp.${ARCH}.o
+
+       ${LD} -arch ${ARCH} -r aliases.tmp.${ARCH}.o -alias _foo _fooalt -alias _foo _fooalt2 -o aliases.cmdline.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content -no_sort aliases.cmdline.${ARCH}.o > aliases.cmdline.${ARCH}.o.dump
+       ${FAIL_IF_ERROR} diff aliases.source.${ARCH}.o.dump  aliases.cmdline.${ARCH}.o.dump
+
+       ${LD} -arch ${ARCH} -r aliases.tmp.${ARCH}.o -alias_list aliases.txt -o aliases.file.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content -no_sort aliases.file.${ARCH}.o > aliases.file.${ARCH}.o.dump
+       ${PASS_IFF} diff aliases.source.${ARCH}.o.dump  aliases.file.${ARCH}.o.dump
+       
+clean:
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/alias-command-line/aliases.s b/unit-tests/test-cases/alias-command-line/aliases.s
new file mode 100644 (file)
index 0000000..ffab4a9
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+       .text
+
+_temp: nop
+               nop
+               
+               .globl _foo
+_foo:  nop
+               nop
+
+#if ALIASES
+               .globl _fooalt
+               .globl _fooalt2
+/* this should make an alias "_fooalt" for "_foo" */
+_fooalt = _foo 
+_fooalt2 = _foo        
+#endif
+
+_bar:  nop
+               nop
+               
+               
+               .subsections_via_symbols
\ No newline at end of file
diff --git a/unit-tests/test-cases/alias-command-line/aliases.txt b/unit-tests/test-cases/alias-command-line/aliases.txt
new file mode 100644 (file)
index 0000000..291f2f7
--- /dev/null
@@ -0,0 +1,6 @@
+_foo           _fooalt 
+# comment
+_foo   _fooalt2
+
+
+
diff --git a/unit-tests/test-cases/alias-objects/Makefile b/unit-tests/test-cases/alias-objects/Makefile
new file mode 100644 (file)
index 0000000..f4bfdc8
--- /dev/null
@@ -0,0 +1,44 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is to verify a .o file with aliases 
+# can round trip through ld -r correctly.  The ObjectDump utility is used
+# dump a "canonical" textual representation of a .o file.
+# The before and after .o files are then diff'ed.
+# No differences means this test passes
+#
+
+run: all
+
+all:
+       ${CC} ${ASMFLAGS} aliases.s -c -o aliases.${ARCH}.o
+       ${LD} -arch ${ARCH} -r -keep_private_externs aliases.${ARCH}.o -o aliases-r.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content -no_sort aliases.${ARCH}.o > aliases.${ARCH}.o.dump
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content -no_sort aliases-r.${ARCH}.o > aliases-r.${ARCH}.o.dump
+       ${PASS_IFF} diff aliases.${ARCH}.o.dump aliases-r.${ARCH}.o.dump
+
+clean:
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/alias-objects/aliases.s b/unit-tests/test-cases/alias-objects/aliases.s
new file mode 100644 (file)
index 0000000..b21f8c7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+       .text
+
+_temp: nop
+               nop
+               
+               .globl _foo
+_foo:  nop
+               nop
+
+               .globl _fooalt
+               .globl _fooalt2
+/* this should make an alias "_fooalt" for "_foo" */
+_fooalt = _foo 
+_fooalt2 = _foo        
+
+_bar:  nop
+               nop
+               
+               
+               .subsections_via_symbols
\ No newline at end of file
index bf79c29f3f6c23fa79eb48b3af240604ae54fafe..6b6a50f431c4558810874ec51823081355ab318e 100644 (file)
@@ -33,11 +33,8 @@ run: all
 
 all:
        ${CC} ${ASMFLAGS} -dynamiclib -single_module -dead_strip foo.c align.s  -exported_symbols_list foo.exp -o foo.${ARCH}.dylib
+       ${FAIL_IF_BAD_MACHO} foo.${ARCH}.dylib
        nm foo.${ARCH}.dylib | grep "3 d _b" | ${PASS_IFF_STDIN}
 
-
 clean:
-       rm -rf foo.${ARCH}.dylib 
-       
-       
-
+       rm -rf *.dylib 
diff --git a/unit-tests/test-cases/align-modulus/comment.txt b/unit-tests/test-cases/align-modulus/comment.txt
new file mode 100644 (file)
index 0000000..240c171
--- /dev/null
@@ -0,0 +1,2 @@
+The point of this test is to verify that the modules of symbol _b is maintained.  The address for _b must be
+3 mod 16.  Therefore the last hexdigit of the address must be 3.
index 9c2aaba841d2006a4e6d2189f8bbea5ead7e72f2..6e0be3f8d1d07a450bdc55eb384f5c884712e13d 100644 (file)
@@ -43,4 +43,4 @@ all:
        ${OTOOL} -hv foo-${ARCH} | grep ALLOW_STACK_EXECUTION | ${PASS_IFF_EMPTY}
 
 clean:
-       rm -rf foo-${ARCH}
+       rm -rf foo-*
diff --git a/unit-tests/test-cases/allow-stack-execute/comment.txt b/unit-tests/test-cases/allow-stack-execute/comment.txt
new file mode 100644 (file)
index 0000000..525ab2b
--- /dev/null
@@ -0,0 +1 @@
+Test the we set the stack execution bit properly.
index 88e215bdeff57b598542e67f644d1e092454f630..ef293a63743baaf599ad16d177b21f63730d008d 100644 (file)
@@ -46,16 +46,21 @@ all:
 
 # test that second -o works
        ${CC} ${CCFLAGS} -dynamiclib baz.c -o libbaz.${ARCH}.dylib foo.${ARCH}.dylib
+       ${FAIL_IF_BAD_MACHO} foo.${ARCH}.dylib
 
 # test that -o and -install_name works with install_name as an allowable
        ${CC} ${CCFLAGS} -dynamiclib bar.c -o temp.${ARCH}.dylib -install_name /tmp/libbar.${ARCH}.dylib foo.${ARCH}.dylib
        ${FAIL_IF_BAD_MACHO} temp.${ARCH}.dylib
 
+# test that -install_name works with variant name
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o temp.${ARCH}.dylib -install_name /tmp/libbar_profile foo.${ARCH}.dylib
+       ${FAIL_IF_BAD_MACHO} temp.${ARCH}.dylib
+
 # test that -o and -install_name fails with install_name different than allowable
-###    ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} -dynamiclib bar.c -o bar.${ARCH}.dylib -install_name /tmp/fail.${ARCH}.dylib foo.${ARCH}.dylib >& fail.log
+       ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} -dynamiclib bar.c -o bar.${ARCH}.dylib -install_name /tmp/fail.${ARCH}.dylib foo.${ARCH}.dylib >& fail.log
 
 # test that a bundle and no client_name fails
-###    ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} -bundle bar.c -o temp.${ARCH}.bundle foo.${ARCH}.dylib >& fail.log
+       ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} -bundle bar.c -o temp.${ARCH}.bundle foo.${ARCH}.dylib >& fail.log
 
 # test that a bundle and an allowable client_name passes
        ${CC} ${CCFLAGS} -bundle bar.c -client_name bar -o bar.${ARCH}.bundle foo.${ARCH}.dylib
@@ -66,6 +71,11 @@ all:
        ${CC} ${CCFLAGS} -dynamiclib foo.${ARCH}.dylib -o foo.framework/foo
        ${FAIL_IF_BAD_MACHO} foo.framework/foo
 
+# test umbrella variant can link against subs
+       mkdir -p foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib foo.${ARCH}.dylib -o foo.framework/foo_debug -install_name /path/foo.framework/foo_debug
+       ${FAIL_IF_BAD_MACHO} foo.framework/foo_debug
+
 # test sibling in umbrella can link against subs
        ${CC} ${CCFLAGS} -dynamiclib main.c -umbrella foo foo.${ARCH}.dylib -o ./main.dylib
        ${FAIL_IF_BAD_MACHO} main.dylib
@@ -75,16 +85,26 @@ all:
        ${FAIL_IF_BAD_MACHO} main.${ARCH}
 
 # test that an executable and no client_name fails
-###    ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} main.c -o main.${ARCH} foo.${ARCH}.dylib >& fail.log
+       ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} main.c -o main.${ARCH} foo.${ARCH}.dylib >& fail.log
 
 # test that an executable and an allowable client_name passes
-#      ${CC} ${CCFLAGS} main.c -o main.${ARCH} -client_name bar foo.${ARCH}.dylib
-#      ${PASS_IFF_GOOD_MACHO} main.${ARCH}
+       ${CC} ${CCFLAGS} main.c -o main.${ARCH} -client_name bar foo.${ARCH}.dylib
+       ${PASS_IFF_GOOD_MACHO} main.${ARCH}
 
+# test that a regular dylib can be made unlinkable by using -allowable_client
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -allowable_client '!' -o unlinkable_foo.${ARCH}.dylib
+       ${FAIL_IF_BAD_MACHO} unlinkable_foo.${ARCH}.dylib
+       ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} main.c -o main.${ARCH} unlinkable_foo.${ARCH}.dylib >& fail.log
+       
+# test that a regular dylib can be made linkable by only specially named clients
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -allowable_client special -o restrictive_foo.${ARCH}.dylib
+       ${FAIL_IF_BAD_MACHO} restrictive_foo.${ARCH}.dylib
+       ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} main.c -o main.${ARCH} restrictive_foo.${ARCH}.dylib >& fail.log
+       ${CC} ${CCFLAGS} main.c -o main.${ARCH} -client_name special restrictive_foo.${ARCH}.dylib
+       ${FAIL_IF_BAD_MACHO} main.${ARCH}
        
 # print final pass
        ${PASS_IFF_GOOD_MACHO} foo.${ARCH}.dylib
        
 clean:
-
-       rm -rf *.${ARCH}.dylib *.${ARCH}.bundle main.${ARCH} fail.log foo.framework bar.framework main.dylib
+       rm -rf *.dylib *.bundle main.???* fail.log *.framework
diff --git a/unit-tests/test-cases/allowable-client/comment.txt b/unit-tests/test-cases/allowable-client/comment.txt
new file mode 100644 (file)
index 0000000..0202b5f
--- /dev/null
@@ -0,0 +1 @@
+Test that the -allowable_client and -client options work when linking against subframeworks.
diff --git a/unit-tests/test-cases/archive-ObjC/Makefile b/unit-tests/test-cases/archive-ObjC/Makefile
new file mode 100644 (file)
index 0000000..f5e0e24
--- /dev/null
@@ -0,0 +1,49 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is to check that -ObjC loads all (and only)
+# .o files that contain Objective-C code.
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} foo.m -c -o foo-${ARCH}.o 
+       ${FAIL_IF_BAD_OBJ} foo-${ARCH}.o
+       ${CC} ${CCFLAGS} bar.c -c -o bar-${ARCH}.o 
+       ${FAIL_IF_BAD_OBJ} bar-${ARCH}.o
+       ${CC} ${CCFLAGS} baz.m -c -o baz-${ARCH}.o 
+       ${FAIL_IF_BAD_OBJ} baz-${ARCH}.o
+       libtool -static foo-${ARCH}.o bar-${ARCH}.o baz-${ARCH}.o -o libfoobarbaz-${ARCH}.a
+       ${CC} ${CCFLAGS} main.c -lfoobarbaz-${ARCH} -L. -o main-${ARCH} -ObjC -framework Foundation
+       ${FAIL_IF_BAD_MACHO} main-${ARCH}
+       nm main-${ARCH} | grep "_bar" | ${FAIL_IF_STDIN}
+       nm main-${ARCH} | grep "_Foo" | ${FAIL_IF_EMPTY}
+       nm main-${ARCH} | grep "_Baz" | ${FAIL_IF_EMPTY}
+       ${PASS_IFF_GOOD_MACHO} main-${ARCH}
+
+clean:
+       rm -rf main-* *.o *.a
diff --git a/unit-tests/test-cases/archive-ObjC/bar.c b/unit-tests/test-cases/archive-ObjC/bar.c
new file mode 100644 (file)
index 0000000..d9b468b
--- /dev/null
@@ -0,0 +1,2 @@
+
+int bar() { return 0; }
diff --git a/unit-tests/test-cases/archive-ObjC/baz.m b/unit-tests/test-cases/archive-ObjC/baz.m
new file mode 100644 (file)
index 0000000..90ae0a1
--- /dev/null
@@ -0,0 +1,8 @@
+#include <Foundation/Foundation.h>
+
+@interface Baz : NSObject
+@end
+
+@implementation Baz
+@end
+
diff --git a/unit-tests/test-cases/archive-ObjC/foo.m b/unit-tests/test-cases/archive-ObjC/foo.m
new file mode 100644 (file)
index 0000000..acba7a4
--- /dev/null
@@ -0,0 +1,8 @@
+#include <Foundation/Foundation.h>
+
+@interface Foo : NSObject
+@end
+
+@implementation Foo
+@end
+
diff --git a/unit-tests/test-cases/archive-ObjC/main.c b/unit-tests/test-cases/archive-ObjC/main.c
new file mode 100644 (file)
index 0000000..dc2fbef
--- /dev/null
@@ -0,0 +1,31 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+
+int main()
+{
+       fprintf(stdout, "hello\n");
+       return 0;
+}
index 721cf2a3f84a6bb7a971fbabcd268e5934ddd0b5..39c0ef97da378cfaab3a36a135dcdb6f5938dc61 100644 (file)
@@ -32,7 +32,9 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} foo.c -c -o foo-${ARCH}.o 
+       ${FAIL_IF_BAD_OBJ} foo-${ARCH}.o
        ${CC} ${CCFLAGS} bar.c -c -o bar-${ARCH}.o 
+       ${FAIL_IF_BAD_OBJ} bar-${ARCH}.o
        libtool -static foo-${ARCH}.o  bar-${ARCH}.o -o libfoobar-${ARCH}.a
        ${CC} ${CCFLAGS} main.c -lfoobar-${ARCH} -L. -o main-${ARCH} 
        ${FAIL_IF_BAD_MACHO} main-${ARCH}
@@ -41,6 +43,4 @@ all:
        ${FAIL_IF_BAD_MACHO} main-${ARCH}
 
 clean:
-       rm -rf main-${ARCH} foo-${ARCH}.o bar-${ARCH}.o libfoobar-${ARCH}.a
-       
-
+       rm -rf main-* *.o *.a
diff --git a/unit-tests/test-cases/archive-basic/comment.txt b/unit-tests/test-cases/archive-basic/comment.txt
new file mode 100644 (file)
index 0000000..0d34170
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that .o files can be found in archives.
diff --git a/unit-tests/test-cases/archive-duplicate/Makefile b/unit-tests/test-cases/archive-duplicate/Makefile
new file mode 100644 (file)
index 0000000..61f4bc7
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ia an archive
+# is listed multiple times, the extras are ignored.
+# This is done in some makefiles because the traditional linker
+# semantics is to only search an archive once.
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} foo.c -c -o foo-${ARCH}.o 
+       ${CC} ${CCFLAGS} bar.c -c -o bar-${ARCH}.o 
+       libtool -static foo-${ARCH}.o  bar-${ARCH}.o -o libfoobar-${ARCH}.a
+       ${CC} ${CCFLAGS} main.c -lfoobar-${ARCH} -lfoobar-${ARCH} -L. -o main-${ARCH} -all_load
+       ${FAIL_IF_BAD_MACHO} main-${ARCH}
+       ${CC} ${CCFLAGS} main.c ./libfoobar-${ARCH}.a ./libfoobar-${ARCH}.a -L. -o main-${ARCH} -all_load
+       ${PASS_IFF_GOOD_MACHO} main-${ARCH}
+
+clean:
+       rm -rf main-* *.o *.a
diff --git a/unit-tests/test-cases/archive-duplicate/bar.c b/unit-tests/test-cases/archive-duplicate/bar.c
new file mode 100644 (file)
index 0000000..7fe6403
--- /dev/null
@@ -0,0 +1 @@
+int bar() { return 0; }
diff --git a/unit-tests/test-cases/archive-duplicate/foo.c b/unit-tests/test-cases/archive-duplicate/foo.c
new file mode 100644 (file)
index 0000000..a60f28c
--- /dev/null
@@ -0,0 +1 @@
+int foo() { return 1; }
diff --git a/unit-tests/test-cases/archive-duplicate/main.c b/unit-tests/test-cases/archive-duplicate/main.c
new file mode 100644 (file)
index 0000000..57c4c68
--- /dev/null
@@ -0,0 +1,32 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+extern int foo();
+
+int main()
+{
+       fprintf(stdout, "hello\n");
+       return foo();
+}
\ No newline at end of file
index 676d1a4656c3ef9d76418180b0474a7b07d24afe..2d53734ee7f42c3e553c2552a9ded47f1ac80691 100644 (file)
@@ -37,14 +37,15 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} foo.c -c -o foo-${ARCH}.o 
+       ${FAIL_IF_BAD_OBJ} foo-${ARCH}.o
        ${CC} ${CCFLAGS} bar.c -c -o bar-${ARCH}.o 
+       ${FAIL_IF_BAD_OBJ} bar-${ARCH}.o
        ${CC} ${CCFLAGS} baz.c -c -o baz-${ARCH}.o 
+       ${FAIL_IF_BAD_OBJ} baz-${ARCH}.o
        libtool -static foo-${ARCH}.o  bar-${ARCH}.o  baz-${ARCH}.o -o libfoobar-${ARCH}.a
        ${CC} ${CCFLAGS} main.c foo.c -lfoobar-${ARCH} -L. -o main-${ARCH} 
        ${FAIL_IF_BAD_MACHO} main-${ARCH}
        nm -m main-${ARCH} | grep _baz | grep weak | ${PASS_IFF_STDIN}
 
 clean:
-       rm -rf main-${ARCH} foo-${ARCH}.o bar-${ARCH}.o baz-${ARCH}.o libfoobar-${ARCH}.a
-       
-
+       rm -rf main-* *.o *.a
diff --git a/unit-tests/test-cases/archive-weak/comment.txt b/unit-tests/test-cases/archive-weak/comment.txt
new file mode 100644 (file)
index 0000000..902d22c
--- /dev/null
@@ -0,0 +1,7 @@
+The point of this test if the linker already has a weak definition
+it does not try to find another copy in an archive
+
+There are two case to test:
+1) both the main .o files and the archive have the same weak symbol (_foo)
+2) main.o has a weak symbol and the archive has a non-weak symbol (_baz)
+In both cases the linker should ignore the archive. 
index e5caa646e300f7e4a090be473e03a1f115a23a19..3c8b3e5d585b3e8cca26b54ed99fba6b5ed39a8c 100644 (file)
@@ -35,11 +35,10 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} hello.c -c -o hello.o  -mmacosx-version-min=10.4
-       ${LD} -lcrt1.o hello.o -o hello -lSystem 2> fail.log
-       ${FAIL_IF_BAD_MACHO} hello
-       file hello | grep ${ARCH} | ${PASS_IFF_STDIN}
+       ${FAIL_IF_BAD_OBJ} hello.o
+       ${LD} -r -lcrt1.o hello.o -o hello-r.o -lSystem
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} hello-r.o >/dev/null
+       file hello-r.o | grep ${ARCH} | ${PASS_IFF_STDIN}
 
 clean:
-       rm  hello.o hello fail.log
-       
-
+       rm -rf *.o
diff --git a/unit-tests/test-cases/auto-arch2/Makefile b/unit-tests/test-cases/auto-arch2/Makefile
new file mode 100644 (file)
index 0000000..a6f2520
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+#
+# The point of this test is a check that ld
+# can figure out which architecture is needed 
+# by looking at the .o files when -arch is not used.
+#
+
+run: all
+
+
+all:
+       ${CC} ${CCFLAGS} hello.c -c -o hello-${ARCH}.o -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_OBJ} hello-${ARCH}.o
+       ${FAIL_IF_ERROR} ${LD} -r -lcrt1.o hello-${ARCH}.o -o hello-r.o -lSystem
+       ${FAIL_IF_ERROR} ObjectDump hello-r.o >/dev/null
+       file hello-r.o | grep ${ARCH} | ${PASS_IFF_STDIN}
+
+clean:
+       rm -f *.o
diff --git a/unit-tests/test-cases/auto-arch2/comment.txt b/unit-tests/test-cases/auto-arch2/comment.txt
new file mode 100644 (file)
index 0000000..ed107a9
--- /dev/null
@@ -0,0 +1,3 @@
+The point of this test is a check that ld
+can figure out which architecture is needed 
+by looking at the .o files when -arch is not used.
diff --git a/unit-tests/test-cases/auto-arch2/hello.c b/unit-tests/test-cases/auto-arch2/hello.c
new file mode 100644 (file)
index 0000000..14d9363
--- /dev/null
@@ -0,0 +1,29 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+int main()
+{
+       fprintf(stdout, "hello\n");
+}
index 514fd8b30f2e15f44ace85ea71ac25295a1f8c6d..b99e0858ced6054df4781f11963362902e8fa172 100644 (file)
@@ -34,8 +34,24 @@ run: all
 
 all:
 # build example fully fat dylib
-       ${CC} `echo ${ALL_ARCH_OPTIONS}` -dynamiclib foo.c -o libfoo.dylib -install_name libfoo.dylib
-       lipo libfoo.dylib -remove ${ARCH} -output libfoo.dylib
+
+       gcc `echo ${ALL_ARCH_OPTIONS}` -dynamiclib foo.c -o libfoo.dylib -install_name libfoo.dylib
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       # handle the case of a native ppc compile--this sets the subtype, which must be passed to lipo
+       if [ x${ARCH} != xppc ]; \
+       then \
+               SUB_ARCH=${ARCH}; \
+       else \
+               SUB_ARCH=`lipo -info libfoo.dylib | sed 's/.*://;s/ppc64 //;s/.* \(ppc[^ ]*\).*/\1/'`; \
+               echo SUB_ARCH $$SUB_ARCH; \
+               if [ x$$SUB_ARCH = xALL ]; \
+               then \
+                       SUB_ARCH=ppc; \
+               fi \
+       fi; \
+       lipo libfoo.dylib -remove $$SUB_ARCH -output libfoo.dylib
+
        lipo -create libfoo.dylib -arch_blank ${ARCH} -output libfoo.dylib
        ${CC} ${CCFLAGS} main.c libfoo.dylib -o main
        ${OTOOL} -L main | grep libfoo | ${FAIL_IF_STDIN}
@@ -43,5 +59,4 @@ all:
        
 
 clean:
-       rm -rf libfoo.dylib main
-       
\ No newline at end of file
+       rm -rf *.dylib main
diff --git a/unit-tests/test-cases/blank-stubs/comment.txt b/unit-tests/test-cases/blank-stubs/comment.txt
new file mode 100644 (file)
index 0000000..77a8764
--- /dev/null
@@ -0,0 +1 @@
+Test that blank stubs are handled properly
index 3b31968ec8b3e8f65636bf77a381515e4731c2d4..c0163d03db579d9eb6df2bced31ae15d1e8156cf 100644 (file)
@@ -32,12 +32,12 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
        ${CC} ${CCFLAGS} main.c bar.c -o main
+       ${FAIL_IF_BAD_MACHO} main
        ${CC} ${CCFLAGS} bundle.c -bundle -bundle_loader main libbar.dylib -o bundle.bundle
        ${FAIL_IF_BAD_MACHO} bundle.bundle
        nm -m bundle.bundle | grep _bar | grep "from executable" | ${PASS_IFF_STDIN}
 
 clean:
-       rm libbar.dylib main bundle.bundle
-       
-
+       rm *.dylib main bundle.bundle
diff --git a/unit-tests/test-cases/bundle_loader/comment.txt b/unit-tests/test-cases/bundle_loader/comment.txt
new file mode 100644 (file)
index 0000000..e406042
--- /dev/null
@@ -0,0 +1,3 @@
+The point of this test is a sanity check that ld
+-bundle_loader works, and _bar is found in the executable
+and not in libbar.dylib
diff --git a/unit-tests/test-cases/commons-alignment/Makefile b/unit-tests/test-cases/commons-alignment/Makefile
new file mode 100644 (file)
index 0000000..d073c0e
--- /dev/null
@@ -0,0 +1,37 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Validate linker preserves commons with custom alignment
+#
+
+all:
+       ${CC} ${CCFLAGS} foo.s -c -o foo.o
+       nm -m foo.o | grep '(alignment 2^6)'  | ${FAIL_IF_EMPTY}
+       ${LD} foo.o -r -o foo2.o
+       nm -m foo2.o | grep '(alignment 2^6)' | ${PASS_IFF_STDIN}
+       
+clean:
+       rm -rf foo.o foo2.o
diff --git a/unit-tests/test-cases/commons-alignment/foo.s b/unit-tests/test-cases/commons-alignment/foo.s
new file mode 100644 (file)
index 0000000..03c28fc
--- /dev/null
@@ -0,0 +1,2 @@
+
+  .comm _mycomm64aligned,15,6
diff --git a/unit-tests/test-cases/commons-coalesced-dead_strip/Makefile b/unit-tests/test-cases/commons-coalesced-dead_strip/Makefile
new file mode 100644 (file)
index 0000000..5823a61
--- /dev/null
@@ -0,0 +1,42 @@
+##
+# Copyright (c) 2007 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
+
+
+#
+# The point of this test is to verify if a header file is missing an extern that there won't be
+# duplicates definitions when using -dead_strip.
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} a.c -c -o a.o
+       ${CC} ${CCFLAGS} b.c -c -o b.o
+       ${CC} ${CCFLAGS} c.c -c -o c.o
+       ${CC} -arch ${ARCH} -dynamiclib a.o b.o c.o -o libabc.dylib -dead_strip
+       ${PASS_IFF_GOOD_MACHO} libabc.dylib
+
+clean:
+       rm -rf a.o b.o c.o libabc.dylib one  abc.bar.count
diff --git a/unit-tests/test-cases/commons-coalesced-dead_strip/a.c b/unit-tests/test-cases/commons-coalesced-dead_strip/a.c
new file mode 100644 (file)
index 0000000..fea7234
--- /dev/null
@@ -0,0 +1,4 @@
+#include "c.h"
+
+float aa() { return bar; }
+
diff --git a/unit-tests/test-cases/commons-coalesced-dead_strip/b.c b/unit-tests/test-cases/commons-coalesced-dead_strip/b.c
new file mode 100644 (file)
index 0000000..12e46e8
--- /dev/null
@@ -0,0 +1,4 @@
+#include "c.h"
+
+float bb() { return bar; }
+
diff --git a/unit-tests/test-cases/commons-coalesced-dead_strip/c.c b/unit-tests/test-cases/commons-coalesced-dead_strip/c.c
new file mode 100644 (file)
index 0000000..165d5e4
--- /dev/null
@@ -0,0 +1,3 @@
+
+const float bar = 1.0;
+
diff --git a/unit-tests/test-cases/commons-coalesced-dead_strip/c.h b/unit-tests/test-cases/commons-coalesced-dead_strip/c.h
new file mode 100644 (file)
index 0000000..86a61ae
--- /dev/null
@@ -0,0 +1,4 @@
+
+// missing extern
+const float bar;
+
diff --git a/unit-tests/test-cases/commons-mixed/Makefile b/unit-tests/test-cases/commons-mixed/Makefile
new file mode 100644 (file)
index 0000000..a59a858
--- /dev/null
@@ -0,0 +1,46 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+#
+# The point of this test is to verify a .o built with
+# commons and one built without commons can be merged.
+#
+# <rdar://problem/4743925> problem merging .o files built with and without -fno-common
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} foo.c -c -o foo.${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} foo.${ARCH}.o
+       ${CC} ${CCFLAGS} bar.c -c -fno-common -o bar.${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} bar.${ARCH}.o
+       ${LD} -arch ${ARCH} -r -keep_private_externs foo.${ARCH}.o  bar.${ARCH}.o -o foobar.${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} foobar.${ARCH}.o
+       nm -m foobar.${ARCH}.o | grep bar | grep __common | ${PASS_IFF_STDIN}
+
+clean:
+       rm -rf *.o
diff --git a/unit-tests/test-cases/commons-mixed/bar.c b/unit-tests/test-cases/commons-mixed/bar.c
new file mode 100644 (file)
index 0000000..771802c
--- /dev/null
@@ -0,0 +1,2 @@
+
+int bar;
diff --git a/unit-tests/test-cases/commons-mixed/foo.c b/unit-tests/test-cases/commons-mixed/foo.c
new file mode 100644 (file)
index 0000000..42e0a8e
--- /dev/null
@@ -0,0 +1,2 @@
+
+int foo;
diff --git a/unit-tests/test-cases/commons-order/Makefile b/unit-tests/test-cases/commons-order/Makefile
new file mode 100644 (file)
index 0000000..68e282d
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Validate linker puts commons in the correct order.
+# -fno-commons come first, followed by all other commons
+# in .o order and alphabetically within each .o
+#
+
+all:
+       ${CC} baz.c -fno-common -c -o baz.o
+       ${CC} ${CCFLAGS} main.c foo.c bar.c baz.o -o main -mmacosx-version-min=10.5
+       nm -j -n main | grep _common > symbol.order
+       ${FAIL_IF_ERROR} diff symbol.order expected.order
+       ${PASS_IFF_GOOD_MACHO} main
+       
+clean:
+       rm -rf main baz.o symbol.order
diff --git a/unit-tests/test-cases/commons-order/bar.c b/unit-tests/test-cases/commons-order/bar.c
new file mode 100644 (file)
index 0000000..2d258fc
--- /dev/null
@@ -0,0 +1,3 @@
+int ddd_common;
+int iii_common[4];
+int bbb_common[4];
diff --git a/unit-tests/test-cases/commons-order/baz.c b/unit-tests/test-cases/commons-order/baz.c
new file mode 100644 (file)
index 0000000..6497d29
--- /dev/null
@@ -0,0 +1,3 @@
+int fff_common;
+int iii_common[4];
+int ttt_common;
diff --git a/unit-tests/test-cases/commons-order/expected.order b/unit-tests/test-cases/commons-order/expected.order
new file mode 100644 (file)
index 0000000..4738fc2
--- /dev/null
@@ -0,0 +1,8 @@
+_fff_common
+_iii_common
+_ttt_common
+_aaa_common
+_eee_common
+_ggg_common
+_bbb_common
+_ddd_common
diff --git a/unit-tests/test-cases/commons-order/foo.c b/unit-tests/test-cases/commons-order/foo.c
new file mode 100644 (file)
index 0000000..ca80a59
--- /dev/null
@@ -0,0 +1,3 @@
+int aaa_common;
+int ggg_common[4];
+int eee_common;
diff --git a/unit-tests/test-cases/commons-order/main.c b/unit-tests/test-cases/commons-order/main.c
new file mode 100644 (file)
index 0000000..df77448
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+int main() { return 0; }
+
diff --git a/unit-tests/test-cases/cpu-sub-types/Makefile b/unit-tests/test-cases/cpu-sub-types/Makefile
new file mode 100644 (file)
index 0000000..50f05e9
--- /dev/null
@@ -0,0 +1,91 @@
+##
+# Copyright (c) 2007 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
+
+#
+# The point of this test is validate cpu subtypes processing
+#
+
+test: test-${ARCH}
+
+test-ppc64:
+       ${PASS_IFF} true
+
+test-i386:
+       ${PASS_IFF} true
+
+test-x86_64:
+       ${PASS_IFF} true
+
+test-ppc:
+       gcc foo.c -arch ppc     -mmacosx-version-min=10.4 -c -o foo.o
+       ${FAIL_IF_BAD_OBJ} foo.o
+       gcc foo.c -arch ppc750  -mmacosx-version-min=10.4 -c -o foo-G3.o
+       ${FAIL_IF_BAD_OBJ} foo-G3.o
+       gcc foo.c -arch ppc7400 -mmacosx-version-min=10.4 -c -o foo-G4.o
+       ${FAIL_IF_BAD_OBJ} foo-G4.o
+       gcc foo.c -arch ppc970  -mmacosx-version-min=10.4 -c -o foo-G5.o
+       ${FAIL_IF_BAD_OBJ} foo-G5.o
+       gcc main.c -arch ppc    -mmacosx-version-min=10.4 -c -o main.o
+       ${FAIL_IF_BAD_OBJ} main.o
+       gcc main.c -arch ppc970 -mmacosx-version-min=10.4 -c -o main-G5.o
+       ${FAIL_IF_BAD_OBJ} main-G5.o
+
+       # check ALL+ALL -> ALL
+       ${LD} -r main.o foo.o -o main-r.o
+       ${FAIL_IF_BAD_OBJ} main-r.o
+       otool -hv main-r.o | grep ALL | ${FAIL_IF_EMPTY}
+
+       # check G3+ALL -> G3
+       ${LD} -r main.o foo-G3.o -o main-r.o
+       ${FAIL_IF_BAD_OBJ} main-r.o
+       otool -hv main-r.o | grep ppc750 | ${FAIL_IF_EMPTY}
+
+       # check G4+ALL -> G4
+       ${LD} -r main.o foo-G4.o -o main-r.o
+       ${FAIL_IF_BAD_OBJ} main-r.o
+       otool -hv main-r.o | grep ppc7400 | ${FAIL_IF_EMPTY}
+
+       # check G5+ALL -> G5
+       ${LD} -r main.o foo-G5.o -o main-r.o
+       ${FAIL_IF_BAD_OBJ} main-r.o
+       otool -hv main-r.o | grep ppc970 | ${FAIL_IF_EMPTY}
+
+       # check G5+G4 -> G5
+       ${LD} -r main-G5.o foo-G4.o -o main-r.o
+       ${FAIL_IF_BAD_OBJ} main-r.o
+       otool -hv main-r.o | grep ppc970 | ${FAIL_IF_EMPTY}
+
+       # check G4+G5 -> G5
+       ${LD} -r foo-G4.o main-G5.o -o main-r.o
+       ${FAIL_IF_BAD_OBJ} main-r.o
+       otool -hv main-r.o | grep ppc970 | ${FAIL_IF_EMPTY}
+
+       # check -force_cpusubtype_ALL
+       ${LD} -r main.o foo-G5.o -o main-r.o -force_cpusubtype_ALL
+       ${FAIL_IF_BAD_OBJ} main-r.o
+       otool -hv main-r.o | grep ALL | ${PASS_IFF_STDIN}
+
+clean:
+       rm -f *.o
diff --git a/unit-tests/test-cases/cpu-sub-types/comment.txt b/unit-tests/test-cases/cpu-sub-types/comment.txt
new file mode 100644 (file)
index 0000000..5e47ece
--- /dev/null
@@ -0,0 +1,2 @@
+The point of this test is validate cpu subtypes processsing for PowerPC
+
diff --git a/unit-tests/test-cases/cpu-sub-types/foo.c b/unit-tests/test-cases/cpu-sub-types/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/cpu-sub-types/main.c b/unit-tests/test-cases/cpu-sub-types/main.c
new file mode 100644 (file)
index 0000000..b48076d
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+extern void foo();
+extern void bar();
+
+int main()
+{
+       foo();
+       return 0;
+}
diff --git a/unit-tests/test-cases/dead_strip-archive-global/Makefile b/unit-tests/test-cases/dead_strip-archive-global/Makefile
new file mode 100644 (file)
index 0000000..ef985b7
--- /dev/null
@@ -0,0 +1,43 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# Tests that a global symbol in an archive will stil be exported (and not dead stripped).
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} foo.c -c -o foo.o
+       ${FAIL_IF_BAD_OBJ} foo.o
+       libtool -static foo.o -o libfoo.a
+       ${CC} ${CCFLAGS}  main.c -dynamiclib -Os libfoo.a -dead_strip -o libmain.dylib
+       nm libmain.dylib | grep _bar | ${FAIL_IF_EMPTY}
+       nm libmain.dylib | grep _baz | ${FAIL_IF_STDIN}
+       ${PASS_IFF_GOOD_MACHO} libmain.dylib
+       
+
+clean:
+       rm -rf *.dylib *.a *.o
diff --git a/unit-tests/test-cases/dead_strip-archive-global/foo.c b/unit-tests/test-cases/dead_strip-archive-global/foo.c
new file mode 100644 (file)
index 0000000..41478e8
--- /dev/null
@@ -0,0 +1,12 @@
+
+static int foo_count = 0;
+static int bar_count = 0;
+static int baz_count = 0;
+
+
+void foo() { ++foo_count; }
+
+void bar() { ++bar_count; }
+
+void __attribute__((visibility("hidden"))) 
+       baz() { ++baz_count; }
diff --git a/unit-tests/test-cases/dead_strip-archive-global/main.c b/unit-tests/test-cases/dead_strip-archive-global/main.c
new file mode 100644 (file)
index 0000000..da2b2fd
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+extern void foo();
+
+int main()
+{
+       foo();
+       return 0;
+}
+
+
index c2e66c0c31e19322674582dd89ebf90118e42f70..1542d788c1cad06150fd6ae29ef10e71dfc59c3d 100644 (file)
@@ -24,20 +24,20 @@ TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
 #
-# The point of this test that -dead_strip removes unreference code/data from archives
+# Tests that a common symbol can be used from an archive with -dead_strip.  The tricky
+# part is that common symbols are not in the table of contents for archives.
+# If the linker seens a need for my_common, that won't trigger pulling in the .o
+# file from the archive.  But the later use of foo will.  
 #
 
 run: all
 
 all:
        ${CC} ${CCFLAGS} foo.c -c -o foo.o
+       ${FAIL_IF_BAD_OBJ} foo.o
        libtool -static foo.o -o libfoo.a
        ${CC} ${CCFLAGS}  main.c -mdynamic-no-pic -Os libfoo.a -dead_strip -o main
-       ${FAIL_IF_BAD_MACHO} main
-       nm -j  main | grep dead_wood | ${PASS_IFF_EMPTY}
-       
+       ${PASS_IFF_GOOD_MACHO} main
 
 clean:
-       rm -rf  main libfoo.a foo.o
-       
-
+       rm -rf main *.a *.o
diff --git a/unit-tests/test-cases/dead_strip-archive/comment.txt b/unit-tests/test-cases/dead_strip-archive/comment.txt
new file mode 100644 (file)
index 0000000..8dde1c5
--- /dev/null
@@ -0,0 +1 @@
+The point of this test that -dead_strip removes unreference code/data from archives
index 5985e96f0e4d761a7f6a30c868fd186b81f1e6dc..32ac1c5d817b7563c3dacf52bed409e7104b8fff 100644 (file)
@@ -44,9 +44,6 @@ all:
        ${FAIL_IF_BAD_MACHO} dylib2-${ARCH}
        nm -j dylib2-${ARCH} | grep dead_door_knob | ${FAIL_IF_EMPTY}
        nm -j dylib2-${ARCH} | grep deadwood | ${PASS_IFF_EMPTY}
-       
 
 clean:
-       rm -rf main-${ARCH} dylib-${ARCH} dylib2-${ARCH}
-       
-
+       rm -rf main-* dylib-* dylib2-*
diff --git a/unit-tests/test-cases/dead_strip/comment.txt b/unit-tests/test-cases/dead_strip/comment.txt
new file mode 100644 (file)
index 0000000..90a289c
--- /dev/null
@@ -0,0 +1,5 @@
+The point of this test is a sanity check -dead_strip
+
+1) in a main executable, dead globals are removed
+2) in a dylib/bundle with -exported_symbols_list, dead globals are removed
+3) in a dylib/bundle without -exported_symbols_list, dead globals are *not* removed
diff --git a/unit-tests/test-cases/dead_strip_dylibs/Makefile b/unit-tests/test-cases/dead_strip_dylibs/Makefile
new file mode 100644 (file)
index 0000000..309655e
--- /dev/null
@@ -0,0 +1,52 @@
+##
+# Copyright (c) 2007 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 -dead_strip_dylibs
+#
+
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib 
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib 
+       ${CC} ${CCFLAGS} -dynamiclib baz.c -o libbaz.dylib 
+       ${CC} ${CCFLAGS} main.c libfoo.dylib libbar.dylib libbaz.dylib -o main
+       ${FAIL_IF_BAD_MACHO} main
+       otool -L main | grep libfoo.dylib | ${FAIL_IF_EMPTY}
+       otool -L main | grep libbar.dylib | ${FAIL_IF_EMPTY}
+       otool -L main | grep libbaz.dylib | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c -DCALL_BAR libfoo.dylib libbar.dylib libbaz.dylib -o main -Wl,-dead_strip_dylibs
+       ${FAIL_IF_BAD_MACHO} main
+       otool -L main | grep libfoo.dylib | ${FAIL_IF_STDIN}
+       otool -L main | grep libbar.dylib | ${FAIL_IF_EMPTY}
+       otool -L main | grep libbaz.dylib | ${FAIL_IF_STDIN}
+       ${PASS_IFF} /usr/bin/true
+
+
+clean:
+
+       rm -rf libbar.dylib libfoo.dylib libbaz.dylib main 
diff --git a/unit-tests/test-cases/dead_strip_dylibs/bar.c b/unit-tests/test-cases/dead_strip_dylibs/bar.c
new file mode 100644 (file)
index 0000000..9c18401
--- /dev/null
@@ -0,0 +1,5 @@
+
+int bar (void)
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/dead_strip_dylibs/baz.c b/unit-tests/test-cases/dead_strip_dylibs/baz.c
new file mode 100644 (file)
index 0000000..af6a9f8
--- /dev/null
@@ -0,0 +1,5 @@
+
+int baz (void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/dead_strip_dylibs/foo.c b/unit-tests/test-cases/dead_strip_dylibs/foo.c
new file mode 100644 (file)
index 0000000..d0cdf47
--- /dev/null
@@ -0,0 +1,4 @@
+int foo (void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/dead_strip_dylibs/main.c b/unit-tests/test-cases/dead_strip_dylibs/main.c
new file mode 100644 (file)
index 0000000..2b85b0e
--- /dev/null
@@ -0,0 +1,10 @@
+
+extern void bar();
+
+int main()
+{
+#if    CALL_BAR
+       bar();
+#endif
+       return 0;
+}
diff --git a/unit-tests/test-cases/dead_strip_section_attribute/Makefile b/unit-tests/test-cases/dead_strip_section_attribute/Makefile
new file mode 100644 (file)
index 0000000..e6471f7
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2007 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
+
+#
+# The point of this test is to check that -dead_strip does not remove
+# atoms in sections with the S_ATTR_NO_DEAD_STRIP bit set
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} main.c -dead_strip -o main-${ARCH}
+       ${FAIL_IF_BAD_MACHO} main-${ARCH}
+       nm -j main-${ARCH} | grep _bar | ${FAIL_IF_STDIN}
+       nm -j main-${ARCH} | grep _foo | ${PASS_IFF_STDIN}
+
+clean:
+       rm -rf main-*
diff --git a/unit-tests/test-cases/dead_strip_section_attribute/comment.txt b/unit-tests/test-cases/dead_strip_section_attribute/comment.txt
new file mode 100644 (file)
index 0000000..6ca56e4
--- /dev/null
@@ -0,0 +1,2 @@
+The point of this test is to check that -dead_strip does not remove
+atoms in sections with the S_ATTR_NO_DEAD_STRIP bit set
diff --git a/unit-tests/test-cases/dead_strip_section_attribute/main.c b/unit-tests/test-cases/dead_strip_section_attribute/main.c
new file mode 100644 (file)
index 0000000..5fc1fad
--- /dev/null
@@ -0,0 +1,42 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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@
+ */
+
+int main()
+{
+       return 0;
+}
+
+
+// foo should not be dead stripped
+void __attribute__ ((section ("__TEXT,__text_no_strip,regular,no_dead_strip"))) foo()
+{
+
+}
+
+// bar should be dead stripped
+void __attribute__ ((section ("__DATA,__text2"))) bar()
+{
+
+}
+
diff --git a/unit-tests/test-cases/dtrace-static-probes/Makefile b/unit-tests/test-cases/dtrace-static-probes/Makefile
new file mode 100644 (file)
index 0000000..5046ea1
--- /dev/null
@@ -0,0 +1,60 @@
+##
+# Copyright (c) 2007 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
+
+#
+# The point of this test is a sanity check that ld
+# can link a progam with dtrace static probes
+#
+
+all: run
+
+run: main main-r main-dead_strip libmain.dylib
+       ${FAIL_IF_BAD_MACHO} main
+       ${PASS_IFF_GOOD_MACHO} main-r
+
+main: main.c foo.h bar.h
+       ${CC} main.c -o main 
+
+main-dead_strip: main.c foo.h bar.h
+       ${CC} main.c -o main-dead_strip -dead_strip 
+
+main-r: main.c foo.h bar.h
+       ${CC} main.c -c -o main.o 
+       #${FAIL_IF_BAD_OBJ} main.o
+       ${LD} -r main.o -o main-r.o 
+       #${FAIL_IF_BAD_OBJ} main-r.o
+       ${CC} main-r.o -o main-r
+
+libmain.dylib: main.c foo.h bar.h
+       ${CC} main.c -dynamiclib -o libmain.dylib 
+
+foo.h: foo.d
+       dtrace -h -s foo.d
+
+bar.h: bar.d
+       dtrace -h -s bar.d
+
+clean:
+       rm -rf main main main-r main-dead_strip foo.h bar.h *.o
diff --git a/unit-tests/test-cases/dtrace-static-probes/bar.d b/unit-tests/test-cases/dtrace-static-probes/bar.d
new file mode 100644 (file)
index 0000000..fab36ea
--- /dev/null
@@ -0,0 +1,7 @@
+typedef int weirdType;
+
+provider Bar {
+        probe count1(weirdType);
+};
+
+#pragma D attributes Evolving/Evolving/Common provider Bar args
diff --git a/unit-tests/test-cases/dtrace-static-probes/comment.txt b/unit-tests/test-cases/dtrace-static-probes/comment.txt
new file mode 100644 (file)
index 0000000..b02ac8b
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a progam with dtrace static probes
diff --git a/unit-tests/test-cases/dtrace-static-probes/foo.d b/unit-tests/test-cases/dtrace-static-probes/foo.d
new file mode 100644 (file)
index 0000000..03f1a19
--- /dev/null
@@ -0,0 +1,8 @@
+typedef int weirdType2;
+
+provider Foo {
+       probe count1(weirdType2);
+};
+
+
+#pragma D attributes Evolving/Evolving/Common provider Foo args
diff --git a/unit-tests/test-cases/dtrace-static-probes/main.c b/unit-tests/test-cases/dtrace-static-probes/main.c
new file mode 100644 (file)
index 0000000..bbce55f
--- /dev/null
@@ -0,0 +1,28 @@
+
+#include <stdio.h>
+
+typedef int weirdType;
+typedef int weirdType2;
+
+#include "foo.h"
+#include "bar.h"
+
+
+int deadwood()
+{
+       BAR_COUNT1(2);
+}
+
+
+int main() {
+       int a = 1;
+
+       while(a) {
+               FOO_COUNT1(1);
+               printf("test\n");
+               BAR_COUNT1(2);
+               sleep(1);
+       }
+
+       return 0;
+}
diff --git a/unit-tests/test-cases/dwarf-archive-all_load/Makefile b/unit-tests/test-cases/dwarf-archive-all_load/Makefile
new file mode 100644 (file)
index 0000000..8d38d99
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2007 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 using -all_load to pull all .o files out of an archive
+# proeduces good "debug notes".
+#
+
+run: 
+       ${CC} ${CCFLAGS} -gdwarf-2 foo.c -c -o foo.o
+       ${FAIL_IF_BAD_OBJ} foo.o
+       ${CC} ${CCFLAGS} -gdwarf-2 bar.c -c -o bar.o
+       ${FAIL_IF_BAD_OBJ} bar.o
+       ${CC} ${CCFLAGS} -gdwarf-2 baz.c -c -o baz.o
+       ${FAIL_IF_BAD_OBJ} baz.o
+       libtool -static bar.o baz.o foo.o -o liball.a
+       ${CC} ${CCFLAGS} liball.a -all_load -dynamiclib -o liball.dylib -nodefaultlibs
+       ${FAIL_IF_BAD_MACHO} liball.dylib
+       nm -fap liball.dylib | ./stabs-filter.pl > liball.dylib.stabs
+       ${PASS_IFF} diff liball.dylib.stabs expected-stabs
+
+clean:
+       rm -rf *.o liball.a liball.dylib liball.dylib.stabs 
diff --git a/unit-tests/test-cases/dwarf-archive-all_load/bar.c b/unit-tests/test-cases/dwarf-archive-all_load/bar.c
new file mode 100644 (file)
index 0000000..06752f3
--- /dev/null
@@ -0,0 +1,2 @@
+void bar() {}
+
diff --git a/unit-tests/test-cases/dwarf-archive-all_load/baz.c b/unit-tests/test-cases/dwarf-archive-all_load/baz.c
new file mode 100644 (file)
index 0000000..256a0e3
--- /dev/null
@@ -0,0 +1 @@
+void baz() {}
diff --git a/unit-tests/test-cases/dwarf-archive-all_load/comment.txt b/unit-tests/test-cases/dwarf-archive-all_load/comment.txt
new file mode 100644 (file)
index 0000000..6992acd
--- /dev/null
@@ -0,0 +1,2 @@
+Test that using -all_load to pull all .o files out of an archive
+proeduces good "debug notes".
diff --git a/unit-tests/test-cases/dwarf-archive-all_load/expected-stabs b/unit-tests/test-cases/dwarf-archive-all_load/expected-stabs
new file mode 100644 (file)
index 0000000..0071455
--- /dev/null
@@ -0,0 +1,24 @@
+0000    SO CWD/
+0000    SO bar.c
+0001   OSO CWD/liball.a(bar.o)
+0000 BNSYM 
+0000   FUN _bar
+0000   FUN 
+0000 ENSYM 
+0000    SO 
+0000    SO CWD/
+0000    SO baz.c
+0001   OSO CWD/liball.a(baz.o)
+0000 BNSYM 
+0000   FUN _baz
+0000   FUN 
+0000 ENSYM 
+0000    SO 
+0000    SO CWD/
+0000    SO foo.c
+0001   OSO CWD/liball.a(foo.o)
+0000 BNSYM 
+0000   FUN _foo
+0000   FUN 
+0000 ENSYM 
+0000    SO 
diff --git a/unit-tests/test-cases/dwarf-archive-all_load/foo.c b/unit-tests/test-cases/dwarf-archive-all_load/foo.c
new file mode 100644 (file)
index 0000000..85e6cd8
--- /dev/null
@@ -0,0 +1 @@
+void foo() {}
diff --git a/unit-tests/test-cases/dwarf-archive-all_load/stabs-filter.pl b/unit-tests/test-cases/dwarf-archive-all_load/stabs-filter.pl
new file mode 100755 (executable)
index 0000000..706fd12
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+
+use strict;
+use Cwd;
+
+my $dir = getcwd;
+#my $xxx = $ARGV[1];
+
+while(<>)
+{
+       # get stabs lines that match "NNNNNNN - xxx"
+    if(m/^([0-9a-f]+) - ([0-9a-f]+) (.*?)$/)
+    {
+               # replace any occurances of cwd path with $CWD
+               my $line = $3;
+        if($line =~ m/(.*?)$dir(.*?)$/)
+               {
+                       $line = $1 . "CWD" . $2;
+               }
+               
+               printf "$line\n";
+       }
+}
+
+
index 8159cd9c18b56c75ec0abbb127575ca4e9714aa3..1eb6310d7ba21aaf48d2e1a6a30b29e473451fbc 100644 (file)
@@ -33,29 +33,27 @@ include ${TESTROOT}/include/common.makefile
 
 run: all
 
-all: foobar.o main.o crt1.o 
-       ${CXX} ${CCXXFLAGS} foobar.o main.o -o dwarf-test-${ARCH} -L.
+all: foobar.o main.o 
+       ${CXX} ${CCXXFLAGS} foobar.o main.o -o dwarf-test-${ARCH}
        ${FAIL_IF_BAD_MACHO} dwarf-test-${ARCH}
        nm -ap dwarf-test-${ARCH} | ./stabs-filter.pl > dwarf-test-${ARCH}.stabs
        ${PASS_IFF} diff dwarf-test-${ARCH}.stabs expected-stabs
 
 foobar.o : foo.o bar.o
        ${LD} -r -arch ${ARCH} foo.o bar.o -o foobar.o
-       
+       ${FAIL_IF_BAD_OBJ} foobar.o
+
 foo.o : foo.cxx
-       ${CXX} ${CCXXFLAGS} -gdwarf-2 foo.cxx -c -o foo.o -mdynamic-no-pic
+       ${CXX} ${CCXXFLAGS} -gdwarf-2 foo.cxx -c -o $@ -mdynamic-no-pic
+       ${FAIL_IF_BAD_OBJ} $@
 
 bar.o : bar.cxx
-       ${CXX} ${CCXXFLAGS} -gdwarf-2 bar.cxx -c -o bar.o -mdynamic-no-pic
+       ${CXX} ${CCXXFLAGS} -gdwarf-2 bar.cxx -c -o $@  -mdynamic-no-pic
+       ${FAIL_IF_BAD_OBJ} $@
 
 main.o : main.cxx
-       ${CXX} ${CCXXFLAGS} -gdwarf-2 main.cxx -c -o main.o -mdynamic-no-pic
-
-# don't want any stabs in crt1.o to effect output, so my private stripped copy
-crt1.o : /usr/lib/crt1.o
-       strip -S /usr/lib/crt1.o -o crt1.o
+       ${CXX} ${CCXXFLAGS} -gdwarf-2 main.cxx -c -o $@ -mdynamic-no-pic
+       ${FAIL_IF_BAD_OBJ} $@
 
 clean:
-       rm -rf dwarf-test-${ARCH}  foo.o bar.o foobar.o main.o crt1.o dwarf-test-${ARCH}.stabs
-
-
+       rm -rf dwarf-test-*  *.o *.stabs
diff --git a/unit-tests/test-cases/dwarf-debug-notes-r/comment.txt b/unit-tests/test-cases/dwarf-debug-notes-r/comment.txt
new file mode 100644 (file)
index 0000000..0f1d0b1
--- /dev/null
@@ -0,0 +1,5 @@
+The point of this test is a sanity check that ld
+produces good "debug notes" stabs from dwarf .o files after
+some of the .o files are merged with ld -r.
+Running nm through stabs-filter.pl produces connonical stabs
+that can be diffed against a checked in know good set of stabs
index 8b94b2f74a01c19fc68d52705d5ec517026b77ae..42f1cb72f86e7497bcc7f80b0b2c2142f0aa3055 100644 (file)
@@ -32,23 +32,19 @@ include ${TESTROOT}/include/common.makefile
 
 run: all
 
-all: hello.o other.o crt1.o 
-       ${CXX} ${CCXXFLAGS} -gdwarf-2 hello.o other.o -o dwarf-hello-${ARCH} -L.
+all: hello.o other.o 
+       ${CXX} ${CCXXFLAGS} -gdwarf-2 hello.o other.o -o dwarf-hello-${ARCH}
        ${FAIL_IF_BAD_MACHO} dwarf-hello-${ARCH}
        nm -ap dwarf-hello-${ARCH} | ./stabs-filter.pl > dwarf-hello-${ARCH}.stabs
        ${PASS_IFF} diff dwarf-hello-${ARCH}.stabs expected-stabs
 
 hello.o : hello.cxx
-       ${CXX} ${CCXXFLAGS} -gdwarf-2 hello.cxx -c -o hello.o -mdynamic-no-pic
+       ${CXX} ${CCXXFLAGS} -gdwarf-2 hello.cxx -c -o $@ -mdynamic-no-pic
+       ${FAIL_IF_BAD_OBJ} $@
 
 other.o : other.cxx
-       ${CXX} ${CCXXFLAGS} -gdwarf-2 other.cxx -c -o other.o -mdynamic-no-pic
-
-# don't want any stabs in crt1.o to effect output, so my private stripped copy
-crt1.o : /usr/lib/crt1.o
-       strip -S /usr/lib/crt1.o -o crt1.o
+       ${CXX} ${CCXXFLAGS} -gdwarf-2 other.cxx -c -o $@ -mdynamic-no-pic
+       ${FAIL_IF_BAD_OBJ} $@
 
 clean:
-       rm -rf dwarf-hello-${ARCH}  hello.o  other.o crt1.o dwarf-hello-${ARCH}.stabs
-
-
+       rm -rf dwarf-hello-* *.o *.stabs
diff --git a/unit-tests/test-cases/dwarf-debug-notes/comment.txt b/unit-tests/test-cases/dwarf-debug-notes/comment.txt
new file mode 100644 (file)
index 0000000..5caf129
--- /dev/null
@@ -0,0 +1,4 @@
+The point of this test is a sanity check that ld
+produces good "debug notes" stabs from dwarf .o files
+Running nm through stabs-filter.pl produces connonical stabs
+that can be diffed against a checked in know good set of stabs
index 773e572959bb7c7c4bcd2376252e974698a8afdf..94b026cb2fe7e1df6dad11001658673e5be5a8b1 100644 (file)
@@ -36,6 +36,4 @@ all:
        size -l dwarf-hello-${ARCH} | grep __DWARF | ${PASS_IFF_EMPTY}
 
 clean:
-       rm -rf dwarf-hello-${ARCH} 
-       
-
+       rm -rf dwarf-hello-*
diff --git a/unit-tests/test-cases/dwarf-ignore/comment.txt b/unit-tests/test-cases/dwarf-ignore/comment.txt
new file mode 100644 (file)
index 0000000..06822b2
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld strips out the dwarf segment by default
index 916eff199c2c7113a2bc8fee4b552ff698e410e0..947afa70b3b8b174a8c148468149c86e0e4eb5ef 100644 (file)
@@ -32,10 +32,9 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} -gdwarf-2 hello.c -Wl,-S -o dwarf-hello-${ARCH} 
+       #${CC} ${CCFLAGS} -gdwarf-2 hello.c -o dwarf-hello-${ARCH} 
        ${FAIL_IF_BAD_MACHO} dwarf-hello-${ARCH}
-       nm -ap dwarf-hello-${ARCH} | grep -e "-" | ${PASS_IFF_EMPTY}
+       nm -ap dwarf-hello-${ARCH} | grep -e " - " | ${PASS_IFF_EMPTY}
 
 clean:
-       rm -rf dwarf-hello-${ARCH} 
-       
-
+       rm -rf dwarf-hello-*
diff --git a/unit-tests/test-cases/dwarf-strip/comment.txt b/unit-tests/test-cases/dwarf-strip/comment.txt
new file mode 100644 (file)
index 0000000..5a23827
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld -S produces no debug notes (stabs)
diff --git a/unit-tests/test-cases/dylib-aliases/Makefile b/unit-tests/test-cases/dylib-aliases/Makefile
new file mode 100644 (file)
index 0000000..5c34470
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# Test that libfoo.dylib can be aliases with a symlink or
+# as another dylib and still link
+#
+
+run: all
+
+all: libfoo.dylib libbar.dylib libbaz.dylib
+       ${CC} ${CCFLAGS} main.c -o main -lfoo -lbar -lbaz -L.
+       ${PASS_IFF_GOOD_MACHO} main
+
+libfoo.dylib : foo.c
+       ${CC} foo.c -dynamiclib -o libfoo.dylib
+
+libbar.dylib : bar.c
+       ${CC} bar.c -dynamiclib -o libbar.dylib -install_name libfoo.dylib
+
+libbaz.dylib : libfoo.dylib
+       ln -s libfoo.dylib libbaz.dylib
+
+clean:
+       rm -rf  *.dylib main
diff --git a/unit-tests/test-cases/dylib-aliases/bar.c b/unit-tests/test-cases/dylib-aliases/bar.c
new file mode 100644 (file)
index 0000000..981110f
--- /dev/null
@@ -0,0 +1 @@
+void bar() { }
diff --git a/unit-tests/test-cases/dylib-aliases/foo.c b/unit-tests/test-cases/dylib-aliases/foo.c
new file mode 100644 (file)
index 0000000..2fb55ee
--- /dev/null
@@ -0,0 +1 @@
+void foo() { }
diff --git a/unit-tests/test-cases/dylib-aliases/main.c b/unit-tests/test-cases/dylib-aliases/main.c
new file mode 100644 (file)
index 0000000..03c4b39
--- /dev/null
@@ -0,0 +1,8 @@
+extern void foo();
+extern void bar();
+
+int main() {
+   foo();
+   bar();
+   return 0;
+}
diff --git a/unit-tests/test-cases/dylib-re-export-cycle/Makefile b/unit-tests/test-cases/dylib-re-export-cycle/Makefile
new file mode 100644 (file)
index 0000000..617fbfc
--- /dev/null
@@ -0,0 +1,52 @@
+##
+# Copyright (c) 2007 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
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+#
+# Test that searches for indirect libraries does not cause a cycle
+# <rdar://problem/5277857> OpenGL.framework and X11 both have a libGL.dylib which can cause ld to segfault if both are found
+#
+
+run: all
+
+all: libfoo.dylib 
+       ${CC} main.c libfoo.dylib -o main -L. 2>errmsg || true
+       grep "cycle" errmsg | ${PASS_IFF_STDIN}
+
+libfoo.dylib : foo.c libbar.dylib
+       ${CC} foo.c -dynamiclib -o libfoo.dylib libbar.dylib -sub_library libbar -mmacosx-version-min=10.4
+
+libbar.dylib : bar.c other/libfoo.dylib
+       ${CC} bar.c -dynamiclib -o libbar.dylib other/libfoo.dylib -sub_library libfoo -mmacosx-version-min=10.4
+
+other/libfoo.dylib : foo.c 
+       mkdir -p other
+       ${CC} foo.c -dynamiclib -o other/libfoo.dylib -mmacosx-version-min=10.4
+
+
+
+clean:
+       rm -rf other libfoo.dylib libbar.dylib main errmsg
diff --git a/unit-tests/test-cases/dylib-re-export-cycle/bar.c b/unit-tests/test-cases/dylib-re-export-cycle/bar.c
new file mode 100644 (file)
index 0000000..981110f
--- /dev/null
@@ -0,0 +1 @@
+void bar() { }
diff --git a/unit-tests/test-cases/dylib-re-export-cycle/foo.c b/unit-tests/test-cases/dylib-re-export-cycle/foo.c
new file mode 100644 (file)
index 0000000..2fb55ee
--- /dev/null
@@ -0,0 +1 @@
+void foo() { }
diff --git a/unit-tests/test-cases/dylib-re-export-cycle/main.c b/unit-tests/test-cases/dylib-re-export-cycle/main.c
new file mode 100644 (file)
index 0000000..8273541
--- /dev/null
@@ -0,0 +1,6 @@
+extern void unfindable();
+
+int main() {
+   unfindable();
+   return 0;
+}
diff --git a/unit-tests/test-cases/dylib_file-missing/Makefile b/unit-tests/test-cases/dylib_file-missing/Makefile
new file mode 100644 (file)
index 0000000..f6371af
--- /dev/null
@@ -0,0 +1,42 @@
+##
+# Copyright (c) 2007 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)
+SHELL = bash # use bash shell so we can redirect just stderr
+
+
+# Verify that if -dylib_file option points to a missing, file the link does not fail
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib -install_name "${PWD}/libbar.dylib"
+       ${CC} ${CCFLAGS} foo.c "${PWD}/libbar.dylib" -dynamiclib -o libfoo.dylib -sub_library libbar
+       ${CC} ${CCFLAGS} main.c libfoo.dylib -o main
+       ${CC} ${CCFLAGS} main.c libfoo.dylib -o main -dylib_file "${PWD}/libbar.dylib:libbar2.dylib" 2>warnings.log
+       ${PASS_IFF_GOOD_MACHO} main
+       
+clean:
+       rm -rf *.dylib main warnings.log
diff --git a/unit-tests/test-cases/dylib_file-missing/bar.c b/unit-tests/test-cases/dylib_file-missing/bar.c
new file mode 100644 (file)
index 0000000..2668f9a
--- /dev/null
@@ -0,0 +1,13 @@
+
+
+
+void bar()
+{
+}
+
+#if BAR_EXTRA
+void bar_extra()
+{
+}
+#endif
+
diff --git a/unit-tests/test-cases/dylib_file-missing/foo.c b/unit-tests/test-cases/dylib_file-missing/foo.c
new file mode 100644 (file)
index 0000000..aa31241
--- /dev/null
@@ -0,0 +1,7 @@
+
+extern void bar();
+
+void foo()
+{
+       bar();
+}
diff --git a/unit-tests/test-cases/dylib_file-missing/main.c b/unit-tests/test-cases/dylib_file-missing/main.c
new file mode 100644 (file)
index 0000000..3f109f2
--- /dev/null
@@ -0,0 +1,15 @@
+
+extern void foo();
+extern void bar();
+extern void bar_extra();
+
+int main()
+{
+       foo();
+       bar();
+#if BAR_EXTRA
+       bar_extra();
+#endif
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/dylib_file/Makefile b/unit-tests/test-cases/dylib_file/Makefile
new file mode 100644 (file)
index 0000000..181eee5
--- /dev/null
@@ -0,0 +1,46 @@
+##
+# Copyright (c) 2007 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)
+SHELL = bash # use bash shell so we can redirect just stderr
+
+
+# Verify that -dylib_file option allows you to replace an indirect dylib
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib -install_name "${PWD}/libbar.dylib"
+       ${CC} ${CCFLAGS} bar.c -DBAR_EXTRA -dynamiclib -o libbar2.dylib -install_name "${PWD}/libbar.dylib"
+       ${CC} ${CCFLAGS} foo.c "${PWD}/libbar.dylib" -dynamiclib -o libfoo.dylib -sub_library libbar
+       ${CC} ${CCFLAGS} main.c libfoo.dylib -o main
+       # verify that if main needs bar_extra, it fails
+       ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} main.c -DBAR_EXTRA libfoo.dylib -o main  2> fail.log
+       # verify that if main needs bar_extra, it works with -dylib_file option
+       ${CC} ${CCFLAGS} main.c -DBAR_EXTRA libfoo.dylib -o main -dylib_file "${PWD}/libbar.dylib:libbar2.dylib"
+       ${PASS_IFF_GOOD_MACHO} main
+       
+clean:
+       rm -rf *.dylib main fail.log
diff --git a/unit-tests/test-cases/dylib_file/bar.c b/unit-tests/test-cases/dylib_file/bar.c
new file mode 100644 (file)
index 0000000..2668f9a
--- /dev/null
@@ -0,0 +1,13 @@
+
+
+
+void bar()
+{
+}
+
+#if BAR_EXTRA
+void bar_extra()
+{
+}
+#endif
+
diff --git a/unit-tests/test-cases/dylib_file/comment.txt b/unit-tests/test-cases/dylib_file/comment.txt
new file mode 100644 (file)
index 0000000..e3bfbb7
--- /dev/null
@@ -0,0 +1 @@
+Verify that -dylib_file option allows you to replace an indirect dylib
diff --git a/unit-tests/test-cases/dylib_file/foo.c b/unit-tests/test-cases/dylib_file/foo.c
new file mode 100644 (file)
index 0000000..aa31241
--- /dev/null
@@ -0,0 +1,7 @@
+
+extern void bar();
+
+void foo()
+{
+       bar();
+}
diff --git a/unit-tests/test-cases/dylib_file/main.c b/unit-tests/test-cases/dylib_file/main.c
new file mode 100644 (file)
index 0000000..3f109f2
--- /dev/null
@@ -0,0 +1,15 @@
+
+extern void foo();
+extern void bar();
+extern void bar_extra();
+
+int main()
+{
+       foo();
+       bar();
+#if BAR_EXTRA
+       bar_extra();
+#endif
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/dylib_init/Makefile b/unit-tests/test-cases/dylib_init/Makefile
new file mode 100644 (file)
index 0000000..89db531
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+# When creating a dylib with the -init option to specify the init  routine in 64-bit,
+# libtool should not complain "file not found: __init".
+
+run: all
+
+all:
+       ${FAIL_IF_ERROR} ${CC} -m64 -c foo.c -o foo_64.o
+       ${FAIL_IF_BAD_OBJ} foo_64.o
+       ${FAIL_IF_ERROR} libtool -dynamic -o libtest.A.dylib foo_64.o \
+               -init __init \
+               -compatibility_version 1 -current_version 1 -install_name "/build/ld64_problem/libtest.A.dylib" \
+               -lSystem
+       ${PASS_IFF_GOOD_MACHO} libtest.A.dylib
+
+clean:
+       rm -rf *.dylib *.o 
diff --git a/unit-tests/test-cases/dylib_init/comment.txt b/unit-tests/test-cases/dylib_init/comment.txt
new file mode 100644 (file)
index 0000000..9355f2c
--- /dev/null
@@ -0,0 +1,2 @@
+When creating a dylib with the -init option to specify the init  routine in 64-bit,
+libtool sould not complain "file not found: __init".
diff --git a/unit-tests/test-cases/dylib_init/foo.c b/unit-tests/test-cases/dylib_init/foo.c
new file mode 100644 (file)
index 0000000..9ba156e
--- /dev/null
@@ -0,0 +1,2 @@
+void _init() {
+}
diff --git a/unit-tests/test-cases/eh-strip-test/Makefile b/unit-tests/test-cases/eh-strip-test/Makefile
new file mode 100644 (file)
index 0000000..0b8fcff
--- /dev/null
@@ -0,0 +1,34 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+
+
+all:
+       ${FAIL_IF_ERROR} $(CXX) main.cxx -arch ${ARCH} -o main
+       ${FAIL_IF_ERROR} nm -j main | grep '\.eh$$'| ${FAIL_IF_STDIN}
+       ${PASS_IFF_GOOD_MACHO} main
+clean:
+       rm -rf *.o main main-* *.nm
diff --git a/unit-tests/test-cases/eh-strip-test/comment.txt b/unit-tests/test-cases/eh-strip-test/comment.txt
new file mode 100644 (file)
index 0000000..a99f78e
--- /dev/null
@@ -0,0 +1,21 @@
+Test strip: symbols referenced by indirect symbol table entries can't be stripped (4096290)
+
+__ZN9__gnu_cxx13new_allocatorIiE7destroyEPi
+__ZNKSt12_Vector_baseIiSaIiEE13get_allocatorEv
+__ZN9__gnu_cxx13new_allocatorIiEC2ERKS1_
+__ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPim
+__ZN9__gnu_cxx13new_allocatorIiED2Ev
+__ZNSt6vectorIiSaIiEEC1ERKS0_
+__ZNSaIiEC1ERKS_
+__ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim
+__ZNSt12_Vector_baseIiSaIiEE12_Vector_implC1ERKS0_
+__ZNSaIiED2Ev
+__ZNSt12_Vector_baseIiSaIiEED2Ev
+__ZNSaIiEC1Ev
+__ZNSt12_Vector_baseIiSaIiEEC2ERKS0_
+__ZNSt6vectorIiSaIiEED1Ev
+__ZNSaIiED1Ev
+__ZSt8_DestroyIPiSaIiEEvT_S2_T0_
+__ZN9__gnu_cxx13new_allocatorIiEC2Ev
+__ZNSaIiEC2ERKS_
+__ZNSt12_Vector_baseIiSaIiEE12_Vector_implD1Ev
diff --git a/unit-tests/test-cases/eh-strip-test/main.cxx b/unit-tests/test-cases/eh-strip-test/main.cxx
new file mode 100644 (file)
index 0000000..dd65fef
--- /dev/null
@@ -0,0 +1,6 @@
+#include <vector>
+int main()
+{
+       std::vector<int> stuff;
+       return 0;
+}
diff --git a/unit-tests/test-cases/eh_frame/Makefile b/unit-tests/test-cases/eh_frame/Makefile
new file mode 100644 (file)
index 0000000..6216d8e
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# strips .eh symbols out of final linked images,
+# even when an intermediate ld -r was used.
+#
+
+run: all
+
+all:
+       ${CXX} ${CCXXFLAGS} foo.cxx -dynamiclib -o libfoo.dylib
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       nm libfoo.dylib | grep '.eh' | ${FAIL_IF_STDIN}
+       ${CXX} ${CCXXFLAGS} foo.cxx -c -o foo.o
+       ${FAIL_IF_BAD_OBJ} foo.o
+       ${LD} -r foo.o -o foo2.o
+       ${FAIL_IF_BAD_OBJ} foo2.o
+       ${CXX} ${CCXXFLAGS} foo2.o bar.cxx -dynamiclib -o libfoobar.dylib
+       ${FAIL_IF_BAD_MACHO} libfoobar.dylib
+       nm libfoobar.dylib | grep '.eh' | ${PASS_IFF_EMPTY}
+
+clean:
+       rm  *.dylib *.o
diff --git a/unit-tests/test-cases/eh_frame/bar.cxx b/unit-tests/test-cases/eh_frame/bar.cxx
new file mode 100644 (file)
index 0000000..9623da1
--- /dev/null
@@ -0,0 +1,38 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+
+static void bar1() 
+{ 
+       fprintf(stderr, "hello\n");
+}
+
+void bar2() 
+{ 
+       bar1(); 
+       fprintf(stderr, "world\n");
+}
+
+
diff --git a/unit-tests/test-cases/eh_frame/foo.cxx b/unit-tests/test-cases/eh_frame/foo.cxx
new file mode 100644 (file)
index 0000000..d1e2dd1
--- /dev/null
@@ -0,0 +1,38 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+
+static void foo1() 
+{ 
+       fprintf(stderr, "hello\n");
+}
+
+void foo2() 
+{ 
+       foo1(); 
+       fprintf(stderr, "world\n");
+}
+
+
diff --git a/unit-tests/test-cases/end-label/Makefile b/unit-tests/test-cases/end-label/Makefile
new file mode 100644 (file)
index 0000000..69f51a7
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Check that ld maintains two symbols with the same address and in different sections 
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} foo.s -c -o foo.o
+       ${CC} ${CCFLAGS} bar.s -c -o bar.o
+       ${LD} -r foo.o bar.o -o foobar.o
+       nm -m foobar.o | grep _next | grep __other | ${FAIL_IF_EMPTY}
+       ${LD} -r foobar.o -o foobar2.o
+       nm -m foobar2.o | grep _next | grep __other | ${PASS_IFF_STDIN}
+
+clean:
+       rm -rf *.o
diff --git a/unit-tests/test-cases/end-label/bar.s b/unit-tests/test-cases/end-label/bar.s
new file mode 100644 (file)
index 0000000..db389c4
--- /dev/null
@@ -0,0 +1,7 @@
+
+       .section __DATA,__other,regular
+
+       .globl _next
+_next:
+       nop
+       
\ No newline at end of file
diff --git a/unit-tests/test-cases/end-label/foo.s b/unit-tests/test-cases/end-label/foo.s
new file mode 100644 (file)
index 0000000..888af5f
--- /dev/null
@@ -0,0 +1,11 @@
+
+       .data
+       
+       .globl _start
+       .globl _end
+_start:
+       .long 0
+       .long 0
+_end:
+
+
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/Makefile b/unit-tests/test-cases/exported-symbols-wildcards/Makefile
new file mode 100644 (file)
index 0000000..1890820
--- /dev/null
@@ -0,0 +1,78 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Tests the use of wildcards in exported symbol lists
+#
+
+run: all
+
+all:
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,'_foo*bar'
+       nm -j -g -f libfoo.dylib | diff - expect1 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,'_f?o'
+       nm -j -g -f libfoo.dylib | diff - expect2 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,'_foo*'
+       nm -j -g -f libfoo.dylib | diff - expect3 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,'_f*o*'
+       nm -j -g -f libfoo.dylib | diff - expect4 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,_foo -Wl,-exported_symbol -Wl,'_*bar'
+       nm -j -g -f libfoo.dylib | diff - expect5 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -exported_symbols_list list5
+       nm -j -g -f libfoo.dylib | diff - expect5 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-unexported_symbol -Wl,'_*2*'
+       nm -j -g -f libfoo.dylib | diff - expect6 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,'_f[abcdef]o'
+       nm -j -g -f libfoo.dylib | diff - expect7 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,'_f[a-f]o'
+       nm -j -g -f libfoo.dylib | diff - expect7 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,'_f[a-z]o'
+       nm -j -g -f libfoo.dylib | diff - expect8 | ${FAIL_IF_STDIN}
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+       ${CC} -dynamiclib foo.c -o libfoo.dylib -Wl,-exported_symbol -Wl,'_f[a-fnop]o'
+       nm -j -g -f libfoo.dylib | diff - expect8 | ${FAIL_IF_STDIN}
+       ${PASS_IFF_GOOD_MACHO} libfoo.dylib
+       
+clean:
+       rm libfoo.dylib
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/expect1 b/unit-tests/test-cases/exported-symbols-wildcards/expect1
new file mode 100644 (file)
index 0000000..75aadb3
--- /dev/null
@@ -0,0 +1,2 @@
+_foo2bar
+_foobar
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/expect2 b/unit-tests/test-cases/exported-symbols-wildcards/expect2
new file mode 100644 (file)
index 0000000..09883f8
--- /dev/null
@@ -0,0 +1,3 @@
+_fao
+_ffo
+_foo
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/expect3 b/unit-tests/test-cases/exported-symbols-wildcards/expect3
new file mode 100644 (file)
index 0000000..478bf69
--- /dev/null
@@ -0,0 +1,4 @@
+_foo
+_foo2
+_foo2bar
+_foobar
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/expect4 b/unit-tests/test-cases/exported-symbols-wildcards/expect4
new file mode 100644 (file)
index 0000000..b78c206
--- /dev/null
@@ -0,0 +1,6 @@
+_fao
+_ffo
+_foo
+_foo2
+_foo2bar
+_foobar
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/expect5 b/unit-tests/test-cases/exported-symbols-wildcards/expect5
new file mode 100644 (file)
index 0000000..cc935a4
--- /dev/null
@@ -0,0 +1,3 @@
+_foo
+_foo2bar
+_foobar
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/expect6 b/unit-tests/test-cases/exported-symbols-wildcards/expect6
new file mode 100644 (file)
index 0000000..bdf1d31
--- /dev/null
@@ -0,0 +1,4 @@
+_fao
+_ffo
+_foo
+_foobar
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/expect7 b/unit-tests/test-cases/exported-symbols-wildcards/expect7
new file mode 100644 (file)
index 0000000..c691c40
--- /dev/null
@@ -0,0 +1,2 @@
+_fao
+_ffo
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/expect8 b/unit-tests/test-cases/exported-symbols-wildcards/expect8
new file mode 100644 (file)
index 0000000..09883f8
--- /dev/null
@@ -0,0 +1,3 @@
+_fao
+_ffo
+_foo
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/foo.c b/unit-tests/test-cases/exported-symbols-wildcards/foo.c
new file mode 100644 (file)
index 0000000..bc5be8e
--- /dev/null
@@ -0,0 +1,55 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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 <stddef.h>
+
+
+int foo()
+{
+       return 1;
+}
+
+int foo2()
+{
+       return 1;
+}
+
+int foobar()
+{
+       return 1;
+}
+
+int foo2bar()
+{
+       return 1;
+}
+
+int fao()
+{
+       return 1;
+}
+
+int ffo()
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/exported-symbols-wildcards/list5 b/unit-tests/test-cases/exported-symbols-wildcards/list5
new file mode 100644 (file)
index 0000000..a6776d2
--- /dev/null
@@ -0,0 +1,2 @@
+_foo
+_*bar
diff --git a/unit-tests/test-cases/exported_symbols_list-eol/Makefile b/unit-tests/test-cases/exported_symbols_list-eol/Makefile
new file mode 100644 (file)
index 0000000..25a50b4
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2007 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
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+#
+# Verify that -exported_symbols_list can be used with a file with Mac (0x0D) line endings
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} test.c -dynamiclib -exported_symbols_list test.exp -o libtest.dylib
+       nm -jg libtest.dylib | grep _ > test.nm
+       diff test.nm expected.nm
+       ${PASS_IFF_GOOD_MACHO} libtest.dylib
+
+clean:
+       rm -rf libtest.dylib test.nm
diff --git a/unit-tests/test-cases/exported_symbols_list-eol/expected.nm b/unit-tests/test-cases/exported_symbols_list-eol/expected.nm
new file mode 100644 (file)
index 0000000..b21cbbf
--- /dev/null
@@ -0,0 +1,2 @@
+_common_global2
+_func_global2
diff --git a/unit-tests/test-cases/exported_symbols_list-eol/test.c b/unit-tests/test-cases/exported_symbols_list-eol/test.c
new file mode 100644 (file)
index 0000000..c9fdc35
--- /dev/null
@@ -0,0 +1,18 @@
+
+
+
+static int data_static1 = 1;
+static int data_static2 = 2;
+
+void func_global1() { ++data_static1; }
+void func_global2() { ++data_static2; }
+
+void __attribute__((visibility("hidden"))) func_hidden1() {}
+void __attribute__((visibility("hidden"))) func_hidden2() {}
+
+int common_global1;
+int common_global2;
+
+int __attribute__((visibility("hidden"))) common_hidden1;
+int __attribute__((visibility("hidden"))) common_hidden2;
+
diff --git a/unit-tests/test-cases/exported_symbols_list-eol/test.exp b/unit-tests/test-cases/exported_symbols_list-eol/test.exp
new file mode 100644 (file)
index 0000000..6ab1532
--- /dev/null
@@ -0,0 +1 @@
+_func_global2\r_common_global2\r
\ No newline at end of file
diff --git a/unit-tests/test-cases/exported_symbols_list-r/Makefile b/unit-tests/test-cases/exported_symbols_list-r/Makefile
new file mode 100644 (file)
index 0000000..96ef763
--- /dev/null
@@ -0,0 +1,55 @@
+##
+# Copyright (c) 2007 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
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+#
+# Verify that -exported_symbols_list can be used with -r
+# to reduce visibility of symbols and any missing symbols
+# causes an error
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} test.c -c -o test.o
+       ${FAIL_IF_BAD_OBJ} test.o
+       ${LD} -arch ${ARCH} -r -keep_private_externs test.o -exported_symbols_list test.exp -o test-r.o
+       ${FAIL_IF_BAD_OBJ} test-r.o
+       # verify common not in export-list got demoted to private extern
+       nm -m test-r.o | grep "private external _common_global1" | ${FAIL_IF_EMPTY} 
+       # verify only _common_global1 and _func_global1 changed
+       nm -m test.o | egrep -v '_common_global1|_func_global1|__eh_frame|__data' > test.nm
+       nm -m test-r.o | egrep -v '_common_global1|_func_global1|__eh_frame|__data' > test-r.nm
+       diff test.nm test-r.nm
+       # verify without -keep_private_externs that commons stay private extern 
+       ${LD} -arch ${ARCH} -r  test.o -exported_symbols_list test.exp -o test-rr.o
+       nm -m test-rr.o | grep _common_hidden | grep ') external' | ${FAIL_IF_STDIN}
+       nm -m test-rr.o | grep _common_global1 | grep ') external' | ${FAIL_IF_STDIN}
+       # should error out if told to export unavailable symbol 
+       ${FAIL_IFF_SUCCESS} ${LD} -arch ${ARCH} -r test.o -exported_symbols_list test-bad.exp -o test2.o 2>/dev/null
+
+clean:
+       rm -rf test.o test-r.o test-rr.o test.nm test-r.nm test2.o
diff --git a/unit-tests/test-cases/exported_symbols_list-r/test-bad.exp b/unit-tests/test-cases/exported_symbols_list-r/test-bad.exp
new file mode 100644 (file)
index 0000000..73154ba
--- /dev/null
@@ -0,0 +1,3 @@
+_bar
+_baz
+_foobar
diff --git a/unit-tests/test-cases/exported_symbols_list-r/test.c b/unit-tests/test-cases/exported_symbols_list-r/test.c
new file mode 100644 (file)
index 0000000..c9fdc35
--- /dev/null
@@ -0,0 +1,18 @@
+
+
+
+static int data_static1 = 1;
+static int data_static2 = 2;
+
+void func_global1() { ++data_static1; }
+void func_global2() { ++data_static2; }
+
+void __attribute__((visibility("hidden"))) func_hidden1() {}
+void __attribute__((visibility("hidden"))) func_hidden2() {}
+
+int common_global1;
+int common_global2;
+
+int __attribute__((visibility("hidden"))) common_hidden1;
+int __attribute__((visibility("hidden"))) common_hidden2;
+
diff --git a/unit-tests/test-cases/exported_symbols_list-r/test.exp b/unit-tests/test-cases/exported_symbols_list-r/test.exp
new file mode 100644 (file)
index 0000000..93e7e17
--- /dev/null
@@ -0,0 +1,2 @@
+_func_global2
+_common_global2
diff --git a/unit-tests/test-cases/external-reloc-sorting/Makefile b/unit-tests/test-cases/external-reloc-sorting/Makefile
new file mode 100644 (file)
index 0000000..d9b92d5
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2007 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
+
+#
+# The point of this test is to see that external relocations
+# are sorted so that dyld only has to look up symbols once.
+# The machochecker tool verifies that the relocs are sorted.
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} foo.c -dynamiclib -o libfoo.dylib
+       ${CC} ${CCFLAGS} main.c libfoo.dylib -o main
+       ${PASS_IFF_GOOD_MACHO} main
+
+clean:
+       rm -rf main libfoo.dylib
diff --git a/unit-tests/test-cases/external-reloc-sorting/foo.c b/unit-tests/test-cases/external-reloc-sorting/foo.c
new file mode 100644 (file)
index 0000000..bc28725
--- /dev/null
@@ -0,0 +1,5 @@
+
+int foo = 1;
+int bar = 2;
+int baz = 3;
+
diff --git a/unit-tests/test-cases/external-reloc-sorting/main.c b/unit-tests/test-cases/external-reloc-sorting/main.c
new file mode 100644 (file)
index 0000000..6c68c4c
--- /dev/null
@@ -0,0 +1,39 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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>
+
+// in libfoo.dylib
+extern int foo;
+extern int bar;
+extern int baz;
+
+// this initialilzed data will result in external relocations
+// alternating the values, will create relocs that need sorting
+int* array[] = { &foo, &bar, &baz, &foo, &bar, &baz, &foo, &bar, &baz };
+
+
+int main()
+{
+       return 0;
+}
index 78a10041985e2d11a7aa7040dd8e58e50433b2be..0b1a743b596e8868a122ad15bbe3d43fe467d98e 100644 (file)
@@ -27,7 +27,7 @@ include ${TESTROOT}/include/common.makefile
 PWD = $(shell pwd)
 
 #
-# The point of this test is to check the two forms of the'
+# The point of this test is to check the two forms of the
 #  -filelist option
 #
 
@@ -35,14 +35,13 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} -c hello.c -o hello-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} hello-${ARCH}.o
        echo "${PWD}/hello-${ARCH}.o" > "${PWD}/filelist1"
-       cd /tmp && ${CC} ${CCFLAGS} -arch ${ARCH} -filelist "${PWD}/filelist1"  -o "${PWD}/hello-${ARCH}"
+       cd /tmp && ${CC} ${CCFLAGS} -filelist "${PWD}/filelist1"  -o "${PWD}/hello-${ARCH}"
        ${FAIL_IF_BAD_MACHO} hello-${ARCH}
        echo "hello-${ARCH}.o" > "${PWD}/filelist2"
-       cd /tmp && ${CC} ${CCFLAGS}  -arch ${ARCH} -filelist "${PWD}/filelist2,${PWD}" -o "${PWD}/hello-${ARCH}"
+       cd /tmp && ${CC} ${CCFLAGS} -filelist "${PWD}/filelist2,${PWD}" -o "${PWD}/hello-${ARCH}"
        ${PASS_IFF_GOOD_MACHO} hello-${ARCH}
 
 clean:
-       rm  hello-${ARCH} hello-${ARCH}.o filelist1 filelist2
-       
-
+       rm  hello-* *.o filelist1 filelist2
diff --git a/unit-tests/test-cases/filelist/comment.txt b/unit-tests/test-cases/filelist/comment.txt
new file mode 100644 (file)
index 0000000..f193b11
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to check the two forms of the -filelist option
diff --git a/unit-tests/test-cases/flat-dylib/Makefile b/unit-tests/test-cases/flat-dylib/Makefile
new file mode 100644 (file)
index 0000000..b1015b2
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a small dylib -flat_namespace and
+# indirect internal references.
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} main.c -dynamiclib -o libmain.dylib -flat_namespace 
+       otool -Iv libmain.dylib | grep _foo | ${FAIL_IF_EMPTY}
+       ${PASS_IFF_GOOD_MACHO} libmain.dylib 
+
+clean:
+       rm *.dylib 
diff --git a/unit-tests/test-cases/flat-dylib/main.c b/unit-tests/test-cases/flat-dylib/main.c
new file mode 100644 (file)
index 0000000..6014829
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+void foo() {}
+
+
+int main()
+{
+       foo();
+       fprintf(stdout, "hello\n");
+}
diff --git a/unit-tests/test-cases/flat-indirect-undefines/Makefile b/unit-tests/test-cases/flat-indirect-undefines/Makefile
new file mode 100644 (file)
index 0000000..a3715e0
--- /dev/null
@@ -0,0 +1,49 @@
+##
+# Copyright (c) 2007 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 when linking a main executable for flat-namespace
+# that undefines in loaded flat-namespace dylibs are resolved.
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} foo.c -flat_namespace -dynamiclib -o libfoo.dylib -undefined suppress
+       ${CC} ${CCFLAGS} bar.c -c -o bar.o
+       libtool -static bar.o -o libbar.a
+       # test that linking main executable -twolevel_namespace does not pull in bar()
+       ${CC} ${CCFLAGS} main.c libfoo.dylib libbar.a -o main
+       nm -mn main | grep _bar | ${FAIL_IF_STDIN}
+       # test that linking dylib -flat_namespace does not pull in bar()
+       ${CC} ${CCFLAGS} main.c -flat_namespace libfoo.dylib libbar.a -dynamiclib -o main.dylib
+       nm -mn main.dylib | grep _bar | ${FAIL_IF_STDIN}
+       # test that linking main executable -flat_namespace pulls in bar()
+       ${CC} ${CCFLAGS} main.c -flat_namespace libfoo.dylib libbar.a -o main_flat
+       nm -mn main_flat | grep _bar | ${FAIL_IF_EMPTY}
+       ${PASS_IFF_GOOD_MACHO} main_flat
+       
+clean:
+       rm libfoo.dylib libbar.a bar.o main main_flat main.dylib 
diff --git a/unit-tests/test-cases/flat-indirect-undefines/bar.c b/unit-tests/test-cases/flat-indirect-undefines/bar.c
new file mode 100644 (file)
index 0000000..b348aa8
--- /dev/null
@@ -0,0 +1,4 @@
+
+void bar() {}
+
+
diff --git a/unit-tests/test-cases/flat-indirect-undefines/foo.c b/unit-tests/test-cases/flat-indirect-undefines/foo.c
new file mode 100644 (file)
index 0000000..39df2ea
--- /dev/null
@@ -0,0 +1,8 @@
+
+extern void bar();
+
+void foo()
+{
+       bar();
+}
+
diff --git a/unit-tests/test-cases/flat-indirect-undefines/main.c b/unit-tests/test-cases/flat-indirect-undefines/main.c
new file mode 100644 (file)
index 0000000..246fed4
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+extern void foo();
+
+
+int main()
+{
+       foo();
+       return 0;
+}
diff --git a/unit-tests/test-cases/flat-main/Makefile b/unit-tests/test-cases/flat-main/Makefile
new file mode 100644 (file)
index 0000000..d31b7ab
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a hello-world program -flat_namespace and
+# does not indirect internal references.
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} main.c -o main-${ARCH} -flat_namespace 
+       otool -Iv main-${ARCH} | grep _foo | ${FAIL_IF_STDIN}
+       ${PASS_IFF_GOOD_MACHO} main-${ARCH}
+
+clean:
+       rm  main-*
diff --git a/unit-tests/test-cases/flat-main/main.c b/unit-tests/test-cases/flat-main/main.c
new file mode 100644 (file)
index 0000000..6014829
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+void foo() {}
+
+
+int main()
+{
+       foo();
+       fprintf(stdout, "hello\n");
+}
diff --git a/unit-tests/test-cases/got-elimination/Makefile b/unit-tests/test-cases/got-elimination/Makefile
new file mode 100644 (file)
index 0000000..e856b71
--- /dev/null
@@ -0,0 +1,48 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Check that ld can remove non-lazy pointers for x86_64
+#
+
+all: all-${ARCH}
+
+all-ppc: all-true
+
+all-ppc64: all-true
+
+all-i386: all-true
+
+all-true:
+       ${PASS_IFF} true
+
+all-x86_64:
+       ${CC} ${CCFLAGS} foo.c bar.c -dynamiclib -o libfoobar.dylib 
+       otool -Iv libfoobar.dylib  | grep 0x | ${FAIL_IF_STDIN}
+       ${CC} ${CCFLAGS} foo.c bar.c -dynamiclib -o libfoobar.dylib -flat_namespace
+       otool -Iv libfoobar.dylib  | grep 0x | ${PASS_IFF_STDIN}
+
+clean:
+       rm -rf libfoobar.dylib
diff --git a/unit-tests/test-cases/got-elimination/bar.c b/unit-tests/test-cases/got-elimination/bar.c
new file mode 100644 (file)
index 0000000..781c6fd
--- /dev/null
@@ -0,0 +1,28 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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@
+ */
+
+int bar1 = 1;
+int bar2 = 2;
+int bar3 = 3;
+
diff --git a/unit-tests/test-cases/got-elimination/foo.c b/unit-tests/test-cases/got-elimination/foo.c
new file mode 100644 (file)
index 0000000..45675a3
--- /dev/null
@@ -0,0 +1,42 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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@
+ */
+
+extern int bar1;
+extern int bar2; // just under 2GB array
+extern int bar3;
+
+int getbar1()
+{
+       return bar1;
+}
+
+int getbar2()
+{
+       return bar2;
+}
+
+int getbar3()
+{
+       return bar3;
+}
index e4393cd255ed80e10f83a603101f3768c461c05f..d8cdd51663cde30e7527fc5142781a88b011af23 100644 (file)
@@ -35,6 +35,4 @@ all:
        ${PASS_IFF_GOOD_MACHO} hello-${ARCH}
 
 clean:
-       rm  hello-${ARCH}
-       
-
+       rm  hello-*
diff --git a/unit-tests/test-cases/header-pad/comment.txt b/unit-tests/test-cases/header-pad/comment.txt
new file mode 100644 (file)
index 0000000..79114eb
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a hello-world program with no errors (or crashes)
index 5ce56ccb588e304843bb25bf17be8d23aa48ca92..a1ade02be206a7a2ae85eda9fe19126e6b089bbb 100644 (file)
@@ -35,6 +35,4 @@ all:
        ${PASS_IFF_GOOD_MACHO} hello-${ARCH}
 
 clean:
-       rm  hello-${ARCH}
-       
-
+       rm  hello-*
diff --git a/unit-tests/test-cases/hello-world/comment.txt b/unit-tests/test-cases/hello-world/comment.txt
new file mode 100644 (file)
index 0000000..79114eb
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a hello-world program with no errors (or crashes)
diff --git a/unit-tests/test-cases/implicit-common2/Makefile.newtest b/unit-tests/test-cases/implicit-common2/Makefile.newtest
new file mode 100644 (file)
index 0000000..af93da1
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a program with a large zero-fill section
+#
+
+run: all
+
+all:
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c test.c -o test-${ARCH}.o
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c a.c -o a-${ARCH}.o
+       ${FAIL_IF_ERROR} ar -r libtest-${ARCH}.a test-${ARCH}.o 2>/dev/null
+       #ranlib libtest-${ARCH}.a
+       #${FAIL_IF_ERROR} ${CC} ${LDFLAGS} a-${ARCH}.o -L. -ltest-${ARCH} -o a-${ARCH}
+       #${PASS_IFF_GOOD_MACHO} a-${ARCH}
+
+       ${FAIL_IF_ERROR} ar -r libtest-${ARCH}.a test-${ARCH}.o a-${ARCH}.o 2>/dev/null
+       ${FAIL_IF_ERROR} ranlib libtest-${ARCH}.a
+       ${FAIL_IF_ERROR} ${CC} ${LDFLAGS} a-${ARCH}.o -L. -ltest-${ARCH} -o a-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} a-${ARCH}
+
+clean:
+       rm -rf *.o *.a
diff --git a/unit-tests/test-cases/implicit-common2/a.c b/unit-tests/test-cases/implicit-common2/a.c
new file mode 100644 (file)
index 0000000..8f92c9d
--- /dev/null
@@ -0,0 +1,7 @@
+extern int common_variable;
+
+int
+main(int argc, char **argv)
+{
+       return common_variable;
+}
diff --git a/unit-tests/test-cases/implicit-common2/comment.txt b/unit-tests/test-cases/implicit-common2/comment.txt
new file mode 100644 (file)
index 0000000..a1710c1
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a program with a large zero-fill section
diff --git a/unit-tests/test-cases/implicit-common2/test.c b/unit-tests/test-cases/implicit-common2/test.c
new file mode 100644 (file)
index 0000000..94578c6
--- /dev/null
@@ -0,0 +1,26 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+int common_variable;
+extern int main();
diff --git a/unit-tests/test-cases/implicit-common3/Makefile b/unit-tests/test-cases/implicit-common3/Makefile
new file mode 100644 (file)
index 0000000..caed2d4
--- /dev/null
@@ -0,0 +1,44 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a program with a large zero-fill section
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} -c test.c -o test-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} test-${ARCH}.o
+       ${CC} ${CCFLAGS} -c a.c -o a-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} a-${ARCH}.o
+       ${FAIL_IF_ERROR} ar -r libtest-${ARCH}.a test-${ARCH}.o 2>/dev/null
+       ${FAIL_IF_ERROR} ranlib libtest-${ARCH}.a
+       ${CC} ${LDFLAGS} a-${ARCH}.o -L. -ltest-${ARCH} -o a-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} a-${ARCH}
+
+clean:
+       rm -rf *.o *.a a-*
diff --git a/unit-tests/test-cases/implicit-common3/a.c b/unit-tests/test-cases/implicit-common3/a.c
new file mode 100644 (file)
index 0000000..110842f
--- /dev/null
@@ -0,0 +1,8 @@
+extern int common_var;
+int *fn();
+
+int
+main(int argc, char **argv)
+{
+       return 0!=&common_var;
+}
diff --git a/unit-tests/test-cases/implicit-common3/comment.txt b/unit-tests/test-cases/implicit-common3/comment.txt
new file mode 100644 (file)
index 0000000..a1710c1
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a program with a large zero-fill section
diff --git a/unit-tests/test-cases/implicit-common3/test.c b/unit-tests/test-cases/implicit-common3/test.c
new file mode 100644 (file)
index 0000000..e0fd7e8
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 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@
+ */
+
+struct abc {
+       int a;
+       int b;
+       int c;
+} struct_var;
+
+int common_var;
+extern const int defined_var;
+
+int *fn()
+{
+       return &common_var;
+}
diff --git a/unit-tests/test-cases/implicit-common4/Makefile.newtest b/unit-tests/test-cases/implicit-common4/Makefile.newtest
new file mode 100644 (file)
index 0000000..d70c634
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a program with a large zero-fill section
+#
+
+run: all
+
+all:
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c test.c -o test-${ARCH}.o
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c a.c -o a-${ARCH}.o
+       ${FAIL_IF_ERROR} libtool -o libtest-${ARCH}.a test-${ARCH}.o
+       #${FAIL_IF_ERROR} ${CC} ${LDFLAGS} a-${ARCH}.o -L. -ltest-${ARCH} -o a-${ARCH}
+       #${PASS_IFF_GOOD_MACHO} a-${ARCH}
+
+       ${FAIL_IF_ERROR} libtool -o libtest-${ARCH}.a test-${ARCH}.o a-${ARCH}.o
+       ${FAIL_IF_ERROR} ${CC} ${LDFLAGS} a-${ARCH}.o -L. -ltest-${ARCH} -o a-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} a-${ARCH}
+
+clean:
+       rm -rf *.o *.a
diff --git a/unit-tests/test-cases/implicit-common4/a.c b/unit-tests/test-cases/implicit-common4/a.c
new file mode 100644 (file)
index 0000000..8f92c9d
--- /dev/null
@@ -0,0 +1,7 @@
+extern int common_variable;
+
+int
+main(int argc, char **argv)
+{
+       return common_variable;
+}
diff --git a/unit-tests/test-cases/implicit-common4/comment.txt b/unit-tests/test-cases/implicit-common4/comment.txt
new file mode 100644 (file)
index 0000000..a1710c1
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a program with a large zero-fill section
diff --git a/unit-tests/test-cases/implicit-common4/test.c b/unit-tests/test-cases/implicit-common4/test.c
new file mode 100644 (file)
index 0000000..94578c6
--- /dev/null
@@ -0,0 +1,26 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+int common_variable;
+extern int main();
diff --git a/unit-tests/test-cases/implicit-common5/Makefile.newtest b/unit-tests/test-cases/implicit-common5/Makefile.newtest
new file mode 100644 (file)
index 0000000..d5b6d73
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a program with a large zero-fill section
+#
+
+run: all
+
+all:
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c test.c -o test-${ARCH}.o
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c a.c -o a-${ARCH}.o
+       ${FAIL_IF_ERROR} libtool -o libtest-${ARCH}.a test-${ARCH}.o
+       ${FAIL_IF_ERROR} ${CC} ${LDFLAGS} a-${ARCH}.o -L. -ltest-${ARCH} -o a-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} a-${ARCH}
+
+clean:
+       rm -rf *.o *a
diff --git a/unit-tests/test-cases/implicit-common5/a.c b/unit-tests/test-cases/implicit-common5/a.c
new file mode 100644 (file)
index 0000000..8f92c9d
--- /dev/null
@@ -0,0 +1,7 @@
+extern int common_variable;
+
+int
+main(int argc, char **argv)
+{
+       return common_variable;
+}
diff --git a/unit-tests/test-cases/implicit-common5/comment.txt b/unit-tests/test-cases/implicit-common5/comment.txt
new file mode 100644 (file)
index 0000000..a1710c1
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a program with a large zero-fill section
diff --git a/unit-tests/test-cases/implicit-common5/test.c b/unit-tests/test-cases/implicit-common5/test.c
new file mode 100644 (file)
index 0000000..f34267a
--- /dev/null
@@ -0,0 +1,25 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+int common_variable;
index 32cb276dc9407635325c546bf44683c16c69c4d6..e3056a519f3eddf7d845aa9fc44f17b2d3cf0291 100644 (file)
@@ -36,11 +36,11 @@ run: all
 
 all: 
        ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
        ${CC} ${CCFLAGS} foo.c libbar.dylib -dynamiclib -o libfoo.dylib 
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
        ${FAIL_IF_SUCCESS} ${CC} ${CCFLAGS} main.c -o main libfoo.dylib 2> fail.log
        grep ordinal fail.log | ${PASS_IFF_EMPTY}
 
 clean:
-       rm libfoo.dylib libbar.dylib main fail.log
-       
-
+       rm *.dylib main fail.log
diff --git a/unit-tests/test-cases/indirect-dylib/comment.txt b/unit-tests/test-cases/indirect-dylib/comment.txt
new file mode 100644 (file)
index 0000000..311aa79
--- /dev/null
@@ -0,0 +1,4 @@
+The point of this test is a sanity check that an indirect
+library is not accidentally searched for symbols.
+
+<rdar://problem/4681062> wrong error message when symbol is found in unused indirect library#
diff --git a/unit-tests/test-cases/indirect-path-search/Makefile b/unit-tests/test-cases/indirect-path-search/Makefile
new file mode 100644 (file)
index 0000000..440dd08
--- /dev/null
@@ -0,0 +1,91 @@
+##
+# Copyright (c) 2007 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 -F and -L work when finding indirect libraries
+#
+
+
+run: all
+
+all:
+
+# build foo that re-exports bar
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib 
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -lbar -L. -sub_library libbar
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+# build an alternate libbar that also has baz
+       mkdir -p hide
+       ${CC} ${CCFLAGS} -dynamiclib bar.c baz.c -o hide/libbar.dylib -install_name libbar.dylib
+       ${FAIL_IF_BAD_MACHO} hide/libbar.dylib
+
+# build an executable that depends on a symbol in the alternate bar to validate that -L is used for indirect dylibs
+       ${CC} ${CCFLAGS} main.c -o main -lfoo -Lhide -L. 
+       ${FAIL_IF_BAD_MACHO} main
+
+
+
+# build Foo.framework that re-exports Bar.framework
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar"
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -framework Bar -sub_umbrella Bar
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+
+# build an alternate Bar.framework that also has baz
+       mkdir -p hide/Bar.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c baz.c -o hide/Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar"
+       ${FAIL_IF_BAD_MACHO} hide/Bar.framework/Bar
+
+# build an executable that depends on a symbol in the alternate Bar.framework to validate that -F is used for indirect dylibs
+       ${CC} ${CCFLAGS} main.c -o main -Fhide -F. -framework Foo
+       ${FAIL_IF_BAD_MACHO} main
+
+
+
+# build foo that links against bar
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib 
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib libbar.dylib  
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+# build an alternate libbar that also has baz
+       mkdir -p hide
+       ${CC} ${CCFLAGS} -dynamiclib bar.c baz.c -o hide/libbar.dylib -install_name libbar.dylib
+       ${FAIL_IF_BAD_MACHO} hide/libbar.dylib
+
+# build a flat executable that depends on a symbol in the alternate bar to validate that -L is used for indirect dylibs
+       ${CC} ${CCFLAGS} -flat_namespace main.c -o main -lfoo -Lhide -L. 
+       ${PASS_IFF_GOOD_MACHO} main
+
+
+
+
+
+clean:
+
+       rm -rf hide libbar.dylib libfoo.dylib Foo.framework Bar.framework main
diff --git a/unit-tests/test-cases/indirect-path-search/bar.c b/unit-tests/test-cases/indirect-path-search/bar.c
new file mode 100644 (file)
index 0000000..9c18401
--- /dev/null
@@ -0,0 +1,5 @@
+
+int bar (void)
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/indirect-path-search/baz.c b/unit-tests/test-cases/indirect-path-search/baz.c
new file mode 100644 (file)
index 0000000..af6a9f8
--- /dev/null
@@ -0,0 +1,5 @@
+
+int baz (void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/indirect-path-search/foo.c b/unit-tests/test-cases/indirect-path-search/foo.c
new file mode 100644 (file)
index 0000000..d0cdf47
--- /dev/null
@@ -0,0 +1,4 @@
+int foo (void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/indirect-path-search/main.c b/unit-tests/test-cases/indirect-path-search/main.c
new file mode 100644 (file)
index 0000000..f02701a
--- /dev/null
@@ -0,0 +1,8 @@
+extern int foo ();
+extern int bar ();
+extern int baz ();
+
+int main (void)
+{
+  return foo() + bar() + baz();
+}
diff --git a/unit-tests/test-cases/large-data/Makefile b/unit-tests/test-cases/large-data/Makefile
new file mode 100644 (file)
index 0000000..408a2da
--- /dev/null
@@ -0,0 +1,50 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Check that ld can link > 4GB zero fill section
+#
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+ifeq (,${findstring 64,$(ARCH)})
+       32BIT_SHOULD_FAIL = ${FAIL_IF_SUCCESS}
+else
+       32BIT_SHOULD_FAIL = 
+endif
+
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} test1.c -c -o test1.o
+       ${CC} ${CCFLAGS} test2.c -c -o test2.o
+       ${CC} ${CCFLAGS} test3.c -c -o test3.o
+       ${CC} ${CCFLAGS} test4.c -c -o test4.o
+       ${32BIT_SHOULD_FAIL} ${CC} ${CCFLAGS} test1.o test2.o test3.o test4.o -dynamiclib -o libtest.dylib 2> fail.log
+       ${PASS_IFF} true
+
+clean:
+       rm -rf test*.o libtest.dylib fail.log
diff --git a/unit-tests/test-cases/large-data/test1.c b/unit-tests/test-cases/large-data/test1.c
new file mode 100644 (file)
index 0000000..2d9ec94
--- /dev/null
@@ -0,0 +1,42 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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@
+ */
+
+int mediumarray1[1000];
+int bigarray1[500000000]; // just under 2GB array
+int small1;
+
+int getbig1()
+{
+       return bigarray1[0];
+}
+
+int getmedium1()
+{
+       return mediumarray1[0];
+}
+
+int getsmall1()
+{
+       return small1;
+}
diff --git a/unit-tests/test-cases/large-data/test2.c b/unit-tests/test-cases/large-data/test2.c
new file mode 100644 (file)
index 0000000..d97bed1
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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@
+ */
+
+int bigarray2[500000000]; // just under 2GB array
+int small2;
+
+int getbig2()
+{
+       return bigarray2[0];
+}
+
+
+int getsmall2()
+{
+       return small2;
+}
diff --git a/unit-tests/test-cases/large-data/test3.c b/unit-tests/test-cases/large-data/test3.c
new file mode 100644 (file)
index 0000000..b7ca398
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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@
+ */
+
+int bigarray3[500000000]; // just under 2GB array
+int small3;
+
+int getbig3()
+{
+       return bigarray3[0];
+}
+
+
+int getsmall3()
+{
+       return small3;
+}
diff --git a/unit-tests/test-cases/large-data/test4.c b/unit-tests/test-cases/large-data/test4.c
new file mode 100644 (file)
index 0000000..d879c5c
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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@
+ */
+
+int bigarray4[500000000]; // just under 2GB array
+int small4;
+
+int getbig4()
+{
+       return bigarray4[0];
+}
+
+
+int getsmall4()
+{
+       return small4;
+}
index 209d5a30e810d19e99eabf98e7dc0b09476da398..e3a0d6500d9795b3123db608cf1eaba1fd56eb02 100644 (file)
@@ -38,6 +38,4 @@ all:
        ${FAIL_IFF} cat link_error-${ARCH}  2> fail.log
 
 clean:
-       rm link_error-${ARCH} fail.log
-       
-
+       rm link_error-* fail.log
diff --git a/unit-tests/test-cases/late-link-error/comment.txt b/unit-tests/test-cases/late-link-error/comment.txt
new file mode 100644 (file)
index 0000000..716686d
--- /dev/null
@@ -0,0 +1,2 @@
+The point of this test is a sanity check that if
+ld errors out during linking, that no output file is remaining
index b27351bafec9fed53cdc09c895d8ca4e27b5624d..15f3307c414a9ed6268c9b9f7669d70c89066f48 100644 (file)
@@ -32,14 +32,15 @@ run: all
 
 all:
        ${CC} ${ASMFLAGS} cstring-align-0.s -c -o cstring-align-0-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} cstring-align-0-${ARCH}.o
+
        ${CC} ${ASMFLAGS} cstring-align-3.s -c -o cstring-align-3-${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} cstring-align-3-${ARCH}.o | grep 'align:' > align-3
+
        ${LD} -arch ${ARCH} -r cstring-align-0-${ARCH}.o cstring-align-3-${ARCH}.o -o cstring-r-${ARCH}.o
-       ${OBJECTDUMP} cstring-align-3-${ARCH}.o | grep 'align:' > align-3
-       ${OBJECTDUMP} cstring-r-${ARCH}.o | grep 'align:' > align-r
-       ${PASS_IFF} diff align-3  align-r
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} cstring-r-${ARCH}.o | grep 'align:' > align-r
 
-clean:
-       rm -rf cstring-align-0-${ARCH}.o cstring-align-3-${ARCH}.o cstring-r-${ARCH}.o align-3 align-r
-               
-       
+       ${PASS_IFF} diff align-3 align-r
 
+clean:
+       rm -rf *.o align-3 align-r
diff --git a/unit-tests/test-cases/literals-coalesce-alignment2/Makefile b/unit-tests/test-cases/literals-coalesce-alignment2/Makefile
new file mode 100644 (file)
index 0000000..c3c8c80
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+LD=ld
+
+#
+# The point of this test is to verify that when two cstrings
+# are coalesced that the one with greater alignment is used.
+#
+
+run: all
+
+all:
+       ${CC} ${ASMFLAGS} cstring-align-0.s -c -o cstring-align-0-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} cstring-align-0-${ARCH}.o
+
+       ${CC} ${ASMFLAGS} cstring-align-3.s -c -o cstring-align-3-${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -align -only cstring=hello cstring-align-3-${ARCH}.o > align-3
+
+       ${LD} -arch ${ARCH} -r cstring-align-0-${ARCH}.o cstring-align-3-${ARCH}.o -o cstring-r-${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -align -only cstring=hello cstring-r-${ARCH}.o > align-r
+       ${PASS_IFF} diff -C 6 align-3 align-r
+
+clean:
+       rm -rf *.o align-3 align-r
diff --git a/unit-tests/test-cases/literals-coalesce-alignment2/comment.txt b/unit-tests/test-cases/literals-coalesce-alignment2/comment.txt
new file mode 100644 (file)
index 0000000..3b2e3c7
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to verify that when two cstrings are coalesced that the one with greater alignment is used.
diff --git a/unit-tests/test-cases/literals-coalesce-alignment2/cstring-align-0.s b/unit-tests/test-cases/literals-coalesce-alignment2/cstring-align-0.s
new file mode 100644 (file)
index 0000000..1a55cf6
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006 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@
+ */
+
+       
+       .cstring
+L20:   .asciz "XXX"
+L22:   .ascii "hell\0"
diff --git a/unit-tests/test-cases/literals-coalesce-alignment2/cstring-align-3.s b/unit-tests/test-cases/literals-coalesce-alignment2/cstring-align-3.s
new file mode 100644 (file)
index 0000000..211aa72
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2006 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@
+ */
+
+       .cstring
+       .align 2
+L21: .ascii "hell\0"
+       .align 13
+L99:   .ascii "\0"
diff --git a/unit-tests/test-cases/literals-coalesce-alignment3/Makefile b/unit-tests/test-cases/literals-coalesce-alignment3/Makefile
new file mode 100644 (file)
index 0000000..cac20b9
--- /dev/null
@@ -0,0 +1,48 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#LD=ld64
+
+#
+# The point of this test is to verify that when two cstrings
+# are coalesced that the one with greater alignment is used.
+#
+
+run: all
+
+all:
+       ${CC} ${ASMFLAGS} cstring-align-0.s -c -o cstring-align-0-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} cstring-align-0-${ARCH}.o
+
+       ${CC} ${ASMFLAGS} cstring-align-3.s -c -o cstring-align-3-${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -align -only cstring=hello cstring-align-3-${ARCH}.o > align-3
+
+       ${LD} -arch ${ARCH} -r cstring-align-0-${ARCH}.o cstring-align-3-${ARCH}.o -o cstring-r-${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -align -only cstring=hello cstring-r-${ARCH}.o > align-r
+
+       ${PASS_IFF} diff -C 6 align-3 align-r
+
+clean:
+       rm -rf *.o align-3 align-r
diff --git a/unit-tests/test-cases/literals-coalesce-alignment3/comment.txt b/unit-tests/test-cases/literals-coalesce-alignment3/comment.txt
new file mode 100644 (file)
index 0000000..3b2e3c7
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to verify that when two cstrings are coalesced that the one with greater alignment is used.
diff --git a/unit-tests/test-cases/literals-coalesce-alignment3/cstring-align-0.s b/unit-tests/test-cases/literals-coalesce-alignment3/cstring-align-0.s
new file mode 100644 (file)
index 0000000..1a55cf6
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006 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@
+ */
+
+       
+       .cstring
+L20:   .asciz "XXX"
+L22:   .ascii "hell\0"
diff --git a/unit-tests/test-cases/literals-coalesce-alignment3/cstring-align-3.s b/unit-tests/test-cases/literals-coalesce-alignment3/cstring-align-3.s
new file mode 100644 (file)
index 0000000..211aa72
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2006 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@
+ */
+
+       .cstring
+       .align 2
+L21: .ascii "hell\0"
+       .align 13
+L99:   .ascii "\0"
index 80465f8953224aa77bf4e7df9c549fbd6c44458e..dcf1dbefc84df607d7685cdc8a982de14903199f 100644 (file)
@@ -32,12 +32,9 @@ run: all
 
 all:
        ${CC} ${ASMFLAGS} literals.s -c -o literals-${ARCH}.o
-       ${OBJECTDUMP} literals-${ARCH}.o | grep 'name:'| uniq -c | grep -v '^   [1|2]' | ${FAIL_IF_STDIN}
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} literals-${ARCH}.o | grep 'name:'| uniq -c | grep -v '^   [1|2]' | ${FAIL_IF_STDIN}
        ${LD} -arch ${ARCH} -r literals-${ARCH}.o -o literals-r-${ARCH}.o
-       ${OBJECTDUMP} literals-r-${ARCH}.o | grep 'name:' | uniq -d | ${PASS_IFF_EMPTY}
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} literals-r-${ARCH}.o | grep 'name:' | uniq -d | ${PASS_IFF_EMPTY}
 
 clean:
-       rm -rf literals-${ARCH}.o -o literals-r-${ARCH}.o
-               
-       
-
+       rm -rf *.o
diff --git a/unit-tests/test-cases/literals-coalesce2/Makefile.newtest b/unit-tests/test-cases/literals-coalesce2/Makefile.newtest
new file mode 100644 (file)
index 0000000..0f9d1b5
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is to verify that literals are uniqued.
+# After running ld -r all duplicates should be removed.
+#
+
+run: all
+
+all:
+       ${FAIL_IF_ERROR} ${CC} ${ASMFLAGS} literals.s -c -o literals-${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -only literals-${ARCH}.o | uniq -c | grep -v '^   [1|2]' | ${FAIL_IF_STDIN}
+       ${FAIL_IF_ERROR} ${LD} -arch ${ARCH} -r literals-${ARCH}.o -o literals-r-${ARCH}.o
+       ${PASS_IFF} ./test.sh literals-r-${ARCH}.o
+
+clean:
+       rm -rf *.o
diff --git a/unit-tests/test-cases/literals-coalesce2/comment.txt b/unit-tests/test-cases/literals-coalesce2/comment.txt
new file mode 100644 (file)
index 0000000..56cea21
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to verify that literals are uniqued.  After running ld -r all duplicates should be removed.
diff --git a/unit-tests/test-cases/literals-coalesce2/literals.s b/unit-tests/test-cases/literals-coalesce2/literals.s
new file mode 100644 (file)
index 0000000..b8d4354
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+       .literal8
+       
+L1:    .long 12345678
+       .long 87654321
+       
+L2:    .long 12345678
+       .long 87654322
+       
+L3:    .long 22345678
+       .long 87654321
+       
+L4:    .long 12345678
+       .long 87654321
+       
+       .literal4       
+L11:.long 12345678
+L12:.long 12345679
+L13:.long 22345678
+L14:.long 12345678
+       
+       .cstring
+L21: .ascii "hello\0"
+L22: .ascii "hello,there\0"
+L23: .ascii "there\0"
+L24: .ascii "hello\0"
diff --git a/unit-tests/test-cases/literals-coalesce2/test.sh b/unit-tests/test-cases/literals-coalesce2/test.sh
new file mode 100755 (executable)
index 0000000..57a36b7
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SZ=`size "$1" | tail -n 1 | sed 's,\([0-9]*\).*,\1,'`
+[ "$SZ" ] && [ "$SZ" = 54 ] && exit 0
+exit 1
diff --git a/unit-tests/test-cases/llvm-integration/Makefile b/unit-tests/test-cases/llvm-integration/Makefile
new file mode 100644 (file)
index 0000000..67e2789
--- /dev/null
@@ -0,0 +1,229 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+LLVMGCC = /usr/local/bin/llvm-gcc
+LLVMGXX = /usr/local/bin/llvm-g++
+#
+# Test the we set the stack execution bit properly.
+
+run:
+       @if [ -f /usr/local/bin/llvm-gcc ] ; then \
+         $(MAKE) all ; \
+       else \
+         ${PASS_IFF} /usr/bin/true ; \
+       fi
+
+all: zero one two three four five six seven eight nine ten eleven twelve thirteen
+
+
+zero:
+       #
+       # llvm  : a.c : Dfoo3
+       # llvm  : b.c : Dfoo2
+       # MachO : main.c : Ufoo2, Ufoo3
+       #
+       #echo "Zero..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a.c -c -o a-${ARCH}.o  ${OTHER}
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm b.c -c -o b-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main.c -c -o main-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a-${ARCH}.o b-${ARCH}.o main-${ARCH}.o -o main-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main-${ARCH}
+       ${PASS_IFF} ./main-${ARCH}
+
+one:
+       #
+       # llvm  : a1.c : Dfoo3, Ufoo4
+       # llvm  : b1.c : Dfoo2, Ufoo4
+       # MachO : main1.c : Dfoo4, Ufoo2, Ufoo3
+       #
+       #echo "One..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a1.c -c -o a1-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm b1.c -c -o b1-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main1.c -c -o main1-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a1-${ARCH}.o b1-${ARCH}.o main1-${ARCH}.o -o main1-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main1-${ARCH}
+       ${PASS_IFF} ./main1-${ARCH}
+
+two:
+       #
+       # llvm  : a2.c : Dfoo3, Ufoo4
+       # llvm  : b2.c : Dfoo2, Dfoo4
+       # MachO : main2.c : Ufoo2, Ufoo3
+       #
+       #echo "Two..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a2.c -c -o a2-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm b2.c -c -o b2-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main2.c -c -o main2-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a2-${ARCH}.o b2-${ARCH}.o main2-${ARCH}.o -o main2-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main2-${ARCH}
+       ${PASS_IFF} ./main2-${ARCH}
+
+three:
+       #
+       # llvm  : a3.c : Dfoo1, Dbar
+       # llvm  : b3.c : Dfoo2, Ubar
+       # MachO : main3.c : Ufoo1, Ufoo2, Ubar
+       #
+       #echo "Three..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a3.c -c -o a3-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm b3.c -c -o b3-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main3.c -c -o main3-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a3-${ARCH}.o b3-${ARCH}.o main3-${ARCH}.o -o main3-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main3-${ARCH}
+       ${PASS_IFF} ./main3-${ARCH}
+
+four:
+       #
+       # llvm  : a4.c : Dfoo3, Ufoo4
+       # llvm  : b4.c : Dfoo2, DLmyfoo, Ufoo4
+       # MachO : main4.c : Dfoo4, Ufoo2, Ufoo3
+       #
+       #echo "Four..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a4.c -c -o a4-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm b4.c -c -o b4-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main4.c -c -o main4-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a4-${ARCH}.o b4-${ARCH}.o main4-${ARCH}.o -o main4-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main4-${ARCH}
+       ${PASS_IFF} ./main4-${ARCH}
+
+five:
+       #
+       # llvm  : a5.c : Dfoo1, Ufoo2, Ufoo3
+       # llvm  : b5.c : Dfoo2
+       # MachO : main5.c : Dfoo3, Ufoo1
+       #
+       #echo "Five..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a5.c -c -o a5-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm b5.c -c -o b5-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main5.c -c -o main5-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a5-${ARCH}.o b5-${ARCH}.o main5-${ARCH}.o -o main5-${ARCH}  -Wl,-dead_strip
+       ${PASS_IFF_GOOD_MACHO} main5-${ARCH}
+       ${PASS_IFF} ./main5-${ARCH}
+       ${OTOOL} -tV main5-${ARCH} | grep foo3 | ${PASS_IFF_EMPTY}
+
+six:
+       #
+       # llvm  : a6.c : Dfoo1, Dfoo2
+       # MachO : main6.c : Ufoo1
+       #
+       #echo "Six..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a6.c -c -o a6-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main6.c -c -o main6-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a6-${ARCH}.o  main6-${ARCH}.o -o main6-${ARCH}  -Wl,-dead_strip
+       ${PASS_IFF_GOOD_MACHO} main6-${ARCH}
+       ${PASS_IFF} ./main6-${ARCH}
+       ${OTOOL} -tV main6-${ARCH} | grep foo2 | ${PASS_IFF_EMPTY}
+
+seven:
+       #
+       # llvm  : a7.c : Dfoo1, Dfoo2, Ufoo3
+       # llvm  : b7.c : Dfoo3, ufoo2
+       # MachO : main7.c : Ufoo1
+       #
+       #echo "Seven..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a7.c -c -o a7-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm b7.c -c -o b7-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main7.c -c -o main7-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a7-${ARCH}.o b7-${ARCH}.o  main7-${ARCH}.o -o main7-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main7-${ARCH}
+       ${PASS_IFF} ./main7-${ARCH}
+
+eight:
+       #
+       # llvm  : a8.c : Dfoo1, Dfoo2
+       # MachO : main8.c : Ufoo1
+       #
+       #echo "Eight..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a8.c -c -o a8-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main8.c -c -o main8-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a8-${ARCH}.o main8-${ARCH}.o -o main8-${ARCH}   -Wl,-dead_strip
+       ${PASS_IFF} ./main8-${ARCH}
+       ${OTOOL} -tV main8-${ARCH} | grep foo2 | ${PASS_IFF_EMPTY}
+       ${OTOOL} -tV main8-${ARCH} | grep unnamed_2_1 | ${PASS_IFF_EMPTY}
+
+nine:
+       #
+       # llvm  : a9.c : Dfoo1, Dfoo2, Dfoo3, Ufoo3, Ufoo4
+       # MachO : main9.c : Ufoo1, Dfoo4
+       #
+       #echo "Nine..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a9.c -c -o a9-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main9.c -c -o main9-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a9-${ARCH}.o main9-${ARCH}.o -o main9-${ARCH}   -Wl,-dead_strip
+       ${PASS_IFF} ./main9-${ARCH}
+       ${OTOOL} -tV main9-${ARCH} | grep foo2 | ${PASS_IFF_EMPTY}
+       ${OTOOL} -tV main9-${ARCH} | grep foo4 | ${PASS_IFF_EMPTY}
+       ${OTOOL} -tV main9-${ARCH} | grep unnamed_2_1 | ${PASS_IFF_EMPTY}
+
+ten:
+       #
+       # llvm  : a10.c
+       # llvm  : b10.c
+       # MachO : main10.c
+       #
+       #echo "Ten..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a10.c -c -o a10-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm b10.c -c -o b10-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main10.c -c -o main10-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a10-${ARCH}.o b10-${ARCH}.o main10-${ARCH}.o -o main10-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main10-${ARCH}
+
+eleven:
+       #
+       # llvm  : a11.c
+       # MachO : main11.c
+       #
+       #echo "Eleven..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a11.c -c -o a11-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main11.c -c -o main11-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a11-${ARCH}.o main11-${ARCH}.o -o main11-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main11-${ARCH}
+       ./main11-${ARCH} >& /dev/null
+
+twelve:
+       #
+       # llvm  : a12.c
+       # MachO : main12.c
+       #
+       #echo "Tweleve..."
+       ${LLVMGCC} ${CCFLAGS} --emit-llvm a12.c -c -o a12-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} main12.c -c -o main12-${ARCH}.o
+       ${LLVMGCC} ${CCFLAGS} a12-${ARCH}.o main12-${ARCH}.o -o main12-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main12-${ARCH}
+       ./main12-${ARCH}
+
+thirteen:
+       #
+       # llvm : a13.cc
+       # MachO : main13.cc
+       #
+       # echo "Thirteen..."
+       ${LLVMGCC} ${CXXFLAGS} --emit-llvm a13.cc -c -o a13-${ARCH}.o
+       ${LLVMGCC} ${CXXFLAGS} main13.cc -c -o main13-${ARCH}.o
+       ${LLVMGXX} a13-${ARCH}.o main13-${ARCH}.o -o main13-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} main13-${ARCH}
+
+       
+clean:
+       rm -rf *.o main*-* big.*
diff --git a/unit-tests/test-cases/llvm-integration/a.c b/unit-tests/test-cases/llvm-integration/a.c
new file mode 100644 (file)
index 0000000..0c96178
--- /dev/null
@@ -0,0 +1,5 @@
+int foo3()
+{
+       return 21;
+}
+
diff --git a/unit-tests/test-cases/llvm-integration/a1.c b/unit-tests/test-cases/llvm-integration/a1.c
new file mode 100644 (file)
index 0000000..f9fb403
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+extern int foo4();
+int foo3()
+{
+/*       printf ("%s\n",strerror(errno)); */
+       return foo4();
+}
+
diff --git a/unit-tests/test-cases/llvm-integration/a10.c b/unit-tests/test-cases/llvm-integration/a10.c
new file mode 100644 (file)
index 0000000..0dc181e
--- /dev/null
@@ -0,0 +1,5 @@
+extern void foo(void);
+
+void foo(void)
+{
+}
diff --git a/unit-tests/test-cases/llvm-integration/a11.c b/unit-tests/test-cases/llvm-integration/a11.c
new file mode 100644 (file)
index 0000000..e95dc40
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+void foo3(void)
+{
+  fputc ('x', stderr);
+  printf ("\n");
+}
diff --git a/unit-tests/test-cases/llvm-integration/a12.c b/unit-tests/test-cases/llvm-integration/a12.c
new file mode 100644 (file)
index 0000000..80bc1e8
--- /dev/null
@@ -0,0 +1,8 @@
+#include "a12.h"
+
+enum E e[1000];
+void foo(void)
+{
+  e[1] = ONE;
+}
+
diff --git a/unit-tests/test-cases/llvm-integration/a12.h b/unit-tests/test-cases/llvm-integration/a12.h
new file mode 100644 (file)
index 0000000..be43955
--- /dev/null
@@ -0,0 +1,8 @@
+enum E
+  {
+    ZERO,
+    ONE
+  };
+    
+extern enum E e[1000];
+extern void foo(void);
diff --git a/unit-tests/test-cases/llvm-integration/a13.cc b/unit-tests/test-cases/llvm-integration/a13.cc
new file mode 100644 (file)
index 0000000..edc938a
--- /dev/null
@@ -0,0 +1,3 @@
+#include "a13.h"
+
+A::~A() {}
diff --git a/unit-tests/test-cases/llvm-integration/a13.h b/unit-tests/test-cases/llvm-integration/a13.h
new file mode 100644 (file)
index 0000000..bc00448
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+class A {
+ public:
+  virtual ~A();
+  void foo() { printf ("Hi\n"); }
+};
diff --git a/unit-tests/test-cases/llvm-integration/a2.c b/unit-tests/test-cases/llvm-integration/a2.c
new file mode 100644 (file)
index 0000000..0eb20c5
--- /dev/null
@@ -0,0 +1,6 @@
+extern int foo4(void);
+int foo3()
+{
+       return foo4();
+}
+
diff --git a/unit-tests/test-cases/llvm-integration/a3.c b/unit-tests/test-cases/llvm-integration/a3.c
new file mode 100644 (file)
index 0000000..040ca5f
--- /dev/null
@@ -0,0 +1,6 @@
+int bar;
+int foo1()
+{
+       return bar;
+}
+
diff --git a/unit-tests/test-cases/llvm-integration/a4.c b/unit-tests/test-cases/llvm-integration/a4.c
new file mode 100644 (file)
index 0000000..0eb20c5
--- /dev/null
@@ -0,0 +1,6 @@
+extern int foo4(void);
+int foo3()
+{
+       return foo4();
+}
+
diff --git a/unit-tests/test-cases/llvm-integration/a5.c b/unit-tests/test-cases/llvm-integration/a5.c
new file mode 100644 (file)
index 0000000..bcb22d9
--- /dev/null
@@ -0,0 +1,10 @@
+extern int foo2(void);
+extern int foo3(void);
+
+int foo1()
+{
+       int i = 42;
+       if (foo2())
+         i = foo3();
+       return i;
+}
diff --git a/unit-tests/test-cases/llvm-integration/a6.c b/unit-tests/test-cases/llvm-integration/a6.c
new file mode 100644 (file)
index 0000000..b621453
--- /dev/null
@@ -0,0 +1,10 @@
+
+int foo1()
+{
+  return 42;
+}
+
+int foo2()
+{
+  return 21;
+}
diff --git a/unit-tests/test-cases/llvm-integration/a7.c b/unit-tests/test-cases/llvm-integration/a7.c
new file mode 100644 (file)
index 0000000..560919a
--- /dev/null
@@ -0,0 +1,11 @@
+extern int foo3(void);
+
+int foo1(void)
+{
+  return foo3();
+}
+
+int foo2(void)
+{
+  return 42;
+}
diff --git a/unit-tests/test-cases/llvm-integration/a8.c b/unit-tests/test-cases/llvm-integration/a8.c
new file mode 100644 (file)
index 0000000..47352a7
--- /dev/null
@@ -0,0 +1,23 @@
+
+static signed int i = 0;
+extern int foo1(void);
+extern void foo2(void);
+
+void foo2(void) {
+
+  i = -1;
+
+}
+
+static int foo3() {
+  return 10;
+}
+
+int foo1(void)
+{
+  int data = 0;
+  if (i < 0)
+    data = foo3();
+  data += 42;
+  return data;
+}
diff --git a/unit-tests/test-cases/llvm-integration/a9.c b/unit-tests/test-cases/llvm-integration/a9.c
new file mode 100644 (file)
index 0000000..da2c8fa
--- /dev/null
@@ -0,0 +1,25 @@
+
+static signed int i = 0;
+extern int foo1(void);
+extern void foo2(void);
+extern void foo4(void);
+
+void foo2(void) {
+
+  i = -1;
+
+}
+
+static int foo3() {
+  foo4();
+  return 10;
+}
+
+int foo1(void)
+{
+  int data = 0;
+  if (i < 0)
+    data = foo3();
+  data += 42;
+  return data;
+}
diff --git a/unit-tests/test-cases/llvm-integration/a9.list b/unit-tests/test-cases/llvm-integration/a9.list
new file mode 100644 (file)
index 0000000..583bc2f
--- /dev/null
@@ -0,0 +1,3 @@
+_foo1
+_main
+_bar
diff --git a/unit-tests/test-cases/llvm-integration/b.c b/unit-tests/test-cases/llvm-integration/b.c
new file mode 100644 (file)
index 0000000..61c92dc
--- /dev/null
@@ -0,0 +1,3 @@
+int foo2() {
+       return 21;
+}
diff --git a/unit-tests/test-cases/llvm-integration/b1.c b/unit-tests/test-cases/llvm-integration/b1.c
new file mode 100644 (file)
index 0000000..5158abe
--- /dev/null
@@ -0,0 +1,4 @@
+extern int foo4();
+int foo2() {
+       return foo4();
+}
diff --git a/unit-tests/test-cases/llvm-integration/b10.c b/unit-tests/test-cases/llvm-integration/b10.c
new file mode 100644 (file)
index 0000000..d899aa9
--- /dev/null
@@ -0,0 +1,7 @@
+#include "b10.h"
+extern void foo(void);
+
+struct my_struct my_hooks = {
+  foo
+};
+
diff --git a/unit-tests/test-cases/llvm-integration/b10.h b/unit-tests/test-cases/llvm-integration/b10.h
new file mode 100644 (file)
index 0000000..fcb50d2
--- /dev/null
@@ -0,0 +1,6 @@
+struct my_struct
+{
+  void (*f)(void);
+};
+
+extern struct my_struct my_hooks;
diff --git a/unit-tests/test-cases/llvm-integration/b2.c b/unit-tests/test-cases/llvm-integration/b2.c
new file mode 100644 (file)
index 0000000..a20f6e3
--- /dev/null
@@ -0,0 +1,9 @@
+extern int foo4(void);
+
+int foo4(void)
+{
+  return 21;
+}
+int foo2() {
+       return foo4();
+}
diff --git a/unit-tests/test-cases/llvm-integration/b3.c b/unit-tests/test-cases/llvm-integration/b3.c
new file mode 100644 (file)
index 0000000..31e7ee8
--- /dev/null
@@ -0,0 +1,4 @@
+extern int bar;
+int foo2() {
+       return bar;
+}
diff --git a/unit-tests/test-cases/llvm-integration/b4.c b/unit-tests/test-cases/llvm-integration/b4.c
new file mode 100644 (file)
index 0000000..9437ad0
--- /dev/null
@@ -0,0 +1,13 @@
+extern int foo4(void);
+
+int foo4(void)
+{
+  return 21;
+}
+static int myfoo()
+{
+  return foo4();
+}
+int foo2() {
+       return myfoo();
+}
diff --git a/unit-tests/test-cases/llvm-integration/b5.c b/unit-tests/test-cases/llvm-integration/b5.c
new file mode 100644 (file)
index 0000000..a105df9
--- /dev/null
@@ -0,0 +1,4 @@
+int foo2(void)
+{
+  return 0;
+}
diff --git a/unit-tests/test-cases/llvm-integration/b7.c b/unit-tests/test-cases/llvm-integration/b7.c
new file mode 100644 (file)
index 0000000..d34f91a
--- /dev/null
@@ -0,0 +1,7 @@
+extern int foo2(void);
+extern int foo3(void);
+
+int foo3(void)
+{
+  return foo2();
+}
diff --git a/unit-tests/test-cases/llvm-integration/main.c b/unit-tests/test-cases/llvm-integration/main.c
new file mode 100644 (file)
index 0000000..ac424ca
--- /dev/null
@@ -0,0 +1,9 @@
+extern int foo2();
+extern int foo3();
+int main(){
+       int i = foo3() + foo2();
+       if (i == 42)
+         return 0;
+       else
+         return 1;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main1.c b/unit-tests/test-cases/llvm-integration/main1.c
new file mode 100644 (file)
index 0000000..ccad10d
--- /dev/null
@@ -0,0 +1,13 @@
+extern int foo2();
+extern int foo3();
+int foo4()
+{
+  return 21;
+}
+int main(){
+       int i = foo3() + foo2();
+       if (i == 42)
+         return 0;
+       else
+         return 1;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main10.c b/unit-tests/test-cases/llvm-integration/main10.c
new file mode 100644 (file)
index 0000000..dabcdcf
--- /dev/null
@@ -0,0 +1,10 @@
+#include "b10.h"
+
+int main()
+{
+  struct my_struct *mh = &my_hooks;
+
+  mh->f();
+
+  return 0;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main11.c b/unit-tests/test-cases/llvm-integration/main11.c
new file mode 100644 (file)
index 0000000..82ef7ff
--- /dev/null
@@ -0,0 +1,7 @@
+
+extern void foo3(void);
+int main()
+{
+  foo3();
+  return 0;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main12.c b/unit-tests/test-cases/llvm-integration/main12.c
new file mode 100644 (file)
index 0000000..4de8725
--- /dev/null
@@ -0,0 +1,7 @@
+#include "a12.h"
+int main()
+{
+  e[0] = ZERO;
+  foo();
+  return e[0];
+}
diff --git a/unit-tests/test-cases/llvm-integration/main13.cc b/unit-tests/test-cases/llvm-integration/main13.cc
new file mode 100644 (file)
index 0000000..697d81b
--- /dev/null
@@ -0,0 +1,8 @@
+#include "a13.h"
+
+int main()
+{
+  A a;
+  a.foo();
+  return 0;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main2.c b/unit-tests/test-cases/llvm-integration/main2.c
new file mode 100644 (file)
index 0000000..ac424ca
--- /dev/null
@@ -0,0 +1,9 @@
+extern int foo2();
+extern int foo3();
+int main(){
+       int i = foo3() + foo2();
+       if (i == 42)
+         return 0;
+       else
+         return 1;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main3.c b/unit-tests/test-cases/llvm-integration/main3.c
new file mode 100644 (file)
index 0000000..a5058fe
--- /dev/null
@@ -0,0 +1,13 @@
+extern int foo1();
+extern int foo2();
+extern int bar;
+int main(){
+        int i;
+       bar = 14;
+       i = foo1() + foo2() + bar;
+       if (i == 42)
+         return 0;
+       else
+         return 1;
+
+}
diff --git a/unit-tests/test-cases/llvm-integration/main4.c b/unit-tests/test-cases/llvm-integration/main4.c
new file mode 100644 (file)
index 0000000..ac424ca
--- /dev/null
@@ -0,0 +1,9 @@
+extern int foo2();
+extern int foo3();
+int main(){
+       int i = foo3() + foo2();
+       if (i == 42)
+         return 0;
+       else
+         return 1;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main5.c b/unit-tests/test-cases/llvm-integration/main5.c
new file mode 100644 (file)
index 0000000..28d551d
--- /dev/null
@@ -0,0 +1,16 @@
+
+extern int foo1(void);
+
+int foo3(void)
+{
+  return 42;
+}
+
+int main()
+{
+  int i = foo1();
+  if (i == 42)
+    return 0;
+  else
+    return 1;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main6.c b/unit-tests/test-cases/llvm-integration/main6.c
new file mode 100644 (file)
index 0000000..3d00382
--- /dev/null
@@ -0,0 +1,10 @@
+extern int foo1();
+
+int main()
+{
+  int i = foo1();
+  if (i == 42)
+    return 0;
+  else
+    return 1;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main7.c b/unit-tests/test-cases/llvm-integration/main7.c
new file mode 100644 (file)
index 0000000..22427e3
--- /dev/null
@@ -0,0 +1,10 @@
+extern int foo1(void);
+
+int main(void)
+{
+  int i = foo1();
+  if (i == 42)
+    return 0;
+  else
+    return 1;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main8.c b/unit-tests/test-cases/llvm-integration/main8.c
new file mode 100644 (file)
index 0000000..a9c924d
--- /dev/null
@@ -0,0 +1,11 @@
+extern  int foo1(void);
+extern  void foo2(void);
+
+int main()
+{
+  int i = foo1();
+  if (i == 42)
+    return 0;
+  else
+    return 1;
+}
diff --git a/unit-tests/test-cases/llvm-integration/main9.c b/unit-tests/test-cases/llvm-integration/main9.c
new file mode 100644 (file)
index 0000000..b44bf6e
--- /dev/null
@@ -0,0 +1,14 @@
+extern  int foo1(void);
+extern  void foo2(void);
+
+void foo4(void)
+{
+}
+int main()
+{
+  int i = foo1();
+  if (i == 42)
+    return 0;
+  else
+    return 1;
+}
diff --git a/unit-tests/test-cases/loader_path/Makefile b/unit-tests/test-cases/loader_path/Makefile
new file mode 100644 (file)
index 0000000..126c10d
--- /dev/null
@@ -0,0 +1,46 @@
+##
+# Copyright (c) 2007 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
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+#
+# The point of this test is a sanity check that an indirect
+# library loaded with @loader_path works
+#
+# <rdar://problem/4019497> ld64 should handle linking against dylibs that have @loader_path based dylib load commands
+#
+
+run: all
+
+all: 
+       ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib -install_name @loader_path/libbar.dylib
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} foo.c libbar.dylib -dynamiclib -o libfoo.dylib 
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       ${CC} ${CCFLAGS} main.c -o main libfoo.dylib 
+       ${PASS_IFF_GOOD_MACHO} libfoo.dylib
+
+clean:
+       rm *.dylib main
diff --git a/unit-tests/test-cases/loader_path/bar.c b/unit-tests/test-cases/loader_path/bar.c
new file mode 100644 (file)
index 0000000..a307157
--- /dev/null
@@ -0,0 +1,6 @@
+
+int bar() 
+{
+       return 1;
+}
+
diff --git a/unit-tests/test-cases/loader_path/foo.c b/unit-tests/test-cases/loader_path/foo.c
new file mode 100644 (file)
index 0000000..8c2179d
--- /dev/null
@@ -0,0 +1,7 @@
+
+extern int bar();
+
+int foo()
+{
+       return bar();
+}
diff --git a/unit-tests/test-cases/loader_path/main.c b/unit-tests/test-cases/loader_path/main.c
new file mode 100644 (file)
index 0000000..829ca5e
--- /dev/null
@@ -0,0 +1,8 @@
+extern void foo();
+
+int main()
+{
+       foo();
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/local-symbol-partial-stripping/Makefile b/unit-tests/test-cases/local-symbol-partial-stripping/Makefile
new file mode 100644 (file)
index 0000000..8fc14f7
--- /dev/null
@@ -0,0 +1,75 @@
+##
+# Copyright (c) 2007 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
+
+#
+# This test case checks -non_global_symbols_no_strip_list and -non_global_symbols_strip_list
+# with and without wildcards
+#
+
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} main.c foo.c -o main
+       ${FAIL_IF_BAD_MACHO} main
+       nm -j main > main.nm
+       # build stripping a.list
+       ${CC} ${CCFLAGS} main.c foo.c -Wl,-non_global_symbols_strip_list,a.list -o main-a
+       ${FAIL_IF_BAD_MACHO} main-a
+       nm -j main-a > main-a.nm
+       diff main.nm main-a.nm | egrep '<|>' > a.diff
+       diff a.diff a.expect | ${FAIL_IF_STDIN}
+       # build but strip at .o file level a.list
+       ${CC} ${CCFLAGS} main.c -c -o main.o
+       ${CC} ${CCFLAGS} foo.c -c -o foo.o
+       ${LD} -r -arch ${ARCH} main.o foo.o -o all-a.o -non_global_symbols_strip_list a.list
+       ${CC} ${CCFLAGS} all-a.o -Wl,-non_global_symbols_strip_list,a.list -o main-a
+       ${FAIL_IF_BAD_MACHO} main-a
+       nm -j main-a > main-a.nm
+       diff main.nm main-a.nm | egrep '<|>' > a.diff
+       diff a.diff a.expect | ${FAIL_IF_STDIN}
+       # build stripping b.list
+       ${CC} ${CCFLAGS} main.c foo.c -Wl,-non_global_symbols_strip_list,b.list -o main-b
+       ${FAIL_IF_BAD_MACHO} main-b
+       nm -j main-b > main-b.nm
+       diff main.nm main-b.nm | egrep '<|>' > b.diff
+       diff b.diff b.expect | ${FAIL_IF_STDIN}
+       # build but strip at .o file level b.list
+       ${CC} ${CCFLAGS} main.c -c -o main.o
+       ${CC} ${CCFLAGS} foo.c -c -o foo.o
+       ${LD} -r -arch ${ARCH} main.o foo.o -o all-b.o -non_global_symbols_strip_list b.list
+       ${CC} ${CCFLAGS} all-b.o -Wl,-non_global_symbols_strip_list,b.list -o main-b
+       ${FAIL_IF_BAD_MACHO} main-b
+       nm -j main-b > main-b.nm
+       diff main.nm main-b.nm | egrep '<|>' > b.diff
+       diff b.diff b.expect | ${FAIL_IF_STDIN}
+       # build stripping c.list
+       ${CC} ${CCFLAGS} main.c foo.c -Wl,-non_global_symbols_no_strip_list,c.list -o main-c
+       nm -m main-c | grep non-external | grep -v my | ${FAIL_IF_STDIN}
+       ${PASS_IFF_GOOD_MACHO} main-c
+       
+       
+clean:
+       rm -rf main main.nm main-a main-a.nm a.diff main-b main-b.nm b.diff main-c all-a.o all-b.o foo.o main.o
diff --git a/unit-tests/test-cases/local-symbol-partial-stripping/a.expect b/unit-tests/test-cases/local-symbol-partial-stripping/a.expect
new file mode 100644 (file)
index 0000000..9ecbf53
--- /dev/null
@@ -0,0 +1,2 @@
+< _myglobal
+< _xmyglobal2
diff --git a/unit-tests/test-cases/local-symbol-partial-stripping/a.list b/unit-tests/test-cases/local-symbol-partial-stripping/a.list
new file mode 100644 (file)
index 0000000..16c59a2
--- /dev/null
@@ -0,0 +1,2 @@
+_myglobal
+_xmyglobal2
diff --git a/unit-tests/test-cases/local-symbol-partial-stripping/b.expect b/unit-tests/test-cases/local-symbol-partial-stripping/b.expect
new file mode 100644 (file)
index 0000000..f1d15e4
--- /dev/null
@@ -0,0 +1,3 @@
+< _myfunction
+< _myglobal2
+< _xmyglobal2
diff --git a/unit-tests/test-cases/local-symbol-partial-stripping/b.list b/unit-tests/test-cases/local-symbol-partial-stripping/b.list
new file mode 100644 (file)
index 0000000..97170ac
--- /dev/null
@@ -0,0 +1,2 @@
+*2
+_myf*on
diff --git a/unit-tests/test-cases/local-symbol-partial-stripping/c.list b/unit-tests/test-cases/local-symbol-partial-stripping/c.list
new file mode 100644 (file)
index 0000000..be715cd
--- /dev/null
@@ -0,0 +1 @@
+*my*
diff --git a/unit-tests/test-cases/local-symbol-partial-stripping/foo.c b/unit-tests/test-cases/local-symbol-partial-stripping/foo.c
new file mode 100644 (file)
index 0000000..42e6cb7
--- /dev/null
@@ -0,0 +1,11 @@
+
+
+int __attribute__((visibility("hidden"))) myglobal = 3;
+int __attribute__((visibility("hidden"))) myglobal2 = 3;
+int __attribute__((visibility("hidden"))) xmyglobal = 3;
+int __attribute__((visibility("hidden"))) xmyglobal2 = 3;
+
+void __attribute__((visibility("hidden"))) myfunction(int x) { }
+
+
+
diff --git a/unit-tests/test-cases/local-symbol-partial-stripping/main.c b/unit-tests/test-cases/local-symbol-partial-stripping/main.c
new file mode 100644 (file)
index 0000000..013bc55
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+extern int myglobal;
+extern void myfunction(int);
+
+int main()
+{
+       myfunction(myglobal);
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/main-stripped/Makefile b/unit-tests/test-cases/main-stripped/Makefile
new file mode 100644 (file)
index 0000000..03756ff
--- /dev/null
@@ -0,0 +1,38 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# Test that a dynamically referenced symbol is always exported
+#
+
+run: all
+
+all:
+       ${CC} main.c -o main-${ARCH} -exported_symbols_list main.exp
+       ${FAIL_IF_BAD_MACHO} main-${ARCH}
+       nm -m main-${ARCH} | grep _magicSymbol | grep "referenced dynamically" | ${PASS_IFF_STDIN}
+
+clean:
+       rm  main-*
diff --git a/unit-tests/test-cases/main-stripped/main.c b/unit-tests/test-cases/main-stripped/main.c
new file mode 100644 (file)
index 0000000..1e71f1b
--- /dev/null
@@ -0,0 +1,34 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stddef.h>
+
+// set magic "dynamically referenced" bit on magicSymbol
+int  magicSymbol = 1;
+asm(".desc _magicSymbol, 0x10");
+
+
+int main()
+{
+       return 0;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/main-stripped/main.exp b/unit-tests/test-cases/main-stripped/main.exp
new file mode 100644 (file)
index 0000000..4eb9e89
--- /dev/null
@@ -0,0 +1 @@
+_main
diff --git a/unit-tests/test-cases/missing-option-args/Makefile b/unit-tests/test-cases/missing-option-args/Makefile
new file mode 100644 (file)
index 0000000..81c3f58
--- /dev/null
@@ -0,0 +1,98 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Verify that missing arguments don't cause ld to crash
+# This tests 64-bit arguments only
+#
+
+
+OUTPUT=2>/dev/null
+LDCMD=${FAIL_IF_SUCCESS} ${LD} -arch ${ARCH} ${OUTPUT}
+
+run: all
+
+all:
+       ${FAIL_IF_SUCCESS} ${LD} -arch 2>/dev/null
+       ${LDCMD} -filelist
+       ${LDCMD} -o
+       ${LDCMD} -read_only_relocs
+       ${LDCMD} -sect_diff_relocs
+       ${LDCMD} -weak_reference_mismatches
+       ${LDCMD} -l
+       ${LDCMD} -weak-l
+       ${LDCMD} -weak-library
+       ${LDCMD} -L
+       ${LDCMD} -syslibroot
+       ${LDCMD} -framework
+       ${LDCMD} -framework name,
+       ${LDCMD} -weak_framework
+       ${LDCMD} -weak_framework name
+       ${LDCMD} -weak_framework name,
+       ${LDCMD} -F
+       ${LDCMD} -dylib_file
+       ${LDCMD} -dylib_file install_name
+       ${LDCMD} -sectcreate segname sectname
+       ${LDCMD} -sectorder
+       ${LDCMD} -sectorder segname sectname
+       ${LDCMD} -u
+       ${LDCMD} -e
+       ${LDCMD} -i
+       ${LDCMD} -idefinition:
+       ${LDCMD} -undefined
+       ${LDCMD} -U
+       ${LDCMD} -commons
+       ${LDCMD} -warn_commons
+       ${LDCMD} -exported_symbols_list
+       ${LDCMD} -unexported_symbols_list
+       ${LDCMD} -filelist
+       ${LDCMD} -filelist listfile,
+       ${LDCMD} -headerpad
+       ${LDCMD} -A
+       ${LDCMD} -dylib_install_name
+       ${LDCMD} -umbrella
+       ${LDCMD} -allowable_client
+       ${LDCMD} -client_name
+       ${LDCMD} -sub_umbrella
+       ${LDCMD} -sub_library
+       ${LDCMD} -init
+       ${LDCMD} -dylinker_install_name
+       ${LDCMD} -macosx_version_min
+       ${LDCMD} -final_output
+       ${LDCMD} -seg1addr
+       ${LDCMD} -pagezero_size
+       ${LDCMD} -dylib_compatibility_version
+       ${LDCMD} -stack_addr
+       ${LDCMD} -stack_size
+       ${LDCMD} -sectcreate
+       ${LDCMD} -sectcreate segname
+       ${LDCMD} -sectalign
+       ${LDCMD} -sectalign segname
+       ${LDCMD} -sectalign segname sectname
+       ${LDCMD} -sectorder segname
+       ${LDCMD} -dylib_current_version
+       ${PASS_IFF} true
+
+clean:
diff --git a/unit-tests/test-cases/missing-option-args/comment.txt b/unit-tests/test-cases/missing-option-args/comment.txt
new file mode 100644 (file)
index 0000000..8000102
--- /dev/null
@@ -0,0 +1 @@
+Verify that missing arguments don't cause ld to crash
index 0a8dee09f35ae43bf402c54b7fff9bbece9d2263..136bcf63731dc3dbb1b5f0b9b6091b981fa70d5d 100644 (file)
@@ -35,13 +35,12 @@ run: all
 
 all:
        ${CC} ${ASMFLAGS} test.s -c -o test.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_sort test.${ARCH}.o > test.${ARCH}.o.dump
+
        ${LD} -arch ${ARCH} -r -keep_private_externs test.${ARCH}.o -o test-r.${ARCH}.o
-       ${OBJECTDUMP} -no_sort test.${ARCH}.o > test.${ARCH}.o.dump
-       ${OBJECTDUMP} -no_sort test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_sort test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+
        ${PASS_IFF} diff test.${ARCH}.o.dump test-r.${ARCH}.o.dump
 
 clean:
-       rm -rf test.${ARCH}.o test-r.${ARCH}.o test.${ARCH}.o.dump test-r.${ARCH}.o.dump
-       
-       
-
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/multiple-entry-points/comment.txt b/unit-tests/test-cases/multiple-entry-points/comment.txt
new file mode 100644 (file)
index 0000000..4e819e1
--- /dev/null
@@ -0,0 +1,3 @@
+The point of this test is to verify a .o file can round-trip through ld -r correctly.  The ObjectDump utility is used
+dump a "canonical" textual representation of a .o file.  The before and after .o files are then diff'ed.
+No differences means this test passes
diff --git a/unit-tests/test-cases/no-dynamic-common/Makefile.newtest b/unit-tests/test-cases/no-dynamic-common/Makefile.newtest
new file mode 100644 (file)
index 0000000..d0f7df8
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is to determine if
+#  common symbols are not allowed with MH_DYLIB output format with the -multi_module option
+#
+
+run: all
+
+all:
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c test.c -o test-${ARCH}.o
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c a.c -o a-${ARCH}.o
+       ${PASS_IFF_ERROR} libtool -dynamic -o libtest-${ARCH}.a test-${ARCH}.o 2>/dev/null
+
+clean:
+       rm -rf *.o *.a
diff --git a/unit-tests/test-cases/no-dynamic-common/a.c b/unit-tests/test-cases/no-dynamic-common/a.c
new file mode 100644 (file)
index 0000000..8f92c9d
--- /dev/null
@@ -0,0 +1,7 @@
+extern int common_variable;
+
+int
+main(int argc, char **argv)
+{
+       return common_variable;
+}
diff --git a/unit-tests/test-cases/no-dynamic-common/comment.txt b/unit-tests/test-cases/no-dynamic-common/comment.txt
new file mode 100644 (file)
index 0000000..a5a960d
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to determine if common symbols are not allowed with MH_DYLIB output format with the -multi_module option
diff --git a/unit-tests/test-cases/no-dynamic-common/test.c b/unit-tests/test-cases/no-dynamic-common/test.c
new file mode 100644 (file)
index 0000000..f34267a
--- /dev/null
@@ -0,0 +1,25 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+int common_variable;
index 223c8b8e7767540ab0600e4b2bbdd1e307ae5a7c..c24abecf5ee3dca14bec1492c4b352029c177a0e 100644 (file)
@@ -38,17 +38,26 @@ all:
        rm -f foo-${ARCH}
 
 # Test with stabs
-       ${CC} ${CCFLAGS} foo.c -o foo-${ARCH} -gfull
+       ${CC} ${CCFLAGS} foo.c -o foo-${ARCH} -gfull -gstabs+
        ${FAIL_IF_BAD_MACHO} foo-${ARCH}
        ${OTOOL} -hlv foo-${ARCH} | grep LC_UUID | ${FAIL_IF_STDIN}
 
 # Test with two files one with UUID
        ${CC} ${CCFLAGS} bar.c -c -gdwarf-2
+       ${FAIL_IF_BAD_OBJ} bar.o
+
        ${LD} -arch ${ARCH} bar.o -r -o bar-${ARCH}.o -no_uuid
+       ${FAIL_IF_BAD_OBJ} bar-${ARCH}.o
+
        ${CC} ${CCFLAGS} foo.c -c -gdwarf-2
+       ${FAIL_IF_BAD_OBJ} foo.o
+
        ${LD} -arch ${ARCH} foo.o -r -o foo-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} foo-${ARCH}.o
+
        ${CC} ${CCFLAGS} foo-${ARCH}.o bar-${ARCH}.o -o temp-${ARCH}
        ${FAIL_IF_BAD_MACHO} temp-${ARCH}
+
        ${OTOOL} -hlv temp-${ARCH} | grep LC_UUID | ${FAIL_IF_EMPTY}
        rm -f foo.o bar.o foo-${ARCH}.o bar-${ARCH}.o temp-${ARCH}
 
@@ -58,4 +67,4 @@ all:
        ${OTOOL} -hlv foo-${ARCH} | grep LC_UUID | ${PASS_IFF_EMPTY}
 
 clean:
-       rm -rf foo-${ARCH} bar-${ARCH}.dylib temp-${ARCH}.dylib
+       rm -rf foo-*
diff --git a/unit-tests/test-cases/no-uuid/comment.txt b/unit-tests/test-cases/no-uuid/comment.txt
new file mode 100644 (file)
index 0000000..269bbbd
--- /dev/null
@@ -0,0 +1 @@
+Test the we set emit LC_UUID correctly
diff --git a/unit-tests/test-cases/non-lazy-r/Makefile b/unit-tests/test-cases/non-lazy-r/Makefile
new file mode 100644 (file)
index 0000000..28f94d6
--- /dev/null
@@ -0,0 +1,59 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Check that non-lazy-pointers are properly handled by -r
+#
+
+
+all: all-${ARCH}
+
+all-ppc: hasnl
+
+all-ppc64: hasnl
+
+all-i386: hasnl
+
+all-x86_64: all-true
+
+all-true:
+       ${PASS_IFF} true
+
+
+hasnl:
+       ${CC} ${CCFLAGS} -c foo.c -o foo.o
+       ${CC} ${CCFLAGS} -c other.c -o other.o
+       ${LD} -r -arch ${ARCH} foo.o other.o -o fooall.o -exported_symbol _foo
+       # make sure there  are two indirect symbols: _foo and LOCAL
+       otool -Iv fooall.o | grep "2 entries" | ${FAIL_IF_EMPTY}
+       otool -Iv fooall.o | grep _foo | ${FAIL_IF_EMPTY}
+       otool -Iv fooall.o | grep _other | ${FAIL_IF_STDIN}
+       # make sure re-parsed correctly
+       ${OBJECTDUMP} fooall.o | grep name: | grep '_foo$$non_lazy_ptr' | ${FAIL_IF_EMPTY} 
+       ${OBJECTDUMP} fooall.o | grep name: | grep '_other$$non_lazy_ptr' | ${FAIL_IF_EMPTY}
+       ${PASS_IFF} true
+       
+clean:
+       rm -rf *.o
diff --git a/unit-tests/test-cases/non-lazy-r/foo.c b/unit-tests/test-cases/non-lazy-r/foo.c
new file mode 100644 (file)
index 0000000..1fa325e
--- /dev/null
@@ -0,0 +1,12 @@
+
+
+
+extern int foo;
+
+int getfoo() { return foo; }
+
+
+extern int other;
+
+int getother() { return other; }
+
diff --git a/unit-tests/test-cases/non-lazy-r/other.c b/unit-tests/test-cases/non-lazy-r/other.c
new file mode 100644 (file)
index 0000000..6420437
--- /dev/null
@@ -0,0 +1,2 @@
+int foo = 2;
+int other = 3;
diff --git a/unit-tests/test-cases/objc-gc-checks/Makefile b/unit-tests/test-cases/objc-gc-checks/Makefile
new file mode 100644 (file)
index 0000000..ed12e39
--- /dev/null
@@ -0,0 +1,75 @@
+##
+# Copyright (c) 2007 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
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+#
+# Validate that the linker catches illegal combinations of .o files 
+# compiled with different GC settings. 
+#
+
+test:
+       ${CC} ${CCFLAGS} foo.m -c -o foo.o
+       ${FAIL_IF_BAD_OBJ} foo.o
+
+       ${CC} ${CCFLAGS} foo.m -c -o foo-gc.o -fobjc-gc
+       ${FAIL_IF_BAD_OBJ} foo-gc.o
+
+       ${CC} ${CCFLAGS} foo.m -c -o foo-gc-only.o -fobjc-gc-only
+       ${FAIL_IF_BAD_OBJ} foo-gc-only.o
+
+       ${CC} ${CCFLAGS} bar.m -c -o bar.o
+       ${FAIL_IF_BAD_OBJ} bar.o
+
+       ${CC} ${CCFLAGS} bar.m -c -o bar-gc.o -fobjc-gc
+       ${FAIL_IF_BAD_OBJ} bar-gc.o
+
+       ${CC} ${CCFLAGS} bar.m -c -o bar-gc-only.o -fobjc-gc-only
+       ${FAIL_IF_BAD_OBJ} bar-gc-only.o
+
+       # check RR + RR -> RR
+       ${CC} foo.o bar.o -dynamiclib -o libfoobar.dylib -framework Foundation
+       ${FAIL_IF_BAD_MACHO} libfoobar.dylib
+
+       # check GC/RR + GC/RR -> GC/RR
+       ${CC} foo-gc.o bar-gc.o -dynamiclib -o libfoobar.dylib -framework Foundation
+       ${FAIL_IF_BAD_MACHO} libfoobar.dylib
+
+       # check GC + GC -> GC
+       ${CC} foo-gc-only.o bar-gc-only.o -dynamiclib -o libfoobar.dylib -framework Foundation
+       ${FAIL_IF_BAD_MACHO} libfoobar.dylib
+
+       # check RR + GC/RR -> error
+       ${FAIL_IF_SUCCESS} ${CC} foo.o bar-gc.o -dynamiclib -o libfoobar.dylib -framework Foundation 2> fail.log
+
+       # check RR + GC -> error
+       ${FAIL_IF_SUCCESS} ${CC} foo.o bar-gc-only.o -dynamiclib -o libfoobar.dylib -framework Foundation 2> fail.log
+
+       # check GC + GC/RR -> error
+       ${FAIL_IF_SUCCESS} ${CC} foo-gc-only.o bar-gc.o -dynamiclib -o libfoobar.dylib -framework Foundation 2> fail.log
+       ${PASS_IFF} true
+
+clean:
+       rm -rf foo*.o bar*.o libfoobar.dylib fail.log
diff --git a/unit-tests/test-cases/objc-gc-checks/bar.m b/unit-tests/test-cases/objc-gc-checks/bar.m
new file mode 100644 (file)
index 0000000..f66df50
--- /dev/null
@@ -0,0 +1,12 @@
+#include <Foundation/Foundation.h>
+
+@interface Bar : NSObject {
+       int f;
+}
+- (void) doit;
+@end
+
+@implementation Bar
+- (void) doit { }
+@end
+
diff --git a/unit-tests/test-cases/objc-gc-checks/comment.txt b/unit-tests/test-cases/objc-gc-checks/comment.txt
new file mode 100644 (file)
index 0000000..953da58
--- /dev/null
@@ -0,0 +1 @@
+Validate that the linker catches illegal combintations of .o files compiled with different GC settings
diff --git a/unit-tests/test-cases/objc-gc-checks/foo.m b/unit-tests/test-cases/objc-gc-checks/foo.m
new file mode 100644 (file)
index 0000000..5324bea
--- /dev/null
@@ -0,0 +1,12 @@
+#include <Foundation/Foundation.h>
+
+@interface Foo : NSObject {
+       int f;
+}
+- (void) doit;
+@end
+
+@implementation Foo
+- (void) doit { }
+@end
+
index 169963b576f0f619afa24137917ebc980fca4539..a11f1d0df31127ee7f36cc99368960d6dee45a50 100644 (file)
@@ -33,16 +33,15 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} test.m -c -o test.${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} test.${ARCH}.o
+
        ${LD} -arch ${ARCH} -r test.${ARCH}.o -o test-r.${ARCH}.o
-       nm test-r.${ARCH}.o | grep '.objc_class_name_NSObject' | ${FAIL_IF_EMPTY} 
-       nm test-r.${ARCH}.o | grep '.objc_class_name_NSData'   | ${FAIL_IF_EMPTY} 
-       nm test-r.${ARCH}.o | grep '.objc_class_name_NSArray'  | ${FAIL_IF_EMPTY} 
-       nm test-r.${ARCH}.o | grep '.objc_class_name_NSString' | ${PASS_IFF_STDIN} 
+       ${FAIL_IF_BAD_OBJ} test-r.${ARCH}.o
 
-clean:
-       rm -rf test.${ARCH}.o test.${ARCH}.o.dump
-               
+       nm test-r.${ARCH}.o | grep -i 'objc_class_.*_NSObject' | ${FAIL_IF_EMPTY} 
+       nm test-r.${ARCH}.o | grep -i 'objc_class_.*_NSData'   | ${FAIL_IF_EMPTY} 
+       nm test-r.${ARCH}.o | grep -i 'objc_class_.*_NSArray'  | ${FAIL_IF_EMPTY} 
+       nm test-r.${ARCH}.o | grep -i 'objc_class_.*_NSString' | ${PASS_IFF_STDIN} 
 
-       #${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
-       #grep '.objc_class_name_NSObject' test.${ARCH}.o.dump | ${FAIL_IF_EMPTY} 
-       #grep '.objc_class_name_NSString' test.${ARCH}.o.dump | ${PASS_IFF_STDIN} 
+clean:
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/objc-references/comment.txt b/unit-tests/test-cases/objc-references/comment.txt
new file mode 100644 (file)
index 0000000..ce67b71
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to verify an Objective-C object file is parsed to find the proper class references
diff --git a/unit-tests/test-cases/order_file-ans/Makefile b/unit-tests/test-cases/order_file-ans/Makefile
new file mode 100644 (file)
index 0000000..23fe568
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2007 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
+
+#
+#  Verify that -order_file can be used to order symbols with anonymous name spaces
+#
+
+run: all
+
+all:
+       ${CXX} ${CXXFLAGS} main.cxx -DANCHOR=1 -o main -Wl,-order_file -Wl,main.order 
+       ${FAIL_IF_BAD_MACHO} main
+       nm -n -g -j main | grep "_GLOBAL__N" > main.actual
+       ${PASS_IFF} diff main.actual main.expected
+
+
+clean:
+       rm -rf main main.actual
diff --git a/unit-tests/test-cases/order_file-ans/main.cxx b/unit-tests/test-cases/order_file-ans/main.cxx
new file mode 100644 (file)
index 0000000..b0412f9
--- /dev/null
@@ -0,0 +1,62 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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>
+
+
+#if ANCHOR
+       int anchor = 4;
+#endif
+
+namespace {
+       struct myanonstruct { int a; };
+}
+
+// function defined in anonymous namespace
+namespace {
+       void foo() { }
+}
+
+// function that has an anonymous namespace parameter
+void bar(myanonstruct* x) { }
+
+
+// function in anonymous namespace that has an anonymous namespace parameter
+namespace {
+       void baz(myanonstruct* x) { }
+}
+
+// nested namespace 
+namespace wow {
+       namespace {
+               void inner() { }
+       }
+}
+
+
+
+
+int main()
+{
+       return 0;
+}
diff --git a/unit-tests/test-cases/order_file-ans/main.expected b/unit-tests/test-cases/order_file-ans/main.expected
new file mode 100644 (file)
index 0000000..75e104f
--- /dev/null
@@ -0,0 +1,4 @@
+__Z3barPN17_GLOBAL__N_anchor12myanonstructE
+__ZN3wow17_GLOBAL__N_anchor5innerEv
+__ZN17_GLOBAL__N_anchor3bazEPNS_12myanonstructE
+__ZN17_GLOBAL__N_anchor3fooEv
diff --git a/unit-tests/test-cases/order_file-ans/main.order b/unit-tests/test-cases/order_file-ans/main.order
new file mode 100644 (file)
index 0000000..36dd786
--- /dev/null
@@ -0,0 +1,4 @@
+__Z3barPN95_GLOBAL__N__Volumes_my_src_ld64_unit_tests_test_cases_order_file_ans_main.cxx_00000000_38BA812C12myanonstructE
+__ZN3wow95_GLOBAL__N__Volumes_my_src_ld64_unit_tests_test_cases_order_file_ans_main.cxx_00000000_38BA812C5innerEv
+__ZN95_GLOBAL__N__Volumes_my_src_ld64_unit_tests_test_cases_order_file_ans_main.cxx_00000000_38BA812C3bazEPNS_12myanonstructE
+__ZN95_GLOBAL__N__Volumes_my_src_ld64_unit_tests_test_cases_order_file_ans_main.cxx_00000000_38BA812C3fooEv
diff --git a/unit-tests/test-cases/order_file/Makefile b/unit-tests/test-cases/order_file/Makefile
new file mode 100644 (file)
index 0000000..21ae0ea
--- /dev/null
@@ -0,0 +1,57 @@
+##
+# Copyright (c) 2006-2007 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
+
+#
+# The point of this test is a sanity check -order_file.
+# The main1 test verifies that C functions can be re-ordered
+# The main2 test verifies that a block of assembly is not moves en mas
+# The main1 test verifies that an order file with spaces and comments works
+#
+
+run: all
+
+all:
+       as -arch ${ARCH} -L extra.s -o extra.o
+       ${CC} ${CCFLAGS} main.c extra.o -o main1 -Wl,-order_file -Wl,main1.order 
+       ${FAIL_IF_BAD_MACHO} main1
+       nm -n -g -j main1 | grep "_main" > main1.nm
+       ${PASS_IFF} diff main1.nm main1.expected
+
+       ${CC} ${CCFLAGS} main.c extra.o -o main2 -Wl,-order_file -Wl,main2.order 
+       ${FAIL_IF_BAD_MACHO} main2
+       nm -n -j main2 | egrep '^_[a-z]+[0-9]$$' > main2.nm
+       ${PASS_IFF} diff main2.nm main2.expected
+
+       ${CC} -arch ${ARCH} -c main.c -o main.o
+       ${CC} ${CCFLAGS} main.o extra.o -o main3 -Wl,-order_file -Wl,main3.order 
+       ${FAIL_IF_BAD_MACHO} main3
+       nm -n -g -j main3 | grep "_main" > main3.nm
+       ${PASS_IFF} diff main3.nm main3.expected
+
+
+
+
+clean:
+       rm -rf main1 *.nm main2 *.o warnings.log main3
diff --git a/unit-tests/test-cases/order_file/extra.s b/unit-tests/test-cases/order_file/extra.s
new file mode 100644 (file)
index 0000000..90166ce
--- /dev/null
@@ -0,0 +1,24 @@
+
+
+       .text
+       
+       .globl _foo1
+_foo1: nop
+
+       .globl _aaa2
+_aaa2:
+_bbb2:
+_ccc2:
+       nop
+       
+       .globl _bbb3
+_aaa3:
+_bbb3:
+_ccc3:
+       nop
+
+
+_aaa4:
+       nop
+       
+       
\ No newline at end of file
diff --git a/unit-tests/test-cases/order_file/main.c b/unit-tests/test-cases/order_file/main.c
new file mode 100644 (file)
index 0000000..5643b45
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+int main()
+{
+       return 0;
+}
+
+void main2() {}
+void main3() {}
+void main4() {}
diff --git a/unit-tests/test-cases/order_file/main1.expected b/unit-tests/test-cases/order_file/main1.expected
new file mode 100644 (file)
index 0000000..04d128b
--- /dev/null
@@ -0,0 +1,4 @@
+_main4
+_main3
+_main
+_main2
diff --git a/unit-tests/test-cases/order_file/main1.order b/unit-tests/test-cases/order_file/main1.order
new file mode 100644 (file)
index 0000000..06b34d5
--- /dev/null
@@ -0,0 +1,4 @@
+_main4
+_main3
+
+
diff --git a/unit-tests/test-cases/order_file/main2.expected b/unit-tests/test-cases/order_file/main2.expected
new file mode 100644 (file)
index 0000000..8aca65c
--- /dev/null
@@ -0,0 +1,11 @@
+_main3
+_foo1
+_aaa2
+_bbb2
+_ccc2
+_aaa3
+_bbb3
+_ccc3
+_aaa4
+_main4
+_main2
diff --git a/unit-tests/test-cases/order_file/main2.order b/unit-tests/test-cases/order_file/main2.order
new file mode 100644 (file)
index 0000000..87f89e6
--- /dev/null
@@ -0,0 +1,6 @@
+_main3
+_aaa3
+_main4
+
+
+
diff --git a/unit-tests/test-cases/order_file/main3.expected b/unit-tests/test-cases/order_file/main3.expected
new file mode 100644 (file)
index 0000000..04d128b
--- /dev/null
@@ -0,0 +1,4 @@
+_main4
+_main3
+_main
+_main2
diff --git a/unit-tests/test-cases/order_file/main3.order b/unit-tests/test-cases/order_file/main3.order
new file mode 100644 (file)
index 0000000..d135527
--- /dev/null
@@ -0,0 +1,8 @@
+
+# spaces before and after main4
+main.o:   _main4  
+#
+main.o:  _main3# trailing comment
+#
+
+
diff --git a/unit-tests/test-cases/prebound-split-seg/Makefile b/unit-tests/test-cases/prebound-split-seg/Makefile
new file mode 100644 (file)
index 0000000..07bce59
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+SHELL = bash # use bash shell so we can redirect just stderr
+
+#
+# The point of this test is to build a prebound split-seg library
+#
+
+run: all
+
+all: 
+       ${CC} ${CCFLAGS} -seg_addr_table address_table -prebind bar.c -dynamiclib -o libbar.dylib -install_name /foo/bar/libbar.dylib
+       ${PASS_IFF_GOOD_MACHO} libbar.dylib
+
+clean:
+       rm *.dylib 
diff --git a/unit-tests/test-cases/prebound-split-seg/address_table b/unit-tests/test-cases/prebound-split-seg/address_table
new file mode 100644 (file)
index 0000000..b611ca8
--- /dev/null
@@ -0,0 +1,4 @@
+# comment
+0x91000000     0xA1000000      /foo/bar/libbar.dylib           
+#
+
diff --git a/unit-tests/test-cases/prebound-split-seg/bar.c b/unit-tests/test-cases/prebound-split-seg/bar.c
new file mode 100644 (file)
index 0000000..46b7269
--- /dev/null
@@ -0,0 +1,36 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+int x = 3;
+int* xp = &x;
+
+
+int bar() 
+{
+       return *xp;
+}
+
+void* pbar = &bar;
+
index 655631cb0656b0d67e1dae249eef9ebbd23d922f..be0ba42ed3cd28a6f06a4cca0b34c22526aa25e3 100644 (file)
@@ -33,15 +33,22 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} -c foo.c -o foo.o
+       ${FAIL_IF_BAD_OBJ} foo.o
+
        ${CC} ${CCFLAGS} -c bar.c -o bar.o
+       ${FAIL_IF_BAD_OBJ} bar.o
+
        ${LD} -r foo.o bar.o -o foobar.o -arch ${ARCH}
+       ${FAIL_IF_BAD_OBJ} foobar.o
+
        ${CC} ${CCFLAGS} hello.c foobar.o -o hello
        ${FAIL_IF_BAD_MACHO} hello
+
        ${LD} -r foo.o bar.o -o foobar2.o -arch ${ARCH} -keep_private_externs
+       ${FAIL_IF_BAD_OBJ} foobar2.o
+
        ${CC} ${CCFLAGS} hello.c foobar2.o -o hello2
        ${PASS_IFF_GOOD_MACHO} hello2
 
 clean:
-       rm  foo.o bar.o foobar.o hello foobar2.o hello2
-       
-
+       rm -rf *.o hello hello2
diff --git a/unit-tests/test-cases/private-non-lazy/comment.txt b/unit-tests/test-cases/private-non-lazy/comment.txt
new file mode 100644 (file)
index 0000000..e6d11c0
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to check that a non-lazy-pointer in foo.o to a private-extern symbol in bar.o will properly survive ld -r
diff --git a/unit-tests/test-cases/re-export-cases/Makefile b/unit-tests/test-cases/re-export-cases/Makefile
new file mode 100644 (file)
index 0000000..64ec112
--- /dev/null
@@ -0,0 +1,167 @@
+##
+# Copyright (c) 2007 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 all the different ways that re-exports can be specified and implemented
+#
+
+
+run: all
+
+all:
+
+# -sub_library for 10.4
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib  -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -lbar -L. -sub_library libbar -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       otool -lv libfoo.dylib | grep LC_SUB_LIBRARY | ${FAIL_IF_EMPTY}
+       otool -lv libfoo.dylib | grep LC_REEXPORT_DYLIB | ${FAIL_IF_STDIN}
+       
+# -sub_library for 10.5
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib   -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -lbar -L. -sub_library libbar -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       otool -lv libfoo.dylib | grep LC_REEXPORT_DYLIB | ${FAIL_IF_EMPTY}
+       otool -lv libfoo.dylib | grep LC_SUB_LIBRARY | ${FAIL_IF_STDIN}
+       
+       
+# -sub_umbrella for 10.4
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar"  -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -framework Bar -sub_umbrella Bar  -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+       otool -lv Foo.framework/Foo | grep LC_SUB_UMBRELLA | ${FAIL_IF_EMPTY}
+       otool -lv Foo.framework/Foo | grep LC_REEXPORT_DYLIB | ${FAIL_IF_STDIN}
+
+# -sub_umbrella for 10.5
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar"  -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -framework Bar -sub_umbrella Bar  -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+       otool -lv Foo.framework/Foo | grep LC_REEXPORT_DYLIB | ${FAIL_IF_EMPTY}
+       otool -lv Foo.framework/Foo | grep LC_SUB_UMBRELLA | ${FAIL_IF_STDIN}
+       
+
+# -umbrella for 10.4
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar" -umbrella Foo -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -framework Bar -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+       otool -lv Bar.framework/Bar | grep LC_SUB_FRAMEWORK | ${FAIL_IF_EMPTY}
+       otool -lv Foo.framework/Foo | grep LC_REEXPORT_DYLIB | ${FAIL_IF_STDIN}
+
+# -umbrella for 10.5
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar" -umbrella Foo -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -framework Bar -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+       otool -lv Bar.framework/Bar | grep LC_SUB_FRAMEWORK | ${FAIL_IF_EMPTY}
+       otool -lv Foo.framework/Foo | grep LC_REEXPORT_DYLIB | ${FAIL_IF_EMPTY}
+
+
+# -reexport_library for 10.4
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib  -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -Wl,-reexport_library,libbar.dylib -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       otool -lv libfoo.dylib | grep LC_SUB_LIBRARY | ${FAIL_IF_EMPTY}
+       otool -lv libfoo.dylib | grep LC_REEXPORT_DYLIB | ${FAIL_IF_STDIN}
+       
+# -reexport_library for 10.5
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib  -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -Wl,-reexport_library,libbar.dylib -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       otool -lv libfoo.dylib | grep LC_REEXPORT_DYLIB | ${FAIL_IF_EMPTY}
+       otool -lv libfoo.dylib | grep LC_SUB_LIBRARY | ${FAIL_IF_STDIN}
+       
+
+# -reexport-l for 10.4
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib  -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -Wl,-reexport-lbar -L. -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       otool -lv libfoo.dylib | grep LC_SUB_LIBRARY | ${FAIL_IF_EMPTY}
+       otool -lv libfoo.dylib | grep LC_REEXPORT_DYLIB | ${FAIL_IF_STDIN}
+       
+# -reexport-l for 10.5
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib   -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -Wl,-reexport-lbar -L. -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       otool -lv libfoo.dylib | grep LC_REEXPORT_DYLIB | ${FAIL_IF_EMPTY}
+       otool -lv libfoo.dylib | grep LC_SUB_LIBRARY | ${FAIL_IF_STDIN}
+
+
+# -reexport_framework for 10.4
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar"  -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -Wl,-reexport_framework,Bar -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+       otool -lv Foo.framework/Foo | grep LC_SUB_UMBRELLA | ${FAIL_IF_EMPTY}
+       otool -lv Foo.framework/Foo | grep LC_REEXPORT_DYLIB | ${FAIL_IF_STDIN}
+
+# -reexport_framework for 10.5
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar"  -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -Wl,-reexport_framework,Bar -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+       otool -lv Foo.framework/Foo | grep LC_REEXPORT_DYLIB | ${FAIL_IF_EMPTY}
+       otool -lv Foo.framework/Foo | grep LC_SUB_UMBRELLA | ${FAIL_IF_STDIN}
+       
+
+# -reexport_framework and -umbrella for 10.4
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar" -umbrella Foo -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -Wl,-reexport_framework,Bar -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+       otool -lv Bar.framework/Bar | grep LC_SUB_FRAMEWORK | ${FAIL_IF_EMPTY}
+       otool -lv Foo.framework/Foo | grep LC_REEXPORT_DYLIB | ${FAIL_IF_STDIN}
+
+
+# -reexport_framework and -umbrella for 10.4
+       mkdir -p Bar.framework Foo.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o Bar.framework/Bar -install_name "`pwd`/Bar.framework/Bar" -umbrella Foo -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} Bar.framework/Bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o Foo.framework/Foo -F. -Wl,-reexport_framework,Bar -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} Foo.framework/Foo
+       otool -lv Bar.framework/Bar | grep LC_SUB_FRAMEWORK | ${FAIL_IF_EMPTY}
+       otool -lv Foo.framework/Foo | grep LC_REEXPORT_DYLIB | ${FAIL_IF_EMPTY}
+
+       ${PASS_IFF} /usr/bin/true
+
+
+clean:
+
+       rm -rf hide libbar.dylib libfoo.dylib Foo.framework Bar.framework 
diff --git a/unit-tests/test-cases/re-export-cases/bar.c b/unit-tests/test-cases/re-export-cases/bar.c
new file mode 100644 (file)
index 0000000..9c18401
--- /dev/null
@@ -0,0 +1,5 @@
+
+int bar (void)
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/re-export-cases/baz.c b/unit-tests/test-cases/re-export-cases/baz.c
new file mode 100644 (file)
index 0000000..af6a9f8
--- /dev/null
@@ -0,0 +1,5 @@
+
+int baz (void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/re-export-cases/foo.c b/unit-tests/test-cases/re-export-cases/foo.c
new file mode 100644 (file)
index 0000000..d0cdf47
--- /dev/null
@@ -0,0 +1,4 @@
+int foo (void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/re-export-flag/Makefile b/unit-tests/test-cases/re-export-flag/Makefile
new file mode 100644 (file)
index 0000000..82228ee
--- /dev/null
@@ -0,0 +1,48 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# Test that the MH_NO_REEXPORTED_DYLIBS bit is set in dylibs with no re-exports
+#
+
+run: all
+
+all:
+# build base library
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o `pwd`/libbar.dylib
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+
+# build library the re-exports base library
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib libbar.dylib -sub_library libbar
+# test that foo does not have MH_NO_REEXPORTED_DYLIBS bit
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+
+# build libray that links with base but does not re-export it
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo2.dylib libbar.dylib 
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       otool -hv libfoo2.dylib | grep NO_REEXPORTED_DYLIBS | ${PASS_IFF_STDIN}
+
+clean:
+       rm -rf *.dylib
diff --git a/unit-tests/test-cases/re-export-flag/bar.c b/unit-tests/test-cases/re-export-flag/bar.c
new file mode 100644 (file)
index 0000000..34e5666
--- /dev/null
@@ -0,0 +1,5 @@
+
+int bar(void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/re-export-flag/foo.c b/unit-tests/test-cases/re-export-flag/foo.c
new file mode 100644 (file)
index 0000000..714540a
--- /dev/null
@@ -0,0 +1,4 @@
+int foo(void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/re-export-optimizations/Makefile b/unit-tests/test-cases/re-export-optimizations/Makefile
new file mode 100644 (file)
index 0000000..a1dfd88
--- /dev/null
@@ -0,0 +1,65 @@
+##
+# Copyright (c) 2007 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 a public re-exported library is automatically added as a dependent
+# unless nothing is used from it.
+#
+
+
+run: all
+
+all:
+
+# -sub_library for 10.4
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib  -install_name /usr/lib/libbar.dylib -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -lbar -L. -sub_library libbar -mmacosx-version-min=10.4
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       ${CC} ${CCFLAGS} main.c -DCALL_BAR libfoo.dylib -o main -L. -mmacosx-version-min=10.4
+       otool -L main | grep libbar | ${FAIL_IF_EMPTY}
+       nm -m main | grep _bar | grep libbar | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c libfoo.dylib -o main -L. -mmacosx-version-min=10.4
+       otool -L main | grep libbar | ${FAIL_IF_STDIN}
+       
+               
+# -sub_library for 10.5
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib  -install_name /usr/lib/libbar.dylib -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -lbar -L. -sub_library libbar -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       ${CC} ${CCFLAGS} main.c -DCALL_BAR libfoo.dylib -o main -L. -mmacosx-version-min=10.5
+       otool -L main | grep libbar | ${FAIL_IF_EMPTY}
+       nm -m main | grep _bar | grep libbar | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c libfoo.dylib -o main -L. -mmacosx-version-min=10.5
+       otool -L main | grep libbar | ${FAIL_IF_STDIN}
+       
+                       
+       ${PASS_IFF} /usr/bin/true
+
+
+clean:
+
+       rm -rf libbar.dylib libfoo.dylib main 
diff --git a/unit-tests/test-cases/re-export-optimizations/bar.c b/unit-tests/test-cases/re-export-optimizations/bar.c
new file mode 100644 (file)
index 0000000..9c18401
--- /dev/null
@@ -0,0 +1,5 @@
+
+int bar (void)
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/re-export-optimizations/foo.c b/unit-tests/test-cases/re-export-optimizations/foo.c
new file mode 100644 (file)
index 0000000..d0cdf47
--- /dev/null
@@ -0,0 +1,4 @@
+int foo (void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/re-export-optimizations/main.c b/unit-tests/test-cases/re-export-optimizations/main.c
new file mode 100644 (file)
index 0000000..2b85b0e
--- /dev/null
@@ -0,0 +1,10 @@
+
+extern void bar();
+
+int main()
+{
+#if    CALL_BAR
+       bar();
+#endif
+       return 0;
+}
diff --git a/unit-tests/test-cases/re-export-relative-paths/Makefile b/unit-tests/test-cases/re-export-relative-paths/Makefile
new file mode 100644 (file)
index 0000000..2560a86
--- /dev/null
@@ -0,0 +1,49 @@
+##
+# Copyright (c) 2007 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 @loader_path and @executable_path can be resolved finding indirect dylibs
+#
+
+
+run: all
+
+all:
+       mkdir -p hide
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -install_name '@loader_path/libfoo.dylib' -o hide/libfoo.dylib 
+       ${FAIL_IF_BAD_MACHO} hide/libfoo.dylib
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o hide/libbar.dylib -install_name '@executable_path/hide/libbar.dylib'
+       ${FAIL_IF_BAD_MACHO} hide/libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib wrap.c -o hide/libwrap.dylib -Wl,-reexport-lfoo -Wl,-reexport-lbar -Lhide
+       ${FAIL_IF_BAD_MACHO} hide/libwrap.dylib
+       ${CC} ${CCFLAGS} main.c -o main hide/libwrap.dylib
+       ${CC} ${CCFLAGS} main.c -dynamiclib -o libmain.dylib hide/libwrap.dylib -Wl,-executable_path,`pwd`/main
+       ${CC} ${CCFLAGS} main.c -dynamiclib -o libmain.dylib hide/libwrap.dylib -Wl,-executable_path,`pwd`
+       ${PASS_IFF} /usr/bin/true
+
+
+clean:
+
+       rm -rf hide libbar.dylib libfoo.dylib libwrap.dylib main libmain.dylib
diff --git a/unit-tests/test-cases/re-export-relative-paths/bar.c b/unit-tests/test-cases/re-export-relative-paths/bar.c
new file mode 100644 (file)
index 0000000..9c18401
--- /dev/null
@@ -0,0 +1,5 @@
+
+int bar (void)
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/re-export-relative-paths/foo.c b/unit-tests/test-cases/re-export-relative-paths/foo.c
new file mode 100644 (file)
index 0000000..d0cdf47
--- /dev/null
@@ -0,0 +1,4 @@
+int foo (void)
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/re-export-relative-paths/main.c b/unit-tests/test-cases/re-export-relative-paths/main.c
new file mode 100644 (file)
index 0000000..367c6cb
--- /dev/null
@@ -0,0 +1,11 @@
+extern int foo();
+extern int bar();
+extern int wrap();
+
+int main()
+{
+   foo();
+   bar();
+   wrap();
+  return 0;
+}
diff --git a/unit-tests/test-cases/re-export-relative-paths/wrap.c b/unit-tests/test-cases/re-export-relative-paths/wrap.c
new file mode 100644 (file)
index 0000000..d3cdd85
--- /dev/null
@@ -0,0 +1,2 @@
+int wrap() { return 0; }
+
index 6cea9e274c4b88d9a0d8596760ca4786262c2b8b..53d702a3af6cdcdeadd255c90583b23828e38581 100644 (file)
@@ -2,14 +2,14 @@
 # Copyright (c) 2006 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,
@@ -17,7 +17,7 @@
 # FITNESS FOR A PARTICULAR PURPOSE, 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 = ../..
@@ -31,12 +31,14 @@ include ${TESTROOT}/include/common.makefile
 
 SHELL = bash # use bash shell so we can redirect just stderr
 
-run: all
-
+run:
+       @if [ ${ARCH} = x86_64 ] ; then \
+       ${PASS_IFF} /usr/bin/true ; \
+       else \
+       $(MAKE) all ; \
+       fi
 all:
        ${FAIL_IFF} ${CC} ${CCFLAGS} test.c -mdynamic-no-pic -dynamiclib -o test-${ARCH}.dylib 2> fail.log
 
 clean:
-       rm  test-${ARCH}.dylib fail.log
-       
-
+       rm -rf *.dylib fail.log
diff --git a/unit-tests/test-cases/read-only-relocs/comment.txt b/unit-tests/test-cases/read-only-relocs/comment.txt
new file mode 100644 (file)
index 0000000..f319d31
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld will fail to link a dylib compiled with -mdynamic-no-pic
index 2077033c101ce16355386a4b3e3c27d658ba3e45..77bdf6b00bccef8d639a8ce890bca84a66f1ad31 100644 (file)
@@ -32,15 +32,22 @@ include ${TESTROOT}/include/common.makefile
 run: all
 
 all:
-       ${CC} -arch ${ARCH} -c foo.c -o foo.${ARCH}.o
-       ${CC} -arch ${ARCH} -c bar.m -o bar.${ARCH}.o
-       ${CC} -arch ${ARCH} foo.${ARCH}.o bar.${ARCH}.o -dynamiclib -o libfoo.${ARCH}.dylib -framework Foundation -single_module -mmacosx-version-min=10.5
-       ${CC} -arch ${ARCH} foo.${ARCH}.o bar.${ARCH}.o -dynamiclib -o libfoo-alt.${ARCH}.dylib -framework Foundation -single_module -mmacosx-version-min=10.5 -seg1addr 0x12340000 -install_name libfoo.${ARCH}.dylib
+       ${CC} -c foo.c -o foo.${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} foo.${ARCH}.o
+
+       ${CC} -c bar.m -o bar.${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} bar.${ARCH}.o
+
+       ${CC} foo.${ARCH}.o bar.${ARCH}.o -dynamiclib -o libfoo.${ARCH}.dylib -framework Foundation -single_module -mmacosx-version-min=10.5
+       ${FAIL_IF_BAD_MACHO} libfoo.${ARCH}.dylib
+
+       ${CC} foo.${ARCH}.o bar.${ARCH}.o -dynamiclib -o libfoo-alt.${ARCH}.dylib -framework Foundation -single_module -mmacosx-version-min=10.5 -seg1addr 0x12340000 -install_name libfoo.${ARCH}.dylib
+       ${FAIL_IF_BAD_MACHO} libfoo-alt.${ARCH}.dylib
+
        rebase -arch ${ARCH} -low_address 0x12340000 libfoo.${ARCH}.dylib
        ${FAIL_IF_BAD_MACHO} libfoo.${ARCH}.dylib
+
        ${PASS_IFF} diff libfoo.${ARCH}.dylib libfoo-alt.${ARCH}.dylib
 
 clean:
-       rm foo.${ARCH}.o bar.${ARCH}.o libfoo.${ARCH}.dylib libfoo-alt.${ARCH}.dylib
-       
-
+       rm *.o *.dylib
diff --git a/unit-tests/test-cases/rebase-basic/comment.txt b/unit-tests/test-cases/rebase-basic/comment.txt
new file mode 100644 (file)
index 0000000..013eb45
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to see that a dylib run through the rebase tool is the same as if the dylib was originally built at that address
index 6c0eb7b917bd19d55d1a47833c8a6c1e37cda97d..c231ac499598872792bcae03d0ae60d038383cfd 100644 (file)
@@ -35,13 +35,12 @@ run: all
 
 all:
        ${CC} ${ASMFLAGS} relocs-asm.s -c -o relocs-asm.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content relocs-asm.${ARCH}.o > relocs-asm.${ARCH}.o.dump
+
        ${LD} -arch ${ARCH} -r -keep_private_externs relocs-asm.${ARCH}.o -o relocs-asm-r.${ARCH}.o
-       ${OBJECTDUMP} -no_content relocs-asm.${ARCH}.o > relocs-asm.${ARCH}.o.dump
-       ${OBJECTDUMP} -no_content relocs-asm-r.${ARCH}.o > relocs-asm-r.${ARCH}.o.dump
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content relocs-asm-r.${ARCH}.o > relocs-asm-r.${ARCH}.o.dump
+
        ${PASS_IFF} diff relocs-asm.${ARCH}.o.dump relocs-asm-r.${ARCH}.o.dump
 
 clean:
-       rm -rf relocs-asm.${ARCH}.o relocs-asm-r.${ARCH}.o relocs-asm.${ARCH}.o.dump relocs-asm-r.${ARCH}.o.dump
-       
-       
-
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/relocs-asm/comment.txt b/unit-tests/test-cases/relocs-asm/comment.txt
new file mode 100644 (file)
index 0000000..4e819e1
--- /dev/null
@@ -0,0 +1,3 @@
+The point of this test is to verify a .o file can round-trip through ld -r correctly.  The ObjectDump utility is used
+dump a "canonical" textual representation of a .o file.  The before and after .o files are then diff'ed.
+No differences means this test passes
index afacc62139699d20f7869c92aa6c942058f64467..28cfc566a66eb4bbede84bb4a878b7c1706f2dbf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -186,6 +186,18 @@ _test_branches:
        
        # call external + addend
        jne     _external+16
+       
+_pointer_diffs:
+       nop
+       call    _get_ret_eax    
+1:     movl _foo-1b(%eax),%esi
+       movl _foo+10-1b(%eax),%esi
+       movl _test_branches-1b(%eax),%esi
+       movl _test_branches+3-1b(%eax),%esi
+       
+_word_relocs:
+       callw   _pointer_diffs
+
 #endif
 
 
@@ -272,10 +284,35 @@ _test_diffs:
 Llocal2:
        .long 0
        .long Llocal2-_test_branches
+       .long . - _test_branches
+       .long . - _test_branches + 8
+       .long _test_branches - .
+       .long _test_branches - . + 8
+       .long _test_branches - . - 8
 #if __ppc64__
        .quad Llocal2-_test_branches
 #endif
 
+_foo: nop
+
+       .align 2        
+_distance_from_foo:
+       .long   0
+       .long   . - _foo
+       .long   . - 8 - _foo
+       
+       
+_distance_to_foo:
+       .long   _foo - .
+       .long   _foo - . + 4
+       
+
+_distance_to_here:     
+       .long   _foo - _distance_to_here
+       .long   _foo - _distance_to_here - 4 
+       .long   _foo - _distance_to_here - 12 
+       .long   0
+
 
 #if __x86_64__
        .data
index 610a02b416c872ef9882cb726c241e3008a1aa4d..15a7c3591b6d7b57c11907d6d00fc2aef714410a 100644 (file)
@@ -36,14 +36,14 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} test.c -c -o test.${ARCH}.o
-       ${LD} -arch ${ARCH} -r -keep_private_externs test.${ARCH}.o -o test-r.${ARCH}.o
-       ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
        #grep "plus" test.${ARCH}.o.dump | ${FAIL_IF_STDIN}
-       ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+
+       ${LD} -arch ${ARCH} -r -keep_private_externs test.${ARCH}.o -o test-r.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
        #grep "plus" test-r.${ARCH}.o.dump | ${FAIL_IF_STDIN}
+
        ${PASS_IFF} diff test.${ARCH}.o.dump test-r.${ARCH}.o.dump
 
 clean:
-       rm -rf test.${ARCH}.o test-r.${ARCH}.o test.${ARCH}.o.dump test-r.${ARCH}.o.dump
-       
-
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/relocs-c2/Makefile b/unit-tests/test-cases/relocs-c2/Makefile
new file mode 100644 (file)
index 0000000..1a2991a
--- /dev/null
@@ -0,0 +1,59 @@
+##
+# Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+#
+# The point of this test is to verify a .o file can round-trip
+# through ld -r correctly.  The ObjectDump utility is used
+# dump a "canonical" textual representation of a .o file.
+# The before and after .o files are then diff'ed.
+# No differences means this test passes
+#
+# Currently for ppc64 the .o's alternate! in content
+#
+
+LD=ld64
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} test.c -c -o test.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
+       #grep "plus" test.${ARCH}.o.dump | ${FAIL_IF_STDIN}
+
+       ${LD} -arch ${ARCH} -r -keep_private_externs test.${ARCH}.o -o test-r.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+       #grep "plus" test-r.${ARCH}.o.dump | ${FAIL_IF_STDIN}
+
+       ${LD} -arch ${ARCH} -r -keep_private_externs test-r.${ARCH}.o -o test-r-r.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test-r-r.${ARCH}.o > test-r-r.${ARCH}.o.dump
+
+       ${LD} -arch ${ARCH} -r -keep_private_externs test-r-r.${ARCH}.o -o test-r-r-r.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test-r-r-r.${ARCH}.o > test-r-r-r.${ARCH}.o.dump
+
+       ${PASS_IFF} diff -c -w test.${ARCH}.o.dump test-r.${ARCH}.o.dump
+
+clean:
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/relocs-c2/comment.txt b/unit-tests/test-cases/relocs-c2/comment.txt
new file mode 100644 (file)
index 0000000..2499674
--- /dev/null
@@ -0,0 +1,5 @@
+The point of this test is to verify a .o file can round-trip through ld -r correctly.  The ObjectDump utility is used
+dump a "canonical" textual representation of a .o file.  The before and after .o files are then diff'ed.
+No differences means this test passes
+
+Currently for ppc64 the .o's alternate! in content
diff --git a/unit-tests/test-cases/relocs-c2/test.c b/unit-tests/test-cases/relocs-c2/test.c
new file mode 100644 (file)
index 0000000..b877760
--- /dev/null
@@ -0,0 +1,76 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+static int foo;
+
+int __attribute__((visibility("hidden"))) foofoo;
+
+static int                                                                                     uninit_static;
+static int                                                                                     init_static = 1;
+               int __attribute__((visibility("hidden")))       uninit_hidden;
+               int __attribute__((visibility("hidden")))       init_hidden = 1;
+               int                                                                                     uninit_global;
+               int                                                                                     init_global = 1;
+extern int                                                                                     extern_global;
+extern int      __attribute__((visibility("hidden")))  extern_hidden;
+
+static int                                                                                     uninit_static_array[4];
+static int                                                                                     init_static_array[4] = {1,2,3,4};
+               int __attribute__((visibility("hidden")))       uninit_hidden_array[4];
+               int __attribute__((visibility("hidden")))       init_hidden_array[4] = {1,2,3,4};
+               int                                                                                     uninit_global_array[4];
+               int                                                                                     init_global_array[4] = {1,2,3,4};
+extern int                                                                                     extern_global_array[4];
+
+int test1() { return uninit_static; }
+int test2() { return init_static; }
+int test3() { return uninit_hidden; }
+int test4() { return init_hidden; }
+int test5() { return uninit_global; }
+int test6() { return init_global; }
+int test7() { return extern_global; }
+int test8() { return extern_hidden; }
+
+int test_array1() { return uninit_static_array[2]; }
+int test_array2() { return init_static_array[2]; }
+int test_array3() { return uninit_hidden_array[2]; }
+int test_array4() { return init_hidden_array[2]; }
+int test_array5() { return uninit_global_array[2]; }
+int test_array6() { return init_global_array[2]; }
+int test_array7() { return extern_global_array[2]; }
+
+static int foo2;
+int test9() { return foo2; }
+
+
+int* p_init_global = &init_global;
+void* p_test1 = (void*)&test1;
+unsigned char pad = 2;
+unsigned char pad2 = 3;         // this padding throws off alignment on compiler generated anonymous non-lazy pointers...
+
+int func() __attribute__((visibility("hidden")));
+int func() { return foo; }
+
+int func2() { return func() + 1; }
+
index 6d45efd04c0dbb62f75d3c250e10bbc9e2701769..a9ca5ef1875a92d41326eab5f607ed24e808eae1 100644 (file)
@@ -2,14 +2,14 @@
 # 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,
@@ -17,7 +17,7 @@
 # FITNESS FOR A PARTICULAR PURPOSE, 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 = ../..
@@ -35,13 +35,13 @@ include ${TESTROOT}/include/common.makefile
 run: all
 
 all:
-       ${CC} ${CCFLAGS} -Os -mdynamic-no-pic test.c -c -o test.${ARCH}.o
+       ${CC} ${CCFLAGS} -Os $(MDYNAMIC_NO_PIC) test.c -c -o test.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
+
        ${LD} -arch ${ARCH} -r -keep_private_externs test.${ARCH}.o -o test-r.${ARCH}.o
-       ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
-       ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+
        ${PASS_IFF} diff test.${ARCH}.o.dump test-r.${ARCH}.o.dump
 
 clean:
-       rm -rf test.${ARCH}.o test-r.${ARCH}.o test.${ARCH}.o.dump test-r.${ARCH}.o.dump
-       
-
+       rm -rf *.o *.dump
index 31e87c22acb4e679131bbd9044f54e4a8243bea2..2d199d08a793e2a07ef652560013f5e864841553 100644 (file)
@@ -45,3 +45,10 @@ float getSingle() { return 1.0; }
 double getDouble() { return 2.0; }
 long double getLongDouble() { return 3.0; }
 
+
+// rdar://problem/4732996
+const char* stringFutz(int x) {
+       return "hello" + 0x1000 + x;
+}
+
+const char*    usesAddend = "teststr" + 0x2000;
diff --git a/unit-tests/test-cases/relocs-literals2/Makefile b/unit-tests/test-cases/relocs-literals2/Makefile
new file mode 100644 (file)
index 0000000..23e4a82
--- /dev/null
@@ -0,0 +1,50 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+#
+# The point of this test is to verify a .o file can round-trip
+# through ld -r correctly.  The ObjectDump utility is used
+# dump a "canonical" textual representation of a .o file.
+# The before and after .o files are then diff'ed.
+# No differences means this test passes
+#
+ifneq (${ARCH},x86_64)
+       PIC=-mdynamic-no-pic
+endif
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} -Os $(PIC) test.c -c -o test.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
+
+       ${LD} -arch ${ARCH} -r -keep_private_externs test.${ARCH}.o -o test-r.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+
+       ${PASS_IFF} diff test.${ARCH}.o.dump test-r.${ARCH}.o.dump
+
+clean:
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/relocs-literals2/test.c b/unit-tests/test-cases/relocs-literals2/test.c
new file mode 100644 (file)
index 0000000..2d199d0
--- /dev/null
@@ -0,0 +1,54 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * 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@
+ */
+
+const char*                    foo = "foo";
+const char* const      bar = "bar";
+
+const char charArray1[] = "charArray1";
+static const char charArray2[] = "charArray2";
+
+
+const char* getString() { return "string"; }
+const char* getString2() { return charArray2; }
+const char* getString3() { return charArray1; }
+const char* getString4() { return foo; }
+
+
+float          f1 = 3.0;
+double         d1 = 3.0;
+long double ld1 = 3.0;
+
+
+
+float getSingle() { return 1.0; }
+double getDouble() { return 2.0; }
+long double getLongDouble() { return 3.0; }
+
+
+// rdar://problem/4732996
+const char* stringFutz(int x) {
+       return "hello" + 0x1000 + x;
+}
+
+const char*    usesAddend = "teststr" + 0x2000;
diff --git a/unit-tests/test-cases/relocs-literals3/Makefile b/unit-tests/test-cases/relocs-literals3/Makefile
new file mode 100644 (file)
index 0000000..66190ae
--- /dev/null
@@ -0,0 +1,48 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+LD=ld64
+
+
+#
+# The point of this test is to verify a .o file can round-trip
+# through ld -r correctly.  The ObjectDump utility is used
+# dump a "canonical" textual representation of a .o file.
+# The before and after .o files are then diff'ed.
+# No differences means this test passes
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} -Os -mdynamic-no-pic test.c -c -o test.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
+
+       ${LD} -arch ${ARCH} -r -keep_private_externs test.${ARCH}.o -o test-r.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+
+       ${PASS_IFF} diff -C 6 test.${ARCH}.o.dump test-r.${ARCH}.o.dump
+
+clean:
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/relocs-literals3/comment.txt b/unit-tests/test-cases/relocs-literals3/comment.txt
new file mode 100644 (file)
index 0000000..4e819e1
--- /dev/null
@@ -0,0 +1,3 @@
+The point of this test is to verify a .o file can round-trip through ld -r correctly.  The ObjectDump utility is used
+dump a "canonical" textual representation of a .o file.  The before and after .o files are then diff'ed.
+No differences means this test passes
diff --git a/unit-tests/test-cases/relocs-literals3/test.c b/unit-tests/test-cases/relocs-literals3/test.c
new file mode 100644 (file)
index 0000000..31e87c2
--- /dev/null
@@ -0,0 +1,47 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * 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@
+ */
+
+const char*                    foo = "foo";
+const char* const      bar = "bar";
+
+const char charArray1[] = "charArray1";
+static const char charArray2[] = "charArray2";
+
+
+const char* getString() { return "string"; }
+const char* getString2() { return charArray2; }
+const char* getString3() { return charArray1; }
+const char* getString4() { return foo; }
+
+
+float          f1 = 3.0;
+double         d1 = 3.0;
+long double ld1 = 3.0;
+
+
+
+float getSingle() { return 1.0; }
+double getDouble() { return 2.0; }
+long double getLongDouble() { return 3.0; }
+
index 9b55f256784fbed1dd915bc99e51669d53c395eb..0f8846d79cd9c31eb302bf1bccdb36a98abcd2d8 100644 (file)
@@ -36,12 +36,12 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} test.m -c -o test.${ARCH}.o
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
+
        ${LD} -arch ${ARCH} -r -keep_private_externs test.${ARCH}.o -o test-r.${ARCH}.o
-       ${OBJECTDUMP} -no_content test.${ARCH}.o > test.${ARCH}.o.dump
-       ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} -no_content test-r.${ARCH}.o > test-r.${ARCH}.o.dump
+
        ${PASS_IFF} diff test.${ARCH}.o.dump test-r.${ARCH}.o.dump
 
 clean:
-       rm -rf test.${ARCH}.o test-r.${ARCH}.o test.${ARCH}.o.dump test-r.${ARCH}.o.dump
-       
-
+       rm -rf *.o *.dump
diff --git a/unit-tests/test-cases/relocs-objc/comment.txt b/unit-tests/test-cases/relocs-objc/comment.txt
new file mode 100644 (file)
index 0000000..4e819e1
--- /dev/null
@@ -0,0 +1,3 @@
+The point of this test is to verify a .o file can round-trip through ld -r correctly.  The ObjectDump utility is used
+dump a "canonical" textual representation of a .o file.  The before and after .o files are then diff'ed.
+No differences means this test passes
diff --git a/unit-tests/test-cases/segment-order/Makefile b/unit-tests/test-cases/segment-order/Makefile
new file mode 100644 (file)
index 0000000..32c8e81
--- /dev/null
@@ -0,0 +1,37 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Validate linker puts non-standard segments in order of discovery
+#
+
+all:
+       ${CC} ${CCFLAGS} main.c segKKK.s segJJJ.s segLLL.s -o main
+       nm -j -n main | grep _sym > symbol.order
+       ${FAIL_IF_ERROR} diff symbol.order expected.order
+       ${PASS_IFF_GOOD_MACHO} main
+       
+clean:
+       rm -rf main symbol.order
diff --git a/unit-tests/test-cases/segment-order/expected.order b/unit-tests/test-cases/segment-order/expected.order
new file mode 100644 (file)
index 0000000..e05b042
--- /dev/null
@@ -0,0 +1,3 @@
+_sym_kkk
+_sym_jjj
+_sym_lll
diff --git a/unit-tests/test-cases/segment-order/main.c b/unit-tests/test-cases/segment-order/main.c
new file mode 100644 (file)
index 0000000..df77448
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+int main() { return 0; }
+
diff --git a/unit-tests/test-cases/segment-order/segJJJ.s b/unit-tests/test-cases/segment-order/segJJJ.s
new file mode 100644 (file)
index 0000000..d9f5f71
--- /dev/null
@@ -0,0 +1,7 @@
+
+               .section __JJJ,__jjj
+_sym_jjj:      .space  128
+
+
+
+
diff --git a/unit-tests/test-cases/segment-order/segKKK.s b/unit-tests/test-cases/segment-order/segKKK.s
new file mode 100644 (file)
index 0000000..70b1952
--- /dev/null
@@ -0,0 +1,7 @@
+
+               .section __KKK,__kkk
+_sym_kkk:      .space  128
+
+
+
+
diff --git a/unit-tests/test-cases/segment-order/segLLL.s b/unit-tests/test-cases/segment-order/segLLL.s
new file mode 100644 (file)
index 0000000..045eea4
--- /dev/null
@@ -0,0 +1,7 @@
+
+               .section __LLL,__lll
+_sym_lll:      .space  128
+
+
+
+
diff --git a/unit-tests/test-cases/special-labels/Makefile b/unit-tests/test-cases/special-labels/Makefile
new file mode 100644 (file)
index 0000000..060f12e
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# automatically strips labels starting with 'l' and 'L'
+#
+
+run: all
+
+all:
+       as -arch ${ARCH} -L extra.s -o extra.o
+       ${CC} ${CCFLAGS} main.c extra.o -o main
+       nm main | grep "lother" | ${FAIL_IF_STDIN}
+       nm main | grep "L123" | ${FAIL_IF_STDIN}
+       ${PASS_IFF_GOOD_MACHO} main
+
+clean:
+       rm -rf main *.o
diff --git a/unit-tests/test-cases/special-labels/extra.s b/unit-tests/test-cases/special-labels/extra.s
new file mode 100644 (file)
index 0000000..0755508
--- /dev/null
@@ -0,0 +1,9 @@
+
+
+       .data
+
+_foo:  .long 0
+lother:        .long 0
+L123:  .long 0
+_bar:  .long 0
+
diff --git a/unit-tests/test-cases/special-labels/main.c b/unit-tests/test-cases/special-labels/main.c
new file mode 100644 (file)
index 0000000..5c73586
--- /dev/null
@@ -0,0 +1,29 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+int main()
+{
+       return 0;
+}
index c3414e09d3330debcefd5d07674414a4bc94cd91..6e11c596a2bbc69478ec7b7059731f3817ea505d 100644 (file)
@@ -34,19 +34,19 @@ include ${TESTROOT}/include/common.makefile
 run: all
 
 all: hello.o other.o 
-       ${CXX} ${CCXXFLAGS} -gused hello.o other.o -o stabs-hello-${ARCH}
+       ${CXX} ${CCXXFLAGS} -gstabs+ -gused hello.o other.o -o stabs-hello-${ARCH}
        ${FAIL_IF_BAD_MACHO} stabs-hello-${ARCH}
        nm -ap stabs-hello-${ARCH} | grep FUN | grep _Z3fooi | wc -l > stabs-hello-foo-count
        echo "       1" > one
        ${PASS_IFF} diff stabs-hello-foo-count one
 
 hello.o : hello.cxx
-       ${CXX} ${CCXXFLAGS} -gused hello.cxx -c -o hello.o
+       ${CXX} ${CCXXFLAGS} -gstabs+ -gused hello.cxx -c -o $@
+       ${FAIL_IF_BAD_OBJ} $@
 
 other.o : other.cxx
-       ${CXX} ${CCXXFLAGS} -gused other.cxx -c -o other.o
+       ${CXX} ${CCXXFLAGS} -gstabs+ -gused other.cxx -c -o $@
+       ${FAIL_IF_BAD_OBJ} $@
 
 clean:
-       rm -rf stabs-hello-${ARCH}  hello.o other.o stabs-hello-${ARCH}.stabs stabs-hello-foo-count one
-
-
+       rm -rf stabs-hello-* *.o *.stabs stabs-hello-foo-count one
diff --git a/unit-tests/test-cases/stabs-coalesce/comment.txt b/unit-tests/test-cases/stabs-coalesce/comment.txt
new file mode 100644 (file)
index 0000000..f22b9a1
--- /dev/null
@@ -0,0 +1,3 @@
+The point of this test is a sanity check that ld removes the stabs associated with a copy of a coalesced 
+function that was removed.  Running nm through stabs-filter.pl produces connonical stabs
+that can be diffed against a checked in know good set of stabs
diff --git a/unit-tests/test-cases/stabs-directory-slash/Makefile b/unit-tests/test-cases/stabs-directory-slash/Makefile
new file mode 100644 (file)
index 0000000..5318933
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+# Test that file paths in a stab reference ends with a /
+# if there is no terminating /, gdb does not recognize this as a file path
+# The provided files coalesced1a.o coalesced1b.o are ppc64 linked
+# rdar://problem/4565088
+
+run: all
+
+all: 
+       $(CXX) -gstabs+ main.c -o outfile
+       ${FAIL_IF_BAD_MACHO} outfile
+       nm -ap outfile | ${PASS_IFF} grep '.*\<SO\>.*test-cases.*/$$'
+
+clean:
+       rm outfile* 
diff --git a/unit-tests/test-cases/stabs-directory-slash/main.c b/unit-tests/test-cases/stabs-directory-slash/main.c
new file mode 100644 (file)
index 0000000..54dc4c5
--- /dev/null
@@ -0,0 +1,3 @@
+main()
+{
+}
diff --git a/unit-tests/test-cases/stack_addr_no_size/Makefile.newtest b/unit-tests/test-cases/stack_addr_no_size/Makefile.newtest
new file mode 100644 (file)
index 0000000..a9e452f
--- /dev/null
@@ -0,0 +1,77 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+# Test the ld commands -stack_addr, -stack_size
+# Test using -stack_addr only
+
+
+ifeq (,${findstring 64,$(ARCH)})
+       STACK_ADDR = 0xC0000000
+       STACK_SIZE = 0x04000000
+       STACK_TOP  = 0xbc000000
+else
+#ifeq (${ARCH},x86_64)
+       STACK_ADDR = 0x0007fff5fc000000
+       STACK_TOP  = 0x00007fff57000000
+       STACK_SIZE = 0x0000000005000000
+#else
+       #STACK_ADDR = 0x0007ffff00000000
+       #STACK_TOP  = 0x0007fffefb000000
+       #STACK_SIZE = 0x0000000005000000
+#endif
+endif
+
+
+run: all
+
+all:
+# info seems to not work, use warning:
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c main.c -o main-${ARCH}.o
+
+
+       ${FAIL_IF_ERROR} ${LD} -arch ${ARCH} \
+               -stack_addr ${STACK_ADDR} \
+               -lcrt1.o -lSystem \
+               main-${ARCH}.o -o main \
+               2>lderr.out
+
+# Can check warning if desired.
+#ifeq (,${findstring 64,$(ARCH)})
+#      grep "warning no -stack_size specified using the default size" lderr.out | ${FAIL_IF_EMPTY}
+#else
+#      grep "failed: -stack_addr must be used with -stack_size" lderr.out | ${FAIL_IF_EMPTY}
+#endif
+
+       
+# Check for __UNIXSTACK section in object, check that it has the correct value
+       ${FAIL_IF_ERROR} ${OTOOL} -l main>ldcmds.out
+       (echo '1,/^[ ]*segname __UNIXSTACK$$/-d'; echo '/^[ ]*segname /,$$d'; echo w; echo q) | ed ldcmds.out >/dev/null
+       grep __UNIXSTACK ldcmds.out | ${FAIL_IF_EMPTY}
+       grep " vmsize[ ]*${STACK_SIZE}" ldcmds.out | ${FAIL_IF_EMPTY}
+       grep " vmaddr[ ]*${STACK_TOP}" ldcmds.out | ${FAIL_IF_EMPTY}
+       ${PASS_IFF_GOOD_MACHO} main
+
+clean:
+       rm -rf *.o *.err *.out main
diff --git a/unit-tests/test-cases/stack_addr_no_size/comment.txt b/unit-tests/test-cases/stack_addr_no_size/comment.txt
new file mode 100644 (file)
index 0000000..da74f89
--- /dev/null
@@ -0,0 +1,11 @@
+Test the ld commands -stack_addr, -stack_size (3939852 and 4729162)
+
+
+-stack_addr value
+Specifies the initial address of the stack pointer value, where value is a hexadecimal number rounded to the segment alignment. The default segment alignment is the target pagesize (currently, 1000 hexadecimal for the PowerPC and for i386). If -stack_size is specified and -stack_addr is not, a default stack address specific for the architecture being linked will be used and its value printed as a warning message. This creates a segment named __UNIXSTACK. Note that the initial stack address will be either at the high address of the segment or the low address of the segment depending on which direction the stack grows for the architecture being linked.
+
+
+-stack_size value
+Specifies the size of the stack segment value, where value is a hexadecimal number rounded to the segment alignment. The default segment alignment is the target pagesize (currently, 1000 hexadecimal for the PowerPC and for i386). If -stack_addr is specified and -stack_size is not, a default stack size specific for the architecture being linked will be used and its value printed as a warning message. This creates a segment named __UNIXSTACK .
+
+
diff --git a/unit-tests/test-cases/stack_addr_no_size/main.c b/unit-tests/test-cases/stack_addr_no_size/main.c
new file mode 100644 (file)
index 0000000..5c73586
--- /dev/null
@@ -0,0 +1,29 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+int main()
+{
+       return 0;
+}
diff --git a/unit-tests/test-cases/stack_addr_size/Makefile b/unit-tests/test-cases/stack_addr_size/Makefile
new file mode 100644 (file)
index 0000000..49e6467
--- /dev/null
@@ -0,0 +1,71 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+# Test the ld commands -stack_addr, -stack_size
+# Test using both -stack_add and -stack_size
+
+ifeq (,${findstring 64,$(ARCH)})
+       STACK_ADDR = 0xCC000000
+       STACK_SIZE = 0x05000000
+       STACK_TOP  = 0xc7000000
+else
+       STACK_ADDR = 0x110000000
+       STACK_TOP  = 0x000000010b000000
+       STACK_SIZE = 0x0000000005000000
+endif
+
+
+run: all
+
+
+
+all:
+# info seems to not work, use warning:
+       ${CC} ${CCFLAGS} -c main.c -o main-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} main-${ARCH}.o
+
+       ${LD} -arch ${ARCH} \
+               -stack_addr ${STACK_ADDR} -stack_size ${STACK_SIZE} \
+               -lcrt1.o -lSystem \
+               main-${ARCH}.o -o main \
+# # Can check warning if desired.
+#              > lderr.out
+#ifeq (,${findstring 64,$(ARCH)})
+#      grep "warning no -stack_size specified using the default size" lderr.out | ${FAIL_IF_EMPTY}
+#else
+#      grep "failed: -stack_addr must be used with -stack_size" lderr.out | ${FAIL_IF_EMPTY}
+#endif
+
+# Check for __UNIXSTACK section in object, check that it has the correct value
+       ${FAIL_IF_ERROR} ${OTOOL} -l main>ldcmds.out
+       (echo '1,/^[ ]*segname __UNIXSTACK$$/-d'; echo '/^[ ]*segname /,$$d'; echo w; echo q) | ed ldcmds.out >/dev/null
+       grep __UNIXSTACK ldcmds.out | ${FAIL_IF_EMPTY}
+       grep " vmaddr[ ]*${STACK_TOP}" ldcmds.out | ${FAIL_IF_EMPTY}
+       grep " vmsize[ ]*${STACK_SIZE}" ldcmds.out | ${FAIL_IF_EMPTY}
+
+       ${PASS_IFF_GOOD_MACHO} main
+
+clean:
+       rm -rf *.o *.err *.out main
diff --git a/unit-tests/test-cases/stack_addr_size/comment.txt b/unit-tests/test-cases/stack_addr_size/comment.txt
new file mode 100644 (file)
index 0000000..da74f89
--- /dev/null
@@ -0,0 +1,11 @@
+Test the ld commands -stack_addr, -stack_size (3939852 and 4729162)
+
+
+-stack_addr value
+Specifies the initial address of the stack pointer value, where value is a hexadecimal number rounded to the segment alignment. The default segment alignment is the target pagesize (currently, 1000 hexadecimal for the PowerPC and for i386). If -stack_size is specified and -stack_addr is not, a default stack address specific for the architecture being linked will be used and its value printed as a warning message. This creates a segment named __UNIXSTACK. Note that the initial stack address will be either at the high address of the segment or the low address of the segment depending on which direction the stack grows for the architecture being linked.
+
+
+-stack_size value
+Specifies the size of the stack segment value, where value is a hexadecimal number rounded to the segment alignment. The default segment alignment is the target pagesize (currently, 1000 hexadecimal for the PowerPC and for i386). If -stack_addr is specified and -stack_size is not, a default stack size specific for the architecture being linked will be used and its value printed as a warning message. This creates a segment named __UNIXSTACK .
+
+
diff --git a/unit-tests/test-cases/stack_addr_size/main.c b/unit-tests/test-cases/stack_addr_size/main.c
new file mode 100644 (file)
index 0000000..5c73586
--- /dev/null
@@ -0,0 +1,29 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+int main()
+{
+       return 0;
+}
diff --git a/unit-tests/test-cases/stack_size_no_addr/Makefile b/unit-tests/test-cases/stack_size_no_addr/Makefile
new file mode 100644 (file)
index 0000000..a13d767
--- /dev/null
@@ -0,0 +1,78 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+# Test the ld commands -stack_addr, -stack_size
+# Test using -stack_size only
+
+ifeq (,${findstring 64,$(ARCH)})
+       STACK_ADDR = 0xC0000000
+       STACK_SIZE = 0x05000000
+       STACK_TOP  = 0xbb000000
+else
+#ifeq (${ARCH},x86_64)
+       STACK_ADDR = 0x0007fff5fc000000
+       STACK_TOP  = 0x00007fff57000000
+       STACK_SIZE = 0x0000000005000000
+#else
+       #STACK_ADDR = 0x0007ffff00000000
+       #STACK_TOP  = 0x0007fffefb000000
+       #STACK_SIZE = 0x0000000005000000
+#endif
+endif
+
+
+run: all
+
+
+
+all:
+# info seems to not work, use warning:
+       ${CC} ${CCFLAGS} -c main.c -o main-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} main-${ARCH}.o
+
+
+       ${LD} -arch ${ARCH} \
+               -stack_size ${STACK_SIZE} \
+               -lcrt1.o -lSystem \
+               main-${ARCH}.o -o main \
+               2>lderr.out
+
+# Can check warning if desired.
+#ifeq (,${findstring 64,$(ARCH)})
+#      grep "warning no -stack_size specified using the default size" lderr.out | ${FAIL_IF_EMPTY}
+#else
+#      grep "failed: -stack_addr must be used with -stack_size" lderr.out | ${FAIL_IF_EMPTY}
+#endif
+
+# Check for __UNIXSTACK section in object, check that it has the correct value
+       ${FAIL_IF_ERROR} ${OTOOL} -l main>ldcmds.out
+       (echo '1,/^[ ]*segname __UNIXSTACK$$/-d'; echo '/^[ ]*segname /,$$d'; echo w; echo q) | ed ldcmds.out >/dev/null
+       grep __UNIXSTACK ldcmds.out | ${FAIL_IF_EMPTY}
+       grep " vmsize[ ]*${STACK_SIZE}" ldcmds.out | ${FAIL_IF_EMPTY}
+       grep " vmaddr[ ]*${STACK_TOP}" ldcmds.out | ${FAIL_IF_EMPTY}
+       ${PASS_IFF_GOOD_MACHO} main
+
+clean:
+       rm -rf *.o *.err *.out main
diff --git a/unit-tests/test-cases/stack_size_no_addr/comment.txt b/unit-tests/test-cases/stack_size_no_addr/comment.txt
new file mode 100644 (file)
index 0000000..5933975
--- /dev/null
@@ -0,0 +1,11 @@
+Test the ld commands -stack_addr, -stack_size
+
+
+-stack_addr value
+Specifies the initial address of the stack pointer value, where value is a hexadecimal number rounded to the segment alignment. The default segment alignment is the target pagesize (currently, 1000 hexadecimal for the PowerPC and for i386). If -stack_size is specified and -stack_addr is not, a default stack address specific for the architecture being linked will be used and its value printed as a warning message. This creates a segment named __UNIXSTACK. Note that the initial stack address will be either at the high address of the segment or the low address of the segment depending on which direction the stack grows for the architecture being linked.
+
+
+-stack_size value
+Specifies the size of the stack segment value, where value is a hexadecimal number rounded to the segment alignment. The default segment alignment is the target pagesize (currently, 1000 hexadecimal for the PowerPC and for i386). If -stack_addr is specified and -stack_size is not, a default stack size specific for the architecture being linked will be used and its value printed as a warning message. This creates a segment named __UNIXSTACK .
+
+
diff --git a/unit-tests/test-cases/stack_size_no_addr/main.c b/unit-tests/test-cases/stack_size_no_addr/main.c
new file mode 100644 (file)
index 0000000..5c73586
--- /dev/null
@@ -0,0 +1,29 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+int main()
+{
+       return 0;
+}
index cee5f44b99354680177d5aa7bf782b85cdf059d2..8e14133fd6132f4e22dd81ec7a48411f74be9e5a 100644 (file)
@@ -2,14 +2,14 @@
 # Copyright (c) 2006 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,
@@ -17,7 +17,7 @@
 # FITNESS FOR A PARTICULAR PURPOSE, 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 = ../..
@@ -28,13 +28,16 @@ include ${TESTROOT}/include/common.makefile
 # can link a static executable (requires non-public archives)
 #
 
-run: all
+run:
+       @if [ ${ARCH} = ppc ] || [ ${ARCH} = i386 ] ; then \
+       $(MAKE) all ; \
+       else \
+       $(PASS_IFF) /usr/bin/true ; \
+       fi
 
 all:
-       ${CC} ${CCFLAGS} test.c -static -o test-${ARCH} -L/usr/local/lib/system -lc_static -lm_static
+       ${CC} ${CCFLAGS} test.c -static -o test-${ARCH} -L/usr/local/lib/system -lc_static -lm_static -dead_strip 2>/dev/null
        ${PASS_IFF_GOOD_MACHO} test-${ARCH}
 
 clean:
-       rm  test-${ARCH}
-       
-
+       rm -rf test-*
diff --git a/unit-tests/test-cases/static-executable/comment.txt b/unit-tests/test-cases/static-executable/comment.txt
new file mode 100644 (file)
index 0000000..bc535a3
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a static executable (requires non-public archives)
diff --git a/unit-tests/test-cases/static-strip/Makefile.newtest b/unit-tests/test-cases/static-strip/Makefile.newtest
new file mode 100644 (file)
index 0000000..343855e
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a static executable (requires non-public archives)
+#
+
+run: all
+
+all:
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} test.c -static -o test-${ARCH} -L/usr/local/lib/system -lc_static -lm_static
+       ${FAIL_IF_BAD_MACHO} test-${ARCH}
+       ${FAIL_IF_ERROR} strip test-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} test-${ARCH}
+
+clean:
+       rm -rf test-*
diff --git a/unit-tests/test-cases/static-strip/comment.txt b/unit-tests/test-cases/static-strip/comment.txt
new file mode 100644 (file)
index 0000000..bc535a3
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a static executable (requires non-public archives)
diff --git a/unit-tests/test-cases/static-strip/test.c b/unit-tests/test-cases/static-strip/test.c
new file mode 100644 (file)
index 0000000..ab472fb
--- /dev/null
@@ -0,0 +1,28 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+int main()
+{
+       return 0;
+}
diff --git a/unit-tests/test-cases/strip-test2/Makefile b/unit-tests/test-cases/strip-test2/Makefile
new file mode 100644 (file)
index 0000000..778770e
--- /dev/null
@@ -0,0 +1,70 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+# Test strip: symbols referenced by indirect symbol table entries that can'tÊ 
+# be stripped in:
+# __ZN9__gnu_cxx13new_allocatorIiE7destroyEPi
+# __ZNKSt12_Vector_baseIiSaIiEE13get_allocatorEv
+# __ZN9__gnu_cxx13new_allocatorIiEC2ERKS1_
+# __ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPim
+# __ZN9__gnu_cxx13new_allocatorIiED2Ev
+# __ZNSt6vectorIiSaIiEEC1ERKS0_
+# __ZNSaIiEC1ERKS_
+# __ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim
+# __ZNSt12_Vector_baseIiSaIiEE12_Vector_implC1ERKS0_
+# __ZNSaIiED2Ev
+# __ZNSt12_Vector_baseIiSaIiEED2Ev
+# __ZNSaIiEC1Ev
+# __ZNSt12_Vector_baseIiSaIiEEC2ERKS0_
+# __ZNSt6vectorIiSaIiEED1Ev
+# __ZNSaIiED1Ev
+# __ZSt8_DestroyIPiSaIiEEvT_S2_T0_
+# __ZN9__gnu_cxx13new_allocatorIiEC2Ev
+# __ZNSaIiEC2ERKS_
+# __ZNSt12_Vector_baseIiSaIiEE12_Vector_implD1Ev
+
+
+run: all
+
+
+all:
+       $(CXX) main.cxx -arch ${ARCH} -o main
+       ${FAIL_IF_BAD_MACHO} main
+       ${FAIL_IF_ERROR} nm -j main >main-no-strip.nm
+       $(CXX) main.cxx -arch ${ARCH} -o main
+       ${FAIL_IF_BAD_MACHO} main
+
+       # Make sure there are no symbols in the stripped file that aren't
+       # in the unstripped
+       nm -j main | comm -23 - main-no-strip.nm | ${FAIL_IF_STDIN}
+
+       # Now make sure that all the __Z symbols exist
+       strip_cnt=`nm -j main | comm -12 - main-no-strip.nm | grep -c __Z`; \
+       nostrip_cnt=`nm -j main|grep -c __Z`; \
+       [ x"$$strip_cnt" = x"$$nostrip_cnt" ]
+       @echo PASS $$UNIT_TEST_NAME
+
+clean:
+       rm -rf *.o main-* main
diff --git a/unit-tests/test-cases/strip-test2/comment.txt b/unit-tests/test-cases/strip-test2/comment.txt
new file mode 100644 (file)
index 0000000..a99f78e
--- /dev/null
@@ -0,0 +1,21 @@
+Test strip: symbols referenced by indirect symbol table entries can't be stripped (4096290)
+
+__ZN9__gnu_cxx13new_allocatorIiE7destroyEPi
+__ZNKSt12_Vector_baseIiSaIiEE13get_allocatorEv
+__ZN9__gnu_cxx13new_allocatorIiEC2ERKS1_
+__ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPim
+__ZN9__gnu_cxx13new_allocatorIiED2Ev
+__ZNSt6vectorIiSaIiEEC1ERKS0_
+__ZNSaIiEC1ERKS_
+__ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim
+__ZNSt12_Vector_baseIiSaIiEE12_Vector_implC1ERKS0_
+__ZNSaIiED2Ev
+__ZNSt12_Vector_baseIiSaIiEED2Ev
+__ZNSaIiEC1Ev
+__ZNSt12_Vector_baseIiSaIiEEC2ERKS0_
+__ZNSt6vectorIiSaIiEED1Ev
+__ZNSaIiED1Ev
+__ZSt8_DestroyIPiSaIiEEvT_S2_T0_
+__ZN9__gnu_cxx13new_allocatorIiEC2Ev
+__ZNSaIiEC2ERKS_
+__ZNSt12_Vector_baseIiSaIiEE12_Vector_implD1Ev
diff --git a/unit-tests/test-cases/strip-test2/main.cxx b/unit-tests/test-cases/strip-test2/main.cxx
new file mode 100644 (file)
index 0000000..dd65fef
--- /dev/null
@@ -0,0 +1,6 @@
+#include <vector>
+int main()
+{
+       std::vector<int> stuff;
+       return 0;
+}
diff --git a/unit-tests/test-cases/strip-test3/Makefile.newtest b/unit-tests/test-cases/strip-test3/Makefile.newtest
new file mode 100644 (file)
index 0000000..c1ad4c4
--- /dev/null
@@ -0,0 +1,71 @@
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+# Test strip: symbols referenced by indirect symbol table entries that can'tÊ 
+# be stripped in:
+# __ZN9__gnu_cxx13new_allocatorIiE7destroyEPi
+# __ZNKSt12_Vector_baseIiSaIiEE13get_allocatorEv
+# __ZN9__gnu_cxx13new_allocatorIiEC2ERKS1_
+# __ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPim
+# __ZN9__gnu_cxx13new_allocatorIiED2Ev
+# __ZNSt6vectorIiSaIiEEC1ERKS0_
+# __ZNSaIiEC1ERKS_
+# __ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim
+# __ZNSt12_Vector_baseIiSaIiEE12_Vector_implC1ERKS0_
+# __ZNSaIiED2Ev
+# __ZNSt12_Vector_baseIiSaIiEED2Ev
+# __ZNSaIiEC1Ev
+# __ZNSt12_Vector_baseIiSaIiEEC2ERKS0_
+# __ZNSt6vectorIiSaIiEED1Ev
+# __ZNSaIiED1Ev
+# __ZSt8_DestroyIPiSaIiEEvT_S2_T0_
+# __ZN9__gnu_cxx13new_allocatorIiEC2Ev
+# __ZNSaIiEC2ERKS_
+# __ZNSt12_Vector_baseIiSaIiEE12_Vector_implD1Ev
+
+
+run: all
+
+
+all:
+       ${FAIL_IF_ERROR} $(CXX) main.cxx -arch ${ARCH} -o main
+       ${FAIL_IF_BAD_MACHO} main
+       ${FAIL_IF_ERROR} nm -j main >main-no-strip.nm
+       ${FAIL_IF_ERROR} strip main
+       ${FAIL_IF_BAD_MACHO} main
+       ${FAIL_IF_ERROR} $(CXX) main.cxx -arch ${ARCH} -s -o main
+       ${PASS_IFF_GOOD_MACHO} main
+
+       # Make sure there are no symbols in the stripped file that aren't
+       # in the unstripped
+       nm -j main | comm -23 - main-no-strip.nm | ${FAIL_IF_STDIN}
+
+       # Now make sure that all the __Z symbols exist
+       strip_cnt=`nm -j main | comm -12 - main-no-strip.nm | grep -c __Z`; \
+       nostrip_cnt=`nm -j main|grep -c __Z`; \ 
+       [ x"$$strip_cnt" = x"$$nostrip_cnt" ]
+       @echo PASS $$UNIT_TEST_NAME
+clean:
+       rm -rf *.o main main-* *.nm *.out
diff --git a/unit-tests/test-cases/strip-test3/comment.txt b/unit-tests/test-cases/strip-test3/comment.txt
new file mode 100644 (file)
index 0000000..a99f78e
--- /dev/null
@@ -0,0 +1,21 @@
+Test strip: symbols referenced by indirect symbol table entries can't be stripped (4096290)
+
+__ZN9__gnu_cxx13new_allocatorIiE7destroyEPi
+__ZNKSt12_Vector_baseIiSaIiEE13get_allocatorEv
+__ZN9__gnu_cxx13new_allocatorIiEC2ERKS1_
+__ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPim
+__ZN9__gnu_cxx13new_allocatorIiED2Ev
+__ZNSt6vectorIiSaIiEEC1ERKS0_
+__ZNSaIiEC1ERKS_
+__ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim
+__ZNSt12_Vector_baseIiSaIiEE12_Vector_implC1ERKS0_
+__ZNSaIiED2Ev
+__ZNSt12_Vector_baseIiSaIiEED2Ev
+__ZNSaIiEC1Ev
+__ZNSt12_Vector_baseIiSaIiEEC2ERKS0_
+__ZNSt6vectorIiSaIiEED1Ev
+__ZNSaIiED1Ev
+__ZSt8_DestroyIPiSaIiEEvT_S2_T0_
+__ZN9__gnu_cxx13new_allocatorIiEC2Ev
+__ZNSaIiEC2ERKS_
+__ZNSt12_Vector_baseIiSaIiEE12_Vector_implD1Ev
diff --git a/unit-tests/test-cases/strip-test3/main.cxx b/unit-tests/test-cases/strip-test3/main.cxx
new file mode 100644 (file)
index 0000000..dd65fef
--- /dev/null
@@ -0,0 +1,6 @@
+#include <vector>
+int main()
+{
+       std::vector<int> stuff;
+       return 0;
+}
diff --git a/unit-tests/test-cases/strip_local/Makefile b/unit-tests/test-cases/strip_local/Makefile
new file mode 100644 (file)
index 0000000..f32267c
--- /dev/null
@@ -0,0 +1,53 @@
+##
+# Copyright (c) 2006-2007 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
+
+#
+# This test case checks merges two .o files.  One uses
+# a lazy and non-lazy pointer to access the second.
+# The result then has local symbols stripped.  So the
+# end result is a .o file with a lazy and non-lazy pointer to 
+# anonymous stuff.
+#
+#
+
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} hello.c -c
+       ${FAIL_IF_BAD_OBJ} hello.o
+
+       ${CC} ${CCFLAGS} foo.c -c
+       ${FAIL_IF_BAD_OBJ} foo.o
+
+       ${LD} -r hello.o foo.o -o hellofoo.o
+       ${FAIL_IF_BAD_OBJ} hellofoo.o
+
+       strip -x hellofoo.o -o hellofoostripped.o
+       ${CC} ${CCFLAGS} hellofoostripped.o -o main
+       ${PASS_IFF_GOOD_MACHO} main
+
+clean:
+       rm -rf *.o main
diff --git a/unit-tests/test-cases/strip_local/foo.c b/unit-tests/test-cases/strip_local/foo.c
new file mode 100644 (file)
index 0000000..defa5eb
--- /dev/null
@@ -0,0 +1,8 @@
+
+
+int __attribute__((visibility("hidden"))) data = 3;
+
+void __attribute__((visibility("hidden"))) func(int x) { }
+
+
+
diff --git a/unit-tests/test-cases/strip_local/hello.c b/unit-tests/test-cases/strip_local/hello.c
new file mode 100644 (file)
index 0000000..2deed42
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+extern int data;
+extern void func(int);
+
+int main()
+{
+       func(data);
+}
+
diff --git a/unit-tests/test-cases/stripped-indirect-symbol-table/Makefile b/unit-tests/test-cases/stripped-indirect-symbol-table/Makefile
new file mode 100644 (file)
index 0000000..c0647b3
--- /dev/null
@@ -0,0 +1,57 @@
+##
+# Copyright (c) 2007 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
+
+ifeq "${ARCH}"  "i386"
+       POINTER_SEGMENT = __IMPORT
+       POINTER_SECTION  = __pointers
+else
+       POINTER_SEGMENT = __DATA
+       POINTER_SECTION  = __nl_symbol_ptr
+endif
+
+
+#
+# Test that using strip -R to selectively strip symbol names
+# of of a .o file still works with ld.
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} a.c -c -o a.o
+       ${CC} ${CCFLAGS} b.c -c -o b.o
+       ${CC} ${CCFLAGS} c.c -c -o c.o
+       ${CC} ${CCFLAGS} func.c -c -o func.o
+       ${LD} -arch ${ARCH} -r a.o b.o c.o -o most.o
+       strip -x -R strip.list most.o -o most.stripped.o
+       ${CC} ${CCFLAGS} most.stripped.o func.o -dynamiclib -o dylib1
+       ${LD} -arch ${ARCH} -r most.stripped.o func.o -o all.o
+       ${CC} ${CCFLAGS} all.o  -dynamiclib -o dylib2   
+       otool -X -s ${POINTER_SEGMENT} ${POINTER_SECTION} dylib1 >dylib1.pointers
+       otool -X -s ${POINTER_SEGMENT} ${POINTER_SECTION} dylib2 >dylib2.pointers
+       ${PASS_IFF} diff dylib1.pointers dylib2.pointers
+
+clean:
+       rm -rf *.o dylib1 dylib2 *.pointers
diff --git a/unit-tests/test-cases/stripped-indirect-symbol-table/a.c b/unit-tests/test-cases/stripped-indirect-symbol-table/a.c
new file mode 100644 (file)
index 0000000..141b6d9
--- /dev/null
@@ -0,0 +1,7 @@
+
+int aData = 0;
+
+void a()
+{
+       ++aData;
+}
diff --git a/unit-tests/test-cases/stripped-indirect-symbol-table/b.c b/unit-tests/test-cases/stripped-indirect-symbol-table/b.c
new file mode 100644 (file)
index 0000000..9608402
--- /dev/null
@@ -0,0 +1,12 @@
+
+int bData = 0;
+
+void b()
+{
+       ++bData;
+}
+
+void bb()
+{
+       ++bData;
+}
diff --git a/unit-tests/test-cases/stripped-indirect-symbol-table/c.c b/unit-tests/test-cases/stripped-indirect-symbol-table/c.c
new file mode 100644 (file)
index 0000000..db8276a
--- /dev/null
@@ -0,0 +1,11 @@
+extern void b();
+extern void bb();
+
+extern void func(void*);
+
+
+void c()
+{
+       func(&b);
+       func(&bb);
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/stripped-indirect-symbol-table/func.c b/unit-tests/test-cases/stripped-indirect-symbol-table/func.c
new file mode 100644 (file)
index 0000000..5724811
--- /dev/null
@@ -0,0 +1 @@
+void func(void* x) {}
diff --git a/unit-tests/test-cases/stripped-indirect-symbol-table/strip.list b/unit-tests/test-cases/stripped-indirect-symbol-table/strip.list
new file mode 100644 (file)
index 0000000..77ac6e9
--- /dev/null
@@ -0,0 +1,2 @@
+_b
+_bb
diff --git a/unit-tests/test-cases/stub-generation/Makefile b/unit-tests/test-cases/stub-generation/Makefile
new file mode 100644 (file)
index 0000000..9e6ecc0
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Check that ld generates correct stubs 
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} test.c -dynamiclib -Wl,-interposable -o libtest.dylib
+       # only stub should be to _test
+       otool -Iv libtest.dylib | grep '1 entries' | ${FAIL_IF_EMPTY}
+       otool -Iv libtest.dylib | grep '_test' | ${FAIL_IF_EMPTY}
+       ${PASS_IFF_GOOD_MACHO} libtest.dylib
+       
+
+clean:
+       rm libtest.dylib
diff --git a/unit-tests/test-cases/stub-generation/test.c b/unit-tests/test-cases/stub-generation/test.c
new file mode 100644 (file)
index 0000000..4573622
--- /dev/null
@@ -0,0 +1,40 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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>
+
+const char kMyStr[] = "hello";
+
+int test()
+{
+       return 10;
+}
+
+
+const char* getstr()
+{
+       test();
+       return kMyStr;
+}
+
+
diff --git a/unit-tests/test-cases/symbol-moving/Makefile b/unit-tests/test-cases/symbol-moving/Makefile
new file mode 100644 (file)
index 0000000..fc85d7b
--- /dev/null
@@ -0,0 +1,93 @@
+##
+# Copyright (c) 2007 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 magic $ld$ symbols which tell ld to view exported symbols
+# differently than dyld sees them.
+#
+# In this test case aaa and bbb both moved between libfoo and libar
+# between 10.4 and 10.5.
+#
+
+
+run: all
+
+all:
+       # In this test case aaa and bbb both moved between libfoo and libar
+       # between 10.4 and 10.5.
+       ${CC} ${CCFLAGS} -dynamiclib bar.c bbb.c anotb.c -o libbar.dylib  
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c aaa.c bnota.c -o libfoo.dylib 
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       ${CC} ${CCFLAGS} main.c -o main-10.4  libfoo.dylib libbar.dylib -mmacosx-version-min=10.4
+       nm -m main-10.4 | grep _aaa | grep libbar | ${FAIL_IF_EMPTY}
+       nm -m main-10.4 | grep _bbb | grep libfoo | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c -o main-10.4a libbar.dylib libfoo.dylib -mmacosx-version-min=10.4
+       nm -m main-10.4a | grep _aaa | grep libbar | ${FAIL_IF_EMPTY}
+       nm -m main-10.4a | grep _bbb | grep libfoo | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c -o main-10.5  libfoo.dylib libbar.dylib -mmacosx-version-min=10.5
+       nm -m main-10.5 | grep _aaa | grep libfoo | ${FAIL_IF_EMPTY}
+       nm -m main-10.5 | grep _bbb | grep libbar | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c -o main-10.5a libbar.dylib libfoo.dylib  -mmacosx-version-min=10.5
+       nm -m main-10.5a | grep _aaa | grep libfoo | ${FAIL_IF_EMPTY}
+       nm -m main-10.5a | grep _bbb | grep libbar | ${FAIL_IF_EMPTY}
+       # In this test case aaa and bbb both moved between subframeworks of Foo and Bar
+       # between 10.4 and 10.5.
+       mkdir -p Frameworks/Foo.framework/Frameworks/subFoo.framework
+       ${CC} ${CCFLAGS} -dynamiclib foo.c aaa.c -o Frameworks/Foo.framework/Frameworks/subFoo.framework/subFoo \
+               -install_name /System/Library/Frameworks/Foo.framework/Frameworks/subFoo.framework/subFoo \
+               -umbrella Foo
+       ${CC} ${CCFLAGS} -dynamiclib bnota.c -o Frameworks/Foo.framework/Foo \
+               -install_name /System/Library/Frameworks/Frameworks/Foo.framework/Foo \
+               Frameworks/Foo.framework/Frameworks/subFoo.framework/subFoo
+       mkdir -p Frameworks/Bar.framework/Frameworks/subBar.framework
+       ${CC} ${CCFLAGS} -dynamiclib bar.c bbb.c -o Frameworks/Bar.framework/Frameworks/subBar.framework/subBar \
+               -install_name /System/Library/Frameworks/Bar.framework/Frameworks/subBar.framework/subBar \
+               -umbrella Bar
+       ${CC} ${CCFLAGS} -dynamiclib anotb.c -o Frameworks/Bar.framework/Bar \
+               -install_name /System/Library/Frameworks/Frameworks/Bar.framework/Bar \
+               Frameworks/Bar.framework/Frameworks/subBar.framework/subBar
+       ${CC} ${CCFLAGS} main.c -o main-10.4  -framework Foo -framework Bar  -mmacosx-version-min=10.4 \
+               -F./Frameworks -F./Frameworks/Bar.framework/Frameworks -F./Frameworks/Foo.framework/Frameworks 
+       nm -m main-10.4 | grep _aaa | grep " Bar" | ${FAIL_IF_EMPTY}
+       nm -m main-10.4 | grep _bbb | grep " Foo" | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c -o main-10.4a -framework Bar  -framework Foo  -mmacosx-version-min=10.4 \
+               -F./Frameworks -F./Frameworks/Bar.framework/Frameworks -F./Frameworks/Foo.framework/Frameworks 
+       nm -m main-10.4a | grep _aaa | grep " Bar" | ${FAIL_IF_EMPTY}
+       nm -m main-10.4a | grep _bbb | grep " Foo" | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c -o main-10.5  -framework Foo -framework Bar  -mmacosx-version-min=10.5 \
+               -F./Frameworks -F./Frameworks/Bar.framework/Frameworks -F./Frameworks/Foo.framework/Frameworks 
+       nm -m main-10.5 | grep _aaa | grep " Foo" | ${FAIL_IF_EMPTY}
+       nm -m main-10.5 | grep _bbb | grep " Bar" | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main.c -o main-10.5a -framework Bar  -framework Foo  -mmacosx-version-min=10.5 \
+               -F./Frameworks -F./Frameworks/Bar.framework/Frameworks -F./Frameworks/Foo.framework/Frameworks 
+       nm -m main-10.5a | grep _aaa | grep " Foo" | ${FAIL_IF_EMPTY}
+       nm -m main-10.5a | grep _bbb | grep " Bar" | ${FAIL_IF_EMPTY}
+       ${PASS_IFF} /usr/bin/true
+
+
+clean:
+
+       rm -rf  libbar.dylib libfoo.dylib main-10.4 main-10.5 main-10.4a main-10.5a
diff --git a/unit-tests/test-cases/symbol-moving/aaa.c b/unit-tests/test-cases/symbol-moving/aaa.c
new file mode 100644 (file)
index 0000000..71123eb
--- /dev/null
@@ -0,0 +1,3 @@
+
+void aaa() {}
+
diff --git a/unit-tests/test-cases/symbol-moving/anotb.c b/unit-tests/test-cases/symbol-moving/anotb.c
new file mode 100644 (file)
index 0000000..60fcf64
--- /dev/null
@@ -0,0 +1,26 @@
+
+
+#define SYMBOL_IS_HERE_IN_10_4(sym) \
+                 extern const char sym##_tmp __asm("$ld$add$os10.4$_" #sym ); const char sym##_tmp = 0;
+
+#define SYMBOL_IS_HERE_IN_10_5(sym) \
+                 extern const char sym##_tmp __asm("$ld$add$os10.5$_" #sym ); const char sym##_tmp = 0;
+
+#define SYMBOL_NOT_HERE_IN_10_4(sym) \
+                 extern const char sym##_tmp __asm("$ld$hide$os10.4$_" #sym ); const char sym##_tmp = 0;
+                               
+#define SYMBOL_NOT_HERE_IN_10_5(sym) \
+                 extern const char sym##_tmp __asm("$ld$hide$os10.5$_" #sym ); const char sym##_tmp = 0;
+                               
+                               
+//                     10.4            10.5
+// aaa         libbar          libfoo
+// bbb         libfoo          libbar
+//
+
+// bbb is new here in 10.5.  It was elsewhere in 10.4
+SYMBOL_NOT_HERE_IN_10_4(bbb)
+
+// aaa was here in 10.4 and move elsewhere 
+SYMBOL_IS_HERE_IN_10_4(aaa)
+
diff --git a/unit-tests/test-cases/symbol-moving/bar.c b/unit-tests/test-cases/symbol-moving/bar.c
new file mode 100644 (file)
index 0000000..e425999
--- /dev/null
@@ -0,0 +1 @@
+void bar() {}
diff --git a/unit-tests/test-cases/symbol-moving/bbb.c b/unit-tests/test-cases/symbol-moving/bbb.c
new file mode 100644 (file)
index 0000000..b6e9cc0
--- /dev/null
@@ -0,0 +1 @@
+void bbb() {}
diff --git a/unit-tests/test-cases/symbol-moving/bnota.c b/unit-tests/test-cases/symbol-moving/bnota.c
new file mode 100644 (file)
index 0000000..d29b878
--- /dev/null
@@ -0,0 +1,25 @@
+#define SYMBOL_IS_HERE_IN_10_4(sym) \
+                 extern const char sym##_tmp __asm("$ld$add$os10.4$_" #sym ); const char sym##_tmp = 0;
+
+#define SYMBOL_IS_HERE_IN_10_5(sym) \
+                 extern const char sym##_tmp __asm("$ld$add$os10.5$_" #sym ); const char sym##_tmp = 0;
+
+#define SYMBOL_NOT_HERE_IN_10_4(sym) \
+                 extern const char sym##_tmp __asm("$ld$hide$os10.4$_" #sym ); const char sym##_tmp = 0;
+                               
+#define SYMBOL_NOT_HERE_IN_10_5(sym) \
+                 extern const char sym##_tmp __asm("$ld$hide$os10.5$_" #sym ); const char sym##_tmp = 0;
+                               
+                               
+//                     10.4            10.5
+// aaa         libbar          libfoo
+// bbb         libfoo          libbar
+//
+
+
+// bbb was here in 10.4 and move elsewhere 
+SYMBOL_IS_HERE_IN_10_4(bbb)
+
+// aaa is new here in 10.5.  It was elsewhere in 10.4
+SYMBOL_NOT_HERE_IN_10_4(aaa)
+
diff --git a/unit-tests/test-cases/symbol-moving/foo.c b/unit-tests/test-cases/symbol-moving/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/symbol-moving/main.c b/unit-tests/test-cases/symbol-moving/main.c
new file mode 100644 (file)
index 0000000..902e908
--- /dev/null
@@ -0,0 +1,17 @@
+
+extern void foo();
+extern void bar();
+
+extern void aaa();
+extern void bbb();
+
+
+int main()
+{
+       foo();
+       bar();
+       aaa();
+       bbb();
+       
+       return 0;
+}
index 2115e7b3271fad560b8aafd97e0dca700fb804fe..092aa2e5d1b820fabed927730d2589de119ac0d3 100644 (file)
@@ -2,14 +2,14 @@
 # Copyright (c) 2006 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,
@@ -17,7 +17,7 @@
 # FITNESS FOR A PARTICULAR PURPOSE, 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 = ../..
@@ -33,12 +33,13 @@ run: all
 
 all:
        ${CC} ${CCFLAGS} test.c -c -o test.${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} test.${ARCH}.o
+
        ${LD} -arch ${ARCH} -r test.${ARCH}.o -o test-r.${ARCH}.o
-       ${OBJECTDUMP} test-r.${ARCH}.o | grep tentative | ${PASS_IFF_STDIN}
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} test-r.${ARCH}.o | grep tentative | ${FAIL_IF_EMPTY}
+
        ${LD} -arch ${ARCH} -r -d test.${ARCH}.o -o test-r-d.${ARCH}.o
-       ${OBJECTDUMP} test-r-d.${ARCH}.o | grep tentative | ${PASS_IFF_EMPTY}
+       ${FAIL_IF_ERROR} ${OBJECTDUMP} test-r-d.${ARCH}.o | grep tentative | ${PASS_IFF_EMPTY}
 
 clean:
-       rm -rf test.${ARCH}.o test-r.${ARCH}.o 
-       
-
+       rm -rf *.o
diff --git a/unit-tests/test-cases/tentative-to-real/comment.txt b/unit-tests/test-cases/tentative-to-real/comment.txt
new file mode 100644 (file)
index 0000000..de80bea
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is to verify that -r -d will transform a tentative definition into a real one.
diff --git a/unit-tests/test-cases/undefined-dynamic-lookup/Makefile b/unit-tests/test-cases/undefined-dynamic-lookup/Makefile
new file mode 100644 (file)
index 0000000..eebcc37
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2007 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
+
+#
+# Check that -U and -undefined dynamic_lookup work
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} main.c -o main -undefined dynamic_lookup 
+       nm -m main | grep _foo | grep "dynamically looked up" | ${FAIL_IF_EMPTY}
+       ${FAIL_IF_BAD_MACHO} main
+
+       ${CC} ${CCFLAGS} main.c -o main -Wl,-U,_foo 
+       nm -m main | grep _foo | grep "dynamically looked up" | ${FAIL_IF_EMPTY}
+       ${FAIL_IF_BAD_MACHO} main
+
+       ${CC} ${CCFLAGS} main.c -o main -flat_namespace -Wl,-U,_foo
+       nm -m main | grep _foo | grep "dynamically looked up" | ${FAIL_IF_STDIN}
+       ${PASS_IFF_GOOD_MACHO} main
+
+
+clean:
+       rm  main
diff --git a/unit-tests/test-cases/undefined-dynamic-lookup/main.c b/unit-tests/test-cases/undefined-dynamic-lookup/main.c
new file mode 100644 (file)
index 0000000..5de972f
--- /dev/null
@@ -0,0 +1,32 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2007 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>
+
+extern void foo();
+
+int main()
+{
+       foo();
+       return 0;
+}
diff --git a/unit-tests/test-cases/weak-def-ordinal/Makefile b/unit-tests/test-cases/weak-def-ordinal/Makefile
new file mode 100644 (file)
index 0000000..222a82d
--- /dev/null
@@ -0,0 +1,50 @@
+##
+# Copyright (c) 2007 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
+
+
+#
+#  libfoo.dylib has weak defintiion of _foo
+#  libbar.dylib has strong defintiion of _foo
+#
+# Tests that if you link against libfoo.dylib and libbar.dylib 
+# that the two-level-namespace ordinal is set to the non-weak definition
+#
+#<rdar://problem/5137732> ld should keep looking when it finds a weak definition in a dylib#
+#
+
+run: all
+
+all: 
+       ${CC} ${CCFLAGS} foo.c -dynamiclib -o libfoo.dylib
+       ${FAIL_IF_BAD_MACHO} libfoo.dylib
+       ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib
+       ${FAIL_IF_BAD_MACHO} libbar.dylib
+       ${CC} ${CCFLAGS} main.c -o main libfoo.dylib libbar.dylib
+       nm -m main | grep _aaa | grep libbar | ${FAIL_IF_EMPTY}
+       nm -m main | grep _bbb | grep libfoo | ${FAIL_IF_EMPTY}
+       ${PASS_IFF_GOOD_MACHO} main
+       
+clean:
+       rm libfoo.dylib  libbar.dylib main
diff --git a/unit-tests/test-cases/weak-def-ordinal/bar.c b/unit-tests/test-cases/weak-def-ordinal/bar.c
new file mode 100644 (file)
index 0000000..ae61731
--- /dev/null
@@ -0,0 +1,6 @@
+
+int aaa() 
+{
+       return 1;
+}
+
diff --git a/unit-tests/test-cases/weak-def-ordinal/foo.c b/unit-tests/test-cases/weak-def-ordinal/foo.c
new file mode 100644 (file)
index 0000000..d371654
--- /dev/null
@@ -0,0 +1,11 @@
+
+int __attribute__((weak)) aaa()
+{
+       return 0;
+}
+
+int __attribute__((weak)) bbb()
+{
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/weak-def-ordinal/main.c b/unit-tests/test-cases/weak-def-ordinal/main.c
new file mode 100644 (file)
index 0000000..74726fb
--- /dev/null
@@ -0,0 +1,35 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+extern void aaa();
+extern void bbb();
+
+int main()
+{
+       aaa();
+       bbb();
+       return 0;
+}
+
index 69ff397b4aae81e7e884852047c8d95c53877af4..d1fa1f3f9f0ba737cb9d6f11acaff057df039fa2 100644 (file)
@@ -32,6 +32,8 @@ run: all
 
 all:   
        ${CC} ${CCFLAGS} -dynamiclib -single_module foo.c -o libfoo-${ARCH}.dylib 
+       ${FAIL_IF_BAD_MACHO} libfoo-${ARCH}.dylib
+
        ${CC} ${CCFLAGS} -mmacosx-version-min=10.4 main.c -o main-${ARCH} libfoo-${ARCH}.dylib 
        nm -m main-${ARCH} | grep _func1 | grep -v weak    >/dev/null
        nm -m main-${ARCH} | grep _func2 | grep    weak    >/dev/null
@@ -41,6 +43,9 @@ all:
        nm -m main-${ARCH} | grep _data2 | grep    weak    >/dev/null
        nm -m main-${ARCH} | grep _data3 | grep -v weak    >/dev/null
        nm -m main-${ARCH} | grep _data4 | grep    weak    >/dev/null
+       otool -rv main-${ARCH} | grep _data6 > /dev/null
+       ${FAIL_IF_BAD_MACHO} main-${ARCH}
+
        ${CC} ${CCFLAGS} -mmacosx-version-min=10.4 main.c -dynamiclib -o main-${ARCH}.dylib libfoo-${ARCH}.dylib 
        nm -m main-${ARCH}.dylib | grep _func1 | grep -v weak    >/dev/null
        nm -m main-${ARCH}.dylib | grep _func2 | grep    weak    >/dev/null
@@ -50,7 +55,8 @@ all:
        nm -m main-${ARCH}.dylib | grep _data2 | grep    weak    >/dev/null
        nm -m main-${ARCH}.dylib | grep _data3 | grep -v weak    >/dev/null
        nm -m main-${ARCH}.dylib | grep _data4 | grep    weak    >/dev/null
+       otool -rv main-${ARCH}.dylib | grep _data6 > /dev/null
        ${PASS_IFF_GOOD_MACHO} main-${ARCH}.dylib
        
 clean:
-       rm -rf libfoo-${ARCH}.dylib  main-${ARCH}  main-${ARCH}.dylib
+       rm -rf *.dylib main-*
diff --git a/unit-tests/test-cases/weak_import2/Makefile.newtest b/unit-tests/test-cases/weak_import2/Makefile.newtest
new file mode 100644 (file)
index 0000000..5e51b89
--- /dev/null
@@ -0,0 +1,58 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# Test the weak_import attribute works
+#
+
+
+run: all
+
+all:   
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c foo.c -o foo-${ARCH}.o
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -c foo1.c -o foo1-${ARCH}.o
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -dynamiclib foo-${ARCH}.o foo1-${ARCH}.o -o libfoo-${ARCH}.dylib 
+       ${PASS_IFF_ERROR} ${CC} ${CCFLAGS} -mmacosx-version-min=10.4 main.c -o main-${ARCH} libfoo-${ARCH}.dylib 
+       nm -m main-${ARCH} | grep _func1 | grep -v weak    >/dev/null
+       nm -m main-${ARCH} | grep _func2 | grep    weak    >/dev/null
+       nm -m main-${ARCH} | grep _func3 | grep -v weak    >/dev/null 
+       nm -m main-${ARCH} | grep _func4 | grep    weak    >/dev/null
+       nm -m main-${ARCH} | grep _data1 | grep -v weak    >/dev/null
+       nm -m main-${ARCH} | grep _data2 | grep    weak    >/dev/null
+       nm -m main-${ARCH} | grep _data3 | grep -v weak    >/dev/null
+       nm -m main-${ARCH} | grep _data4 | grep    weak    >/dev/null
+       ${FAIL_IF_ERROR} ${CC} ${CCFLAGS} -mmacosx-version-min=10.4 main.c -dynamiclib -o main-${ARCH}.dylib libfoo-${ARCH}.dylib 
+       nm -m main-${ARCH}.dylib | grep _func1 | grep -v weak    >/dev/null
+       nm -m main-${ARCH}.dylib | grep _func2 | grep    weak    >/dev/null
+       nm -m main-${ARCH}.dylib | grep _func3 | grep -v weak    >/dev/null 
+       nm -m main-${ARCH}.dylib | grep _func4 | grep    weak    >/dev/null
+       nm -m main-${ARCH}.dylib | grep _data1 | grep -v weak    >/dev/null
+       nm -m main-${ARCH}.dylib | grep _data2 | grep    weak    >/dev/null
+       nm -m main-${ARCH}.dylib | grep _data3 | grep -v weak    >/dev/null
+       nm -m main-${ARCH}.dylib | grep _data4 | grep    weak    >/dev/null
+       ${PASS_IFF_GOOD_MACHO} main-${ARCH}.dylib
+       
+clean:
+       rm -rf *.dylib main-* *.o
diff --git a/unit-tests/test-cases/weak_import2/comment.txt b/unit-tests/test-cases/weak_import2/comment.txt
new file mode 100644 (file)
index 0000000..5be42d8
--- /dev/null
@@ -0,0 +1 @@
+Test the weak_import attribute works
diff --git a/unit-tests/test-cases/weak_import2/foo.c b/unit-tests/test-cases/weak_import2/foo.c
new file mode 100644 (file)
index 0000000..900b052
--- /dev/null
@@ -0,0 +1,17 @@
+
+
+#include "foo.h"
+
+void func1() {}
+void func2() {}
+void func3() {}
+void func4() {}
+
+
+int data1 = 0;
+int data2 = 0; // weak_import initialized
+int data3;
+int data4;             // weak_import uninitialized
+int data5 = 0;
+int data6 = 0; // weak_import 
+
diff --git a/unit-tests/test-cases/weak_import2/foo.h b/unit-tests/test-cases/weak_import2/foo.h
new file mode 100644 (file)
index 0000000..f455515
--- /dev/null
@@ -0,0 +1,16 @@
+
+
+extern void func1();
+extern void func2() __attribute__((weak_import));
+extern void func3();
+extern void func4() __attribute__((weak_import));
+
+extern int data1;
+extern int data2 __attribute__((weak_import));
+extern int data3;
+extern int data4 __attribute__((weak_import));
+extern int data5;
+extern int data6 __attribute__((weak_import));
+
+
+
diff --git a/unit-tests/test-cases/weak_import2/foo1.c b/unit-tests/test-cases/weak_import2/foo1.c
new file mode 100644 (file)
index 0000000..4580a87
--- /dev/null
@@ -0,0 +1,10 @@
+
+
+void func2() {}
+void func4() {}
+
+
+int data2 = 0; // foo.c also has weak_import initialized
+int data4;             // foo.c also has weak_import uninitialized
+int data6 = 0; // foo.c also has weak_import 
+
diff --git a/unit-tests/test-cases/weak_import2/main.c b/unit-tests/test-cases/weak_import2/main.c
new file mode 100644 (file)
index 0000000..3266aed
--- /dev/null
@@ -0,0 +1,20 @@
+
+#include "foo.h"
+
+
+int* pdata5 = &data5;
+int* pdata6 = &data6;
+
+
+int main (void)
+{
+       // make non-lazy reference to func3 and func4
+       if ( &func3 == &func4 ) {
+               // make lazy reference to func3 and func4
+               func1();
+               func2();
+       }
+   
+   return data1 + data2 + data3 + data4;
+}
+
diff --git a/unit-tests/test-cases/weak_import3/Makefile b/unit-tests/test-cases/weak_import3/Makefile
new file mode 100644 (file)
index 0000000..98a2779
--- /dev/null
@@ -0,0 +1,43 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# Test the weak_import attribute works
+#
+
+
+run: all
+
+all:   
+       ${CC} ${CCFLAGS} -c foo.c -o foo-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} foo-${ARCH}.o
+
+       ${CC} ${CCFLAGS} -c foo1.c -o foo1-${ARCH}.o
+       ${FAIL_IF_BAD_OBJ} foo1-${ARCH}.o
+
+       ${PASS_IFF_ERROR} ${CC} ${CCFLAGS} -dynamiclib foo-${ARCH}.o foo1-${ARCH}.o -o libfoo-${ARCH}.dylib 2>/dev/null
+
+clean:
+       rm -rf *.o *.dylib main-*
diff --git a/unit-tests/test-cases/weak_import3/comment.txt b/unit-tests/test-cases/weak_import3/comment.txt
new file mode 100644 (file)
index 0000000..5be42d8
--- /dev/null
@@ -0,0 +1 @@
+Test the weak_import attribute works
diff --git a/unit-tests/test-cases/weak_import3/foo.c b/unit-tests/test-cases/weak_import3/foo.c
new file mode 100644 (file)
index 0000000..900b052
--- /dev/null
@@ -0,0 +1,17 @@
+
+
+#include "foo.h"
+
+void func1() {}
+void func2() {}
+void func3() {}
+void func4() {}
+
+
+int data1 = 0;
+int data2 = 0; // weak_import initialized
+int data3;
+int data4;             // weak_import uninitialized
+int data5 = 0;
+int data6 = 0; // weak_import 
+
diff --git a/unit-tests/test-cases/weak_import3/foo.h b/unit-tests/test-cases/weak_import3/foo.h
new file mode 100644 (file)
index 0000000..f455515
--- /dev/null
@@ -0,0 +1,16 @@
+
+
+extern void func1();
+extern void func2() __attribute__((weak_import));
+extern void func3();
+extern void func4() __attribute__((weak_import));
+
+extern int data1;
+extern int data2 __attribute__((weak_import));
+extern int data3;
+extern int data4 __attribute__((weak_import));
+extern int data5;
+extern int data6 __attribute__((weak_import));
+
+
+
diff --git a/unit-tests/test-cases/weak_import3/foo1.c b/unit-tests/test-cases/weak_import3/foo1.c
new file mode 100644 (file)
index 0000000..392a5b7
--- /dev/null
@@ -0,0 +1,4 @@
+#include "foo.h"
+
+int data4;             // foo.c also has weak_import uninitialized
+
diff --git a/unit-tests/test-cases/weak_import3/main.c b/unit-tests/test-cases/weak_import3/main.c
new file mode 100644 (file)
index 0000000..3266aed
--- /dev/null
@@ -0,0 +1,20 @@
+
+#include "foo.h"
+
+
+int* pdata5 = &data5;
+int* pdata6 = &data6;
+
+
+int main (void)
+{
+       // make non-lazy reference to func3 and func4
+       if ( &func3 == &func4 ) {
+               // make lazy reference to func3 and func4
+               func1();
+               func2();
+       }
+   
+   return data1 + data2 + data3 + data4;
+}
+
index a5f2f12f97ed6959203a95a080a0fb599ab7c889..d6c0639003195ebe31ecc8b0dcf6df24ef128d1f 100644 (file)
@@ -35,6 +35,4 @@ all:
        ${PASS_IFF_GOOD_MACHO} test-${ARCH}
 
 clean:
-       rm  test-${ARCH}
-       
-
+       rm -rf test-*
diff --git a/unit-tests/test-cases/zero-fill2/Makefile b/unit-tests/test-cases/zero-fill2/Makefile
new file mode 100644 (file)
index 0000000..433078b
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a program with a large zero-fill section
+#
+
+run: all
+
+all:
+       BOOST=1; \
+       [ X"${ARCH}" = Xppc64 -o X"${ARCH}" = Xx86_64 ] && BOOST=100L; \
+       ${CC} ${CCFLAGS} -DBOOST=$$BOOST test.c -mmacosx-version-min=10.4 -o test-${ARCH} -L/Developer/SDKs/MacOSX10.4u.sdk/usr/lib -L/Developer/SDKs/MacOSX10.4u.sdk/usr/lib/system
+
+       ${PASS_IFF_GOOD_MACHO} test-${ARCH}
+
+clean:
+       rm -rf test-*
diff --git a/unit-tests/test-cases/zero-fill2/comment.txt b/unit-tests/test-cases/zero-fill2/comment.txt
new file mode 100644 (file)
index 0000000..a1710c1
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a program with a large zero-fill section
diff --git a/unit-tests/test-cases/zero-fill2/test.c b/unit-tests/test-cases/zero-fill2/test.c
new file mode 100644 (file)
index 0000000..74144d0
--- /dev/null
@@ -0,0 +1,51 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+// if we used one big array, the linker would page align it
+// but we want to test a non-page align big chunk of zero-fill data
+int bigarray1[256];
+int bigarray2[2560];
+int bigarray3[25600];
+int bigarray4[256000];
+int bigarray5[2560000];
+int bigarray6[256000000*BOOST];
+static int staticbigarray1[256];
+static int staticbigarray2[2560];
+static int staticbigarray3[25600];
+static int staticbigarray4[256000];
+static int staticbigarray5[2560000];
+static int staticbigarray6[25600000*BOOST];
+
+int main()
+{
+       staticbigarray1[10] = 4;
+       staticbigarray2[10] = 4;
+       staticbigarray3[10] = 4;
+       staticbigarray4[10] = 4;
+       staticbigarray5[10] = 4;
+       staticbigarray6[10] = 4;
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/zero-fill3/Makefile b/unit-tests/test-cases/zero-fill3/Makefile
new file mode 100644 (file)
index 0000000..50399b7
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+# 
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+# 
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+# 
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# The point of this test is a sanity check that ld
+# can link a program with a large zero-fill section
+#
+
+run:   test-run-${ARCH}
+
+# i386 catches the problem in the assembler phase
+test-run-i386:
+       ${PASS_IFF} true
+
+test-run-ppc test-run-ppc64: test-${ARCH}
+
+test-run-x86_64 test-ppc64:
+       ${CC} ${CCFLAGS} -DSHRINK=1 test.c --save-temps -o test-${ARCH}
+       ${PASS_IFF_GOOD_MACHO} test-${ARCH}
+
+test-ppc:
+       ${PASS_IFF_ERROR} ${CC} ${CCFLAGS} -DSHRINK=4 test.c --save-temps -o test-${ARCH} 2>/dev/null
+
+clean:
+       rm -rf test-* *.o *.s *.i
diff --git a/unit-tests/test-cases/zero-fill3/comment.txt b/unit-tests/test-cases/zero-fill3/comment.txt
new file mode 100644 (file)
index 0000000..a1710c1
--- /dev/null
@@ -0,0 +1 @@
+The point of this test is a sanity check that ld can link a program with a large zero-fill section
diff --git a/unit-tests/test-cases/zero-fill3/test.c b/unit-tests/test-cases/zero-fill3/test.c
new file mode 100644 (file)
index 0000000..64ac72a
--- /dev/null
@@ -0,0 +1,63 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+// if we used one big array, the linker would page align it
+// but we want to test a non-page align big chunk of zero-fill data
+int bigarray1[256];
+int bigarray2[2560];
+int bigarray3[25600];
+int bigarray4[256000];
+int bigarray5[2560000];
+int bigarray7[16777216L+1];
+int bigarray8[2*16777216L+1];
+int bigarray9[4*16777216L+1];
+int bigarray10[8*16777216L+1];
+int bigarray11[16*16777216L+1];
+int bigarray99[2147483647U/SHRINK];
+static int staticbigarray1[256];
+static int staticbigarray2[2560];
+static int staticbigarray3[25600];
+static int staticbigarray4[256000];
+static int staticbigarray5[2560000];
+static int staticbigarray6[25600000];
+//static int staticbigarray99[2147483647U/SHRINK];
+
+int main()
+{
+       bigarray5[10] = 4;
+       bigarray7[10] = 4;
+       bigarray8[10] = 4;
+       bigarray9[10] = 4;
+       bigarray10[10] = 4;
+       bigarray11[10] = 4;
+       bigarray99[10] = 4;
+       staticbigarray1[10] = 4;
+       staticbigarray2[10] = 4;
+       staticbigarray3[10] = 4;
+       staticbigarray4[10] = 4;
+       staticbigarray5[10] = 4;
+       staticbigarray6[10] = 4;
+       return 0;
+}