From eaf282aaf65b222563e6b3db98e12d720fb161bf Mon Sep 17 00:00:00 2001
From: Apple <opensource@apple.com>
Date: Tue, 25 Aug 2015 17:19:19 +0000
Subject: [PATCH] ld64-253.3.tar.gz

---
 doc/man/man1/ld.1                             |   32 +-
 ld64.xcodeproj/project.pbxproj                |   36 +-
 src/abstraction/MachOFileAbstraction.hpp      |   43 +-
 src/create_configure                          |   22 +-
 src/ld/Bitcode.hpp                            |   87 ++
 src/ld/HeaderAndLoadCommands.hpp              |  126 +-
 src/ld/InputFiles.cpp                         |   59 +-
 src/ld/LinkEdit.hpp                           |  205 ++--
 src/ld/LinkEditClassic.hpp                    |   14 +-
 src/ld/Options.cpp                            |  808 ++++++++++---
 src/ld/Options.h                              |   95 +-
 src/ld/OutputFile.cpp                         |  354 +++++-
 src/ld/OutputFile.h                           |   20 +-
 src/ld/Resolver.cpp                           |  191 ++-
 src/ld/Resolver.h                             |    1 +
 src/ld/SymbolTable.cpp                        |    9 +
 src/ld/SymbolTable.h                          |    1 +
 src/ld/code-sign-blobs/memutils.h             |    7 +-
 src/ld/ld.cpp                                 |  130 +-
 src/ld/ld.hpp                                 |   56 +-
 src/ld/lto_file.hpp                           |  642 ----------
 src/ld/parsers/lto_file.cpp                   |  181 ++-
 src/ld/parsers/lto_file.h                     |    5 +
 src/ld/parsers/macho_dylib_file.cpp           |  270 +++--
 src/ld/parsers/macho_relocatable_file.cpp     |  366 +++++-
 src/ld/parsers/macho_relocatable_file.h       |   11 +-
 src/ld/parsers/opaque_section_file.cpp        |    3 +-
 src/ld/parsers/textstub_dylib_file.cpp        | 1072 +++++++++++++++++
 src/ld/parsers/textstub_dylib_file.hpp        |   43 +
 src/ld/passes/bitcode_bundle.cpp              |  809 +++++++++++++
 src/ld/passes/bitcode_bundle.h                |   43 +
 src/ld/passes/branch_island.cpp               |    5 +-
 src/ld/passes/branch_shim.cpp                 |    2 +
 src/ld/passes/dylibs.cpp                      |    1 +
 src/ld/passes/got.cpp                         |   25 +-
 src/ld/passes/huge.cpp                        |    2 +
 src/ld/passes/objc.cpp                        |   13 +-
 src/ld/passes/order.cpp                       |   14 +-
 src/ld/passes/stubs/stub_arm.hpp              |   30 +-
 src/ld/passes/stubs/stub_arm64.hpp            |   22 +-
 src/ld/passes/stubs/stubs.cpp                 |   13 +-
 src/ld/passes/tlvp.cpp                        |    7 +-
 src/other/ObjectDump.cpp                      |    4 +-
 src/other/dyldinfo.cpp                        |  344 ++++--
 unit-tests/include/common.makefile            |   13 +-
 .../dead_strip-live-if-ref-live/Makefile      |   48 +
 .../dead_strip-live-if-ref-live/main.c        |   29 +
 unit-tests/test-cases/tlv-basic/get.s         |  113 ++
 unit-tests/test-cases/tlv-basic/main.c        |   19 +-
 49 files changed, 5105 insertions(+), 1340 deletions(-)
 create mode 100644 src/ld/Bitcode.hpp
 delete mode 100644 src/ld/lto_file.hpp
 create mode 100644 src/ld/parsers/textstub_dylib_file.cpp
 create mode 100644 src/ld/parsers/textstub_dylib_file.hpp
 create mode 100644 src/ld/passes/bitcode_bundle.cpp
 create mode 100644 src/ld/passes/bitcode_bundle.h
 create mode 100644 unit-tests/test-cases/dead_strip-live-if-ref-live/Makefile
 create mode 100644 unit-tests/test-cases/dead_strip-live-if-ref-live/main.c

diff --git a/doc/man/man1/ld.1 b/doc/man/man1/ld.1
index df4b5a4..1c118b8 100644
--- a/doc/man/man1/ld.1
+++ b/doc/man/man1/ld.1
@@ -117,6 +117,10 @@ Produce a mach-o dylinker that has file type MH_DYLINKER.  Only used when buildi
 The default.  Implied by -dylib, -bundle, or -execute
 .It Fl static
 Produces a mach-o file that does not use the dyld.  Only used building the kernel. 
+.It Fl preload
+Produces a mach-o file in which the mach_header, load commands, and symbol table are
+not in any segment.  This output type is used for firmware or embedded development
+where the segments are copied out of the mach-o into ROM/Flash.
 .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
@@ -480,6 +484,7 @@ 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.
+See -exported_symbols_list for syntax and use of wildcards.
 .It Fl print_statistics
 Logs information about the amount of memory and time the linker used.
 .It Fl t
@@ -515,10 +520,31 @@ contains a list of non-global symbol names that should be remain in the output f
 symbol names will be removed from the output file's symbol table. See -exported_symbols_list for syntax and use
 of wildcards.
 .El
+.Ss Options for Bitcode build flow
+.Bl -tag
+.It Fl bitcode_bundle
+Generates an embedded bitcode bundle in the output binary. The bitcode bundle is embedded in __LLVM, __bundle section.
+This option requires all the object files, static libraries and user frameworks/dylibs contain bitcode.
+Note: not all the linker options are supported to use together with -bitcode_bundle.
+.It Fl bitcode_hide_symbol
+Specifies this option together with -bitcode_bundle to hide all non-exported symbols from output bitcode bundle.
+The hide symbol process might not be reversible. To obtain a reverse mapping file to recover all the symbols, use
+-bitcode_symbol_map option.
+.It Fl bitcode_symbol_map Ar path
+Specifies the output for bitcode symbol reverse mapping (.bcsymbolmap). If
+.Ar path
+is an existing directory, UUID.bcsymbolmap will be written to that directory.
+Otherwise, the reverse map will be written to a file at
+.Ar path .
+.El
 .Ss Rarely used Options
 .Bl -tag
 .It Fl v
 Prints the version of the linker.
+.It Fl dirty_data_list Ar filename
+Specifies a file containing the names of data symbols likely to be dirtied.
+If the linker is creating a __DATA_DIRTY segment, those symbols will be moved
+to that segment.
 .It Fl move_to_rw_segment Ar segment_name Ar filename
 Moves data symbols to another segment.  The command line option specifies the
 target segment name and a path to a file containing a list of symbols to move.
@@ -738,6 +764,10 @@ info in the temporary object file.
 During development, this option can be used to space out all global variables so each is on a separate page. 
 This is useful when analyzing dirty and resident pages.  The information can then be used to create an 
 order file  to cluster commonly used/dirty globals onto the same page(s).
+.It Fl not_for_dyld_shared_cache
+Normally, the linker will add extra info to dylibs with -install_name starting with /usr/lib or
+/System/Library/ that allows the dylib to be placed into the dyld shared cache.  Adding this option
+tells the linker to not add that extra info.
 .El
 .Ss Obsolete Options
 .Bl -tag
@@ -749,8 +779,6 @@ Object files (MH_OBJECT) with a LINKEDIT segment are no longer supported. This o
 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. 
 .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
diff --git a/ld64.xcodeproj/project.pbxproj b/ld64.xcodeproj/project.pbxproj
index b4d1749..1c5e622 100644
--- a/ld64.xcodeproj/project.pbxproj
+++ b/ld64.xcodeproj/project.pbxproj
@@ -43,6 +43,7 @@
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
+		B028FCF21A9E7C3F00E3584B /* bitcode_bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B028FCF11A9E7C3F00E3584B /* bitcode_bundle.cpp */; };
 		B3B672421406D42800A376BB /* Snapshot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B3B672411406D42800A376BB /* Snapshot.cpp */; };
 		F9023C4E06D5A272001BBF46 /* ld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9023C3F06D5A254001BBF46 /* ld.cpp */; };
 		F933E3D9092E855B0083EAC8 /* ObjectDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F971EED706D5AD240041D381 /* ObjectDump.cpp */; };
@@ -82,6 +83,7 @@
 		F9EA7584097882F3008B4F1D /* debugline.c in Sources */ = {isa = PBXBuildFile; fileRef = F9EA7582097882F3008B4F1D /* debugline.c */; };
 		F9EA75BC09788857008B4F1D /* debugline.c in Sources */ = {isa = PBXBuildFile; fileRef = F9EA7582097882F3008B4F1D /* debugline.c */; };
 		F9EC78060A2F8674002A3E39 /* rebase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9EC78050A2F8674002A3E39 /* rebase.cpp */; };
+		FA95D6141AB25CF400395811 /* textstub_dylib_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA95D6121AB25CF400395811 /* textstub_dylib_file.cpp */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXBuildRule section */
@@ -241,6 +243,9 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+		B028FCF01A9E7B4A00E3584B /* bitcode_bundle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bitcode_bundle.h; sourceTree = "<group>"; };
+		B028FCF11A9E7C3F00E3584B /* bitcode_bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bitcode_bundle.cpp; sourceTree = "<group>"; };
+		B091FB641ABA3AFB00CC8193 /* Bitcode.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Bitcode.hpp; path = src/ld/Bitcode.hpp; sourceTree = "<group>"; };
 		B3B672411406D42800A376BB /* Snapshot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Snapshot.cpp; path = src/ld/Snapshot.cpp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
 		B3B672441406D44300A376BB /* Snapshot.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = Snapshot.h; path = src/ld/Snapshot.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
 		B3C7A09914295B9C005FC714 /* compile_stubs */ = {isa = PBXFileReference; lastKnownFileType = text.script.csh; path = compile_stubs; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
@@ -333,6 +338,8 @@
 		F9EA7583097882F3008B4F1D /* debugline.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = debugline.h; path = src/ld/debugline.h; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
 		F9EC77EE0A2F85F6002A3E39 /* rebase */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rebase; sourceTree = BUILT_PRODUCTS_DIR; };
 		F9EC78050A2F8674002A3E39 /* rebase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = rebase.cpp; path = src/other/rebase.cpp; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+		FA95D6121AB25CF400395811 /* textstub_dylib_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = textstub_dylib_file.cpp; sourceTree = "<group>"; usesTabs = 1; };
+		FA95D6131AB25CF400395811 /* textstub_dylib_file.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = textstub_dylib_file.hpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -421,6 +428,8 @@
 		F9AA650B1051BD2B003E3539 /* passes */ = {
 			isa = PBXGroup;
 			children = (
+				B028FCF11A9E7C3F00E3584B /* bitcode_bundle.cpp */,
+				B028FCF01A9E7B4A00E3584B /* bitcode_bundle.h */,
 				F984A38010BB4B0D009E9878 /* branch_island.cpp */,
 				F984A38110BB4B0D009E9878 /* branch_island.h */,
 				F9AA44DA1294885F00CB8390 /* branch_shim.cpp */,
@@ -466,6 +475,8 @@
 		F9AA65861051E750003E3539 /* parsers */ = {
 			isa = PBXGroup;
 			children = (
+				FA95D6121AB25CF400395811 /* textstub_dylib_file.cpp */,
+				FA95D6131AB25CF400395811 /* textstub_dylib_file.hpp */,
 				F91B7B0218987D5F0099486F /* libunwind */,
 				F9AA6784105700C2003E3539 /* opaque_section_file.cpp */,
 				F9AA6785105700C2003E3539 /* opaque_section_file.h */,
@@ -525,6 +536,7 @@
 				F9AA650B1051BD2B003E3539 /* passes */,
 				F9AA65861051E750003E3539 /* parsers */,
 				F933DC37092A82480083EAC8 /* Architectures.hpp */,
+				B091FB641ABA3AFB00CC8193 /* Bitcode.hpp */,
 				F9EA7582097882F3008B4F1D /* debugline.c */,
 				F9EA7583097882F3008B4F1D /* debugline.h */,
 				B3B672411406D42800A376BB /* Snapshot.cpp */,
@@ -772,7 +784,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 1;
 			shellPath = /bin/sh;
-			shellScript = "\nif [ -n \"${DT_TOOLCHAIN_DIR}\" ]\nthen\n\tmkdir -p  \"${DSTROOT}/${DT_TOOLCHAIN_DIR}\"\n\tmv ${DSTROOT}/usr \"${DSTROOT}/${DT_TOOLCHAIN_DIR}\"\nelse\n\tif [ -n \"${RC_PURPLE}\" ]\n\tthen\n\t\tmkdir -p  ${DSTROOT}/Developer/Platforms/iPhoneOS.platform/Developer/\n\t\tmv ${DSTROOT}/usr ${DSTROOT}/Developer/Platforms/iPhoneOS.platform/Developer\n\telse\n\t\tmkdir -p  ${DSTROOT}/Developer/usr/bin\n\t\tcp ${DSTROOT}/usr/bin/ld  ${DSTROOT}/Developer/usr/bin\n\tfi\nfi\n\n";
+			shellScript = "\nif [ -n \"${DT_TOOLCHAIN_DIR}\" ]\nthen\n\tmkdir -p  \"${DSTROOT}/${DT_VARIANT}/${DT_TOOLCHAIN_DIR}\"\n\tmv ${DSTROOT}/usr \"${DSTROOT}/${DT_VARIANT}/${DT_TOOLCHAIN_DIR}\"\nelse\n\tif [ -n \"${RC_PURPLE}\" ]\n\tthen\n\t\tmkdir -p  ${DSTROOT}/Developer/Platforms/iPhoneOS.platform/Developer/\n\t\tmv ${DSTROOT}/usr ${DSTROOT}/Developer/Platforms/iPhoneOS.platform/Developer\n\telse\n\t\tmkdir -p  ${DSTROOT}/Developer/usr/bin\n\t\tcp ${DSTROOT}/usr/bin/ld  ${DSTROOT}/Developer/usr/bin\n\tfi\nfi\n\n";
 			showEnvVarsInLog = 0;
 		};
 		F9CCF765144CE244007CB524 /* make configure.h */ = {
@@ -894,6 +906,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				FA95D6141AB25CF400395811 /* textstub_dylib_file.cpp in Sources */,
 				F9C0D4BD06DD28D2001C7193 /* Options.cpp in Sources */,
 				F9023C4E06D5A272001BBF46 /* ld.cpp in Sources */,
 				F9AA65891051E750003E3539 /* macho_relocatable_file.cpp in Sources */,
@@ -918,6 +931,7 @@
 				F93CB248116E69EB003233B8 /* tlvp.cpp in Sources */,
 				F9AA44DC1294885F00CB8390 /* branch_shim.cpp in Sources */,
 				B3B672421406D42800A376BB /* Snapshot.cpp in Sources */,
+				B028FCF21A9E7C3F00E3584B /* bitcode_bundle.cpp in Sources */,
 				F9CC24191461FB4300A92174 /* blob.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -1037,6 +1051,8 @@
 		F933D91C09291AC90083EAC8 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
 				CLANG_CXX_LIBRARY = "libc++";
 				COPY_PHASE_STRIP = NO;
 				CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
@@ -1080,13 +1096,16 @@
 				LD_RUNPATH_SEARCH_PATHS = "@executable_path/../lib/";
 				LINKER_DISPLAYS_MANGLED_NAMES = NO;
 				MACOSX_DEPLOYMENT_TARGET = "";
+				ONLY_ACTIVE_ARCH = NO;
 				OTHER_CPLUSPLUSFLAGS = (
 					"-stdlib=libc++",
 					"$(OTHER_CPLUSPLUSFLAGS)",
 				);
 				OTHER_LDFLAGS = (
 					"-stdlib=libc++",
+					"-lxar",
 					"-Wl,-lazy_library,$(DT_TOOLCHAIN_DIR)/usr/lib/libLTO.dylib",
+					"@$(DERIVED_FILE_DIR)/linkExtras",
 					"-Wl,-exported_symbol,__mh_execute_header",
 				);
 				PREBINDING = NO;
@@ -1100,6 +1119,8 @@
 		F933D91D09291AC90083EAC8 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
 				CLANG_CXX_LIBRARY = "libc++";
 				COPY_PHASE_STRIP = NO;
 				CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
@@ -1151,7 +1172,9 @@
 				);
 				OTHER_LDFLAGS = (
 					"-stdlib=libc++",
+					"-lxar",
 					"-Wl,-lazy_library,$(DT_TOOLCHAIN_DIR)/usr/lib/libLTO.dylib",
+					"@$(DERIVED_FILE_DIR)/linkExtras",
 					"-Wl,-exported_symbol,__mh_execute_header",
 				);
 				PREBINDING = NO;
@@ -1168,6 +1191,7 @@
 		F933D92009291AC90083EAC8 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 				CLANG_CXX_LIBRARY = "libc++";
 				COPY_PHASE_STRIP = NO;
 				DEBUG_INFORMATION_FORMAT = dwarf;
@@ -1186,8 +1210,10 @@
 				HEADER_SEARCH_PATHS = (
 					"$(SRCROOT)/src/ld",
 					"$(DEVELOPER_DIR)/usr/local/include",
+					"$(DT_TOOLCHAIN_DIR)/usr/local/include",
 				);
 				INSTALL_PATH = "$(HOME)/bin";
+				ONLY_ACTIVE_ARCH = NO;
 				OTHER_CPLUSPLUSFLAGS = (
 					"-stdlib=libc++",
 					"$(OTHER_CFLAGS)",
@@ -1211,6 +1237,7 @@
 		F933D92109291AC90083EAC8 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 				CLANG_CXX_LIBRARY = "libc++";
 				COPY_PHASE_STRIP = YES;
 				DEBUG_INFORMATION_FORMAT = dwarf;
@@ -1221,6 +1248,7 @@
 				HEADER_SEARCH_PATHS = (
 					"$(SRCROOT)/src/ld",
 					"$(DEVELOPER_DIR)/usr/local/include",
+					"$(DT_TOOLCHAIN_DIR)/usr/local/include",
 				);
 				INSTALL_PATH = "$(HOME)/bin";
 				OTHER_CPLUSPLUSFLAGS = (
@@ -1299,6 +1327,8 @@
 		F9849FFA10B5DE8E009E9878 /* Release-assert */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
 				CLANG_CXX_LIBRARY = "libc++";
 				COPY_PHASE_STRIP = NO;
 				CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
@@ -1349,7 +1379,9 @@
 				);
 				OTHER_LDFLAGS = (
 					"-stdlib=libc++",
+					"-lxar",
 					"-Wl,-lazy_library,$(DT_TOOLCHAIN_DIR)/usr/lib/libLTO.dylib",
+					"@$(DERIVED_FILE_DIR)/linkExtras",
 					"-Wl,-exported_symbol,__mh_execute_header",
 				);
 				PREBINDING = NO;
@@ -1413,6 +1445,7 @@
 		F9849FFD10B5DE8E009E9878 /* Release-assert */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
 				CLANG_CXX_LIBRARY = "libc++";
 				COPY_PHASE_STRIP = YES;
 				DEBUG_INFORMATION_FORMAT = dwarf;
@@ -1424,6 +1457,7 @@
 				HEADER_SEARCH_PATHS = (
 					"$(SRCROOT)/src/ld",
 					"$(DEVELOPER_DIR)/usr/local/include",
+					"$(DT_TOOLCHAIN_DIR)/usr/local/include",
 				);
 				INSTALL_PATH = "$(HOME)/bin";
 				OTHER_CPLUSPLUSFLAGS = (
diff --git a/src/abstraction/MachOFileAbstraction.hpp b/src/abstraction/MachOFileAbstraction.hpp
index ae61d7c..cfedc81 100644
--- a/src/abstraction/MachOFileAbstraction.hpp
+++ b/src/abstraction/MachOFileAbstraction.hpp
@@ -426,11 +426,18 @@
 	#define LOH_ARM64_ADRP_LDR_GOT			8
 #endif
 
+#ifndef LC_VERSION_MIN_TVOS
+	#define LC_VERSION_MIN_TVOS			0x2F
+#endif
+
+#ifndef LC_VERSION_MIN_WATCHOS
+	#define LC_VERSION_MIN_WATCHOS		0x30
+#endif
+
 #ifndef EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
 	#define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE			0x02
 #endif
 
-
 #ifndef CPU_SUBTYPE_ARM_V8
 	#define CPU_SUBTYPE_ARM_V8		((cpu_subtype_t) 13) 
 #endif
@@ -472,6 +479,40 @@
  
 #define UNWIND_ARM_DWARF_SECTION_OFFSET               0x00FFFFFF
 
+
+// ( <opcode> (delta-uleb128)+ <zero> )+ <zero>
+#define DYLD_CACHE_ADJ_V1_POINTER_32		0x01
+#define DYLD_CACHE_ADJ_V1_POINTER_64		0x02
+#define DYLD_CACHE_ADJ_V1_ADRP				0x03
+#define DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT	0x10 // thru 0x1F
+#define DYLD_CACHE_ADJ_V1_ARM_MOVT			0x20 // thru 0x2F
+
+
+// Whole		 :== <new-marker> <count> FromToSection+
+// FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+
+// ToOffset		 :== <to-sect-offset-delta> <count> FromOffset+
+// FromOffset	 :== <kind> <count> <from-sect-offset-delta>
+#define DYLD_CACHE_ADJ_V2_FORMAT				0x7F
+
+#define DYLD_CACHE_ADJ_V2_POINTER_32			0x01
+#define DYLD_CACHE_ADJ_V2_POINTER_64			0x02
+#define DYLD_CACHE_ADJ_V2_DELTA_32			    0x03
+#define DYLD_CACHE_ADJ_V2_DELTA_64			    0x04
+#define DYLD_CACHE_ADJ_V2_ARM64_ADRP			0x05
+#define DYLD_CACHE_ADJ_V2_ARM64_OFF12			0x06
+#define DYLD_CACHE_ADJ_V2_ARM64_BR26			0x07
+#define DYLD_CACHE_ADJ_V2_ARM_MOVW_MOVT			0x08
+#define DYLD_CACHE_ADJ_V2_ARM_BR24				0x09
+#define DYLD_CACHE_ADJ_V2_THUMB_MOVW_MOVT		0x0A
+#define DYLD_CACHE_ADJ_V2_THUMB_BR22			0x0B
+#define DYLD_CACHE_ADJ_V2_IMAGE_OFF_32			0x0C
+
+
+
+// kind target-address fixup-addr [adj] 
+
+
+
 struct ArchInfo {
 	const char*			archName;
 	cpu_type_t			cpuType;
diff --git a/src/create_configure b/src/create_configure
index f991231..9ce654d 100755
--- a/src/create_configure
+++ b/src/create_configure
@@ -25,8 +25,24 @@ do
 	fi
 done
 
-echo "#define ALL_SUPPORTED_ARCHS  \"${RC_SUPPORTED_ARCHS}\"" >> ${DERIVED_FILE_DIR}/configure.h
-
+if [ -n "${RC_HIDE_TIDE}" ]; then
+	echo "#define ALL_SUPPORTED_ARCHS  \"${RC_SUPPORTED_ARCHS}\"" >> ${DERIVED_FILE_DIR}/configure.h
+	echo "#define SUPPORT_APPLE_TV 0" >> ${DERIVED_FILE_DIR}/configure.h
+else
+	if [ -n "${DT_VARIANT}" -a "${DT_VARIANT}" != "PONDEROSA" ]; then
+		echo "#define ALL_SUPPORTED_ARCHS  \"${RC_SUPPORTED_ARCHS}\"" >> ${DERIVED_FILE_DIR}/configure.h
+		echo "#define SUPPORT_APPLE_TV 0" >> ${DERIVED_FILE_DIR}/configure.h
+	else
+		echo "#define ALL_SUPPORTED_ARCHS  \"${RC_SUPPORTED_ARCHS} (tvOS)\"" >> ${DERIVED_FILE_DIR}/configure.h
+		echo "#define SUPPORT_APPLE_TV 1" >> ${DERIVED_FILE_DIR}/configure.h
+	fi
+fi
 
- 
+if [ -f "${DT_TOOLCHAIN_DIR}/usr/lib/libswiftDemangle.dylib" ]; then
+	echo "-Wl,-lazy_library,${DT_TOOLCHAIN_DIR}/usr/lib/libswiftDemangle.dylib" >  ${DERIVED_FILE_DIR}/linkExtras
+	echo "#define DEMANGLE_SWIFT 1" >> ${DERIVED_FILE_DIR}/configure.h
+else
+	echo "" > ${DERIVED_FILE_DIR}/linkExtras
+fi
 
+echo "#define BITCODE_XAR_VERSION \"1.0\"" >> ${DERIVED_FILE_DIR}/configure.h
diff --git a/src/ld/Bitcode.hpp b/src/ld/Bitcode.hpp
new file mode 100644
index 0000000..68822d2
--- /dev/null
+++ b/src/ld/Bitcode.hpp
@@ -0,0 +1,87 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2005-2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __BITCODE_HPP__
+#define __BITCODE_HPP__
+
+#include <unistd.h>
+
+namespace ld {
+
+class Bitcode {
+public:
+    Bitcode(const uint8_t* content, uint32_t size) : _content(content), _size(size) { }
+
+    virtual bool isMarker() const                               { return _size <= 1 ; }
+    virtual const uint8_t* getContent() const                   { return _content; }
+    virtual uint32_t getSize() const                            { return _size; }
+private:
+    const uint8_t* _content;
+    uint32_t _size;
+};
+
+class LLVMBitcode : public Bitcode {
+public:
+    LLVMBitcode(const uint8_t* content, uint32_t size, const uint8_t* cmd, uint32_t cmdSize) :
+        Bitcode(content, size), _cmdline(cmd), _cmdSize(cmdSize)    { }
+
+    virtual const uint8_t* getCmdline() const                   { return _cmdline; }
+    virtual uint32_t getCmdSize() const                         { return _cmdSize; }
+    virtual const char* getBitcodeName() const                  { return "llvm"; }
+private:
+    const uint8_t* _cmdline;
+    uint32_t _cmdSize;
+};
+
+class ClangBitcode : public LLVMBitcode {
+public:
+    ClangBitcode(const uint8_t* content, uint32_t size, const uint8_t* cmd, uint32_t cmdSize) :
+        LLVMBitcode(content, size, cmd, cmdSize)    { }
+    virtual const char* getBitcodeName() const override         { return "clang"; }
+};
+
+class SwiftBitcode : public LLVMBitcode {
+public:
+    SwiftBitcode(const uint8_t* content, uint32_t size, const uint8_t* cmd, uint32_t cmdSize) :
+        LLVMBitcode(content, size, cmd, cmdSize)    { }
+    virtual const char* getBitcodeName() const override         { return "swift"; }
+};
+
+class AsmBitcode : public Bitcode {
+public:
+    AsmBitcode(const uint8_t* content, uint32_t size) : Bitcode(content, size) { }
+
+    virtual bool isMarker() const override                      { return false; }
+};
+
+class BundleBitcode : public Bitcode {
+public:
+    BundleBitcode(const uint8_t* content, uint32_t size) :
+        Bitcode(content, size)  { }
+};
+
+}
+
+
+#endif /* defined(__BITCODE_HPP__) */
diff --git a/src/ld/HeaderAndLoadCommands.hpp b/src/ld/HeaderAndLoadCommands.hpp
index 3629af5..b47acff 100644
--- a/src/ld/HeaderAndLoadCommands.hpp
+++ b/src/ld/HeaderAndLoadCommands.hpp
@@ -49,6 +49,9 @@ public:
 
 	virtual void setUUID(const uint8_t digest[16]) = 0;
 	virtual void recopyUUIDCommand() = 0;
+	virtual const uint8_t* getUUID() const = 0;
+	virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd,
+									  uint64_t& sectOffset, uint64_t& sectEnd) const = 0;
 };
 
 template <typename A>
@@ -68,6 +71,9 @@ public:
 	// overrides of HeaderAndLoadCommandsAbtract
 	virtual void setUUID(const uint8_t digest[16])	{ memcpy(_uuid, digest, 16); }
 	virtual void recopyUUIDCommand();
+	virtual const uint8_t* getUUID() const                          { return &_uuid[0]; }
+	virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd,
+									  uint64_t& sectOffset, uint64_t& sectEnd) const;
 	
 private:
 	typedef typename A::P						P;
@@ -107,7 +113,6 @@ private:
 	uint8_t*					copySubUmbrellaLoadCommand(uint8_t* p, const char* name) const;
 	uint8_t*					copyFunctionStartsLoadCommand(uint8_t* p) const;
 	uint8_t*					copyDataInCodeLoadCommand(uint8_t* p) const;
-	uint8_t*					copyDependentDRLoadCommand(uint8_t* p) const;
 	uint8_t*					copyDyldEnvLoadCommand(uint8_t* p, const char* env) const;
 	uint8_t*					copyLinkerOptionsLoadCommand(uint8_t* p, const std::vector<const char*>&) const;
 	uint8_t*					copyOptimizationHintsLoadCommand(uint8_t* p) const;
@@ -137,7 +142,6 @@ private:
 	bool						_hasFunctionStartsLoadCommand;
 	bool						_hasDataInCodeLoadCommand;
 	bool						_hasSourceVersionLoadCommand;
-	bool						_hasDependentDRInfo;
 	bool						_hasOptimizationHints;
 	uint32_t					_dylibLoadCommmandsCount;
 	uint32_t					_allowableClientLoadCommmandsCount;
@@ -223,11 +227,12 @@ HeaderAndLoadCommandsAtom<A>::HeaderAndLoadCommandsAtom(const Options& opts, ld:
 	}
 	_hasRPathLoadCommands = (_options.rpaths().size() != 0);
 	_hasSubFrameworkLoadCommand = (_options.umbrellaName() != NULL);
-	_hasVersionLoadCommand = _options.addVersionLoadCommand();
+	_hasVersionLoadCommand = _options.addVersionLoadCommand() ||
+							 (!state.objectFileFoundWithNoVersion && (_options.outputKind() == Options::kObjectFile)
+							 && ((_options.platform() != Options::kPlatformUnknown) || (state.derivedPlatformLoadCommand != 0)) );
 	_hasFunctionStartsLoadCommand = _options.addFunctionStarts();
 	_hasDataInCodeLoadCommand = _options.addDataInCodeInfo();
 	_hasSourceVersionLoadCommand = _options.needsSourceVersionLoadCommand();
-	_hasDependentDRInfo = _options.needsDependentDRInfo();
 	_dylibLoadCommmandsCount = _writer.dylibCount();
 	_allowableClientLoadCommmandsCount = _options.allowableClients().size();
 	_dyldEnvironExrasCount = _options.dyldEnvironExtras().size();
@@ -326,6 +331,31 @@ unsigned int HeaderAndLoadCommandsAtom<A>::segmentCount() const
 	return count;
 }
 
+template <typename A>
+bool HeaderAndLoadCommandsAtom<A>::bitcodeBundleCommand(uint64_t &cmdOffset, uint64_t &cmdEnd,
+														uint64_t &sectOffset, uint64_t &sectEnd) const
+{
+	if ( _options.outputKind() == Options::kObjectFile ) {
+		return false;
+	}
+	cmdOffset = sizeof(macho_header<P>);
+	const char* lastSegName = "";
+	for (std::vector<ld::Internal::FinalSection*>::iterator it = _state.sections.begin(); it != _state.sections.end(); ++it) {
+		if ( strcmp(lastSegName, (*it)->segmentName()) != 0 ) {
+			lastSegName = (*it)->segmentName();
+			cmdOffset += sizeof(macho_segment_command<P>);
+		}
+		if ( strcmp((*it)->segmentName(), "__LLVM") == 0 && strcmp((*it)->sectionName(), "__bundle") == 0 ) {
+			sectOffset = (*it)->fileOffset;
+			sectEnd = (*(it + 1))->fileOffset;
+			cmdEnd = cmdOffset + sizeof(macho_section<P>);
+			return true;
+		}
+		if ( ! (*it)->isSectionHidden() )
+			cmdOffset += sizeof(macho_section<P>);
+	}
+	return false;
+}
 
 template <typename A>
 uint64_t HeaderAndLoadCommandsAtom<A>::size() const
@@ -427,9 +457,6 @@ uint64_t HeaderAndLoadCommandsAtom<A>::size() const
 		}
 	}
 	
-	if ( _hasDependentDRInfo ) 
-		sz += sizeof(macho_linkedit_data_command<P>);
-	
 	if ( _hasOptimizationHints )
 		sz += sizeof(macho_linkedit_data_command<P>);
 		
@@ -507,9 +534,6 @@ uint32_t HeaderAndLoadCommandsAtom<A>::commandsCount() const
 		}
 	}
 
-	if ( _hasDependentDRInfo ) 
-		++count;
-	
 	if ( _hasOptimizationHints )
 		++count;
 		
@@ -692,6 +716,7 @@ struct SegInfo {
 												SegInfo(const char* n, const Options&);
 	const char*									segName;
 	uint32_t									nonHiddenSectionCount;
+	uint32_t									nonSectCreateSections;
 	uint32_t									maxProt;
 	uint32_t									initProt;
 	std::vector<ld::Internal::FinalSection*>	sections;
@@ -699,7 +724,7 @@ struct SegInfo {
 
 
 SegInfo::SegInfo(const char* n, const Options& opts) 
-	: segName(n), nonHiddenSectionCount(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n)) 
+	: segName(n), nonHiddenSectionCount(0), nonSectCreateSections(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n))
 { 
 }
 
@@ -722,6 +747,8 @@ uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection*
 				return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
 			else if ( (strncmp(sect->sectionName(), "__objc_nlcatlist", 16) == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
 				return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
+			else if (  (_options.outputKind() == Options::kObjectFile) && !sect->atoms.empty() && sect->atoms.front()->dontDeadStripIfReferencesLive() )
+				return S_REGULAR | S_ATTR_LIVE_SUPPORT;
 			else
 				return S_REGULAR;
 		case ld::Section::typeCode:
@@ -841,6 +868,8 @@ uint32_t HeaderAndLoadCommandsAtom<A>::sectionFlags(ld::Internal::FinalSection*
 			return S_REGULAR;
 		case ld::Section::typeDebug:
 			return S_REGULAR | S_ATTR_DEBUG;
+		case ld::Section::typeSectCreate:
+			return S_REGULAR;
 	}
 	return S_REGULAR;
 }
@@ -885,6 +914,9 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p) const
 		}
 		if ( ! sect->isSectionHidden() ) 
 			segs.back().nonHiddenSectionCount++;
+		if ( sect->type() != ld::Section::typeSectCreate )
+			segs.back().nonSectCreateSections++;
+
 		segs.back().sections.push_back(sect);
 	}
 	// write out segment load commands for each section with trailing sections
@@ -921,7 +953,8 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p) const
 		segCmd->set_maxprot(si.maxProt);
 		segCmd->set_initprot(si.initProt);
 		segCmd->set_nsects(si.nonHiddenSectionCount);
-		segCmd->set_flags(0);
+		segCmd->set_flags(si.nonSectCreateSections ? 0 : SG_NORELOC); // FIXME, really should check all References
+
 		p += sizeof(macho_segment_command<P>);
 		macho_section<P>* msect = (macho_section<P>*)p;
 		for (std::vector<ld::Internal::FinalSection*>::iterator sit = si.sections.begin(); sit != si.sections.end(); ++sit) {
@@ -1104,20 +1137,40 @@ template <typename A>
 uint8_t* HeaderAndLoadCommandsAtom<A>::copyVersionLoadCommand(uint8_t* p) const
 {
 	macho_version_min_command<P>* cmd = (macho_version_min_command<P>*)p;
-	ld::MacVersionMin macVersion = _options.macosxVersionMin();
-	ld::IOSVersionMin iOSVersion = _options.iOSVersionMin();
-	assert( (macVersion != ld::macVersionUnset) || (iOSVersion != ld::iOSVersionUnset) );
-	if ( macVersion != ld::macVersionUnset ) {
-		cmd->set_cmd(LC_VERSION_MIN_MACOSX);
-		cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
-		cmd->set_version((uint32_t)macVersion);
-		cmd->set_sdk(_options.sdkVersion());
-	}
-	else {
-		cmd->set_cmd(LC_VERSION_MIN_IPHONEOS);
-		cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
-		cmd->set_version((uint32_t)iOSVersion);
-		cmd->set_sdk(_options.sdkVersion());
+	switch (_options.platform()) {
+		case Options::kPlatformUnknown:
+			assert(_state.derivedPlatformLoadCommand != 0 && "unknown platform");
+			cmd->set_cmd(_state.derivedPlatformLoadCommand);
+			cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+			cmd->set_version(_state.minOSVersion);
+			cmd->set_sdk(0);
+			break;
+		case Options::kPlatformOSX:
+			cmd->set_cmd(LC_VERSION_MIN_MACOSX);
+			cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+			cmd->set_version(_state.minOSVersion);
+			cmd->set_sdk(_options.sdkVersion());
+			break;
+		case Options::kPlatformiOS:
+			cmd->set_cmd(LC_VERSION_MIN_IPHONEOS);
+			cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+			cmd->set_version(_state.minOSVersion);
+			cmd->set_sdk(_options.sdkVersion());
+			break;
+		case Options::kPlatformWatchOS:
+			cmd->set_cmd(LC_VERSION_MIN_WATCHOS);
+			cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+			cmd->set_version(_state.minOSVersion);
+			cmd->set_sdk(_options.sdkVersion());
+			break;
+#if SUPPORT_APPLE_TV
+		case Options::kPlatform_tvOS:
+			cmd->set_cmd(LC_VERSION_MIN_TVOS);
+			cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+			cmd->set_version(_state.minOSVersion);
+			cmd->set_sdk(_options.sdkVersion());
+			break;
+#endif
 	}
 	return p + sizeof(macho_version_min_command<P>);
 }
@@ -1158,7 +1211,7 @@ uint8_t* HeaderAndLoadCommandsAtom<x86>::copyThreadsLoadCommand(uint8_t* p) cons
 template <>
 uint32_t HeaderAndLoadCommandsAtom<x86_64>::threadLoadCommandSize() const
 {
-	return this->alignedSize(16 + x86_THREAD_STATE64_COUNT * 4); 
+	return this->alignedSize(16 + 42*4);	// base size + x86_THREAD_STATE64_COUNT * 4
 }
 
 template <>
@@ -1169,8 +1222,8 @@ uint8_t* HeaderAndLoadCommandsAtom<x86_64>::copyThreadsLoadCommand(uint8_t* p) c
 	macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
 	cmd->set_cmd(LC_UNIXTHREAD);
 	cmd->set_cmdsize(threadLoadCommandSize());
-	cmd->set_flavor(x86_THREAD_STATE64);			
-	cmd->set_count(x86_THREAD_STATE64_COUNT);	
+	cmd->set_flavor(4);				// x86_THREAD_STATE64
+	cmd->set_count(42);				// x86_THREAD_STATE64_COUNT
 	cmd->set_thread_register(16, start);		// rip 
 	if ( _options.hasCustomStack() )
 		cmd->set_thread_register(7, _options.customStackAddr());	// r1
@@ -1411,18 +1464,6 @@ uint8_t* HeaderAndLoadCommandsAtom<A>::copyLinkerOptionsLoadCommand(uint8_t* p,
 }
 
 
-template <typename A>
-uint8_t* HeaderAndLoadCommandsAtom<A>::copyDependentDRLoadCommand(uint8_t* p) const
-{
-	macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
-	cmd->set_cmd(LC_DYLIB_CODE_SIGN_DRS);
-	cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
-	cmd->set_dataoff(_writer.dependentDRsSection->fileOffset);
-	cmd->set_datasize(_writer.dependentDRsSection->size);
-	return p + sizeof(macho_linkedit_data_command<P>);
-}
-
-
 
 template <typename A>
 uint8_t* HeaderAndLoadCommandsAtom<A>::copyOptimizationHintsLoadCommand(uint8_t* p) const
@@ -1546,9 +1587,6 @@ void HeaderAndLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 		}
 	}
 	
-	if ( _hasDependentDRInfo ) 
-		p = this->copyDependentDRLoadCommand(p);
- 
 	if ( _hasOptimizationHints )
 		p = this->copyOptimizationHintsLoadCommand(p);
  
diff --git a/src/ld/InputFiles.cpp b/src/ld/InputFiles.cpp
index 30c0875..9eadc2e 100644
--- a/src/ld/InputFiles.cpp
+++ b/src/ld/InputFiles.cpp
@@ -58,6 +58,7 @@
 #include "InputFiles.h"
 #include "macho_relocatable_file.h"
 #include "macho_dylib_file.h"
+#include "textstub_dylib_file.hpp"
 #include "archive_file.h"
 #include "lto_file.h"
 #include "opaque_section_file.h"
@@ -294,7 +295,17 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
 	objOpts.neverConvertDwarf   = !_options.needsUnwindInfoSection();
 	objOpts.verboseOptimizationHints = _options.verboseOptimizationHints();
 	objOpts.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions();
+	objOpts.simulator			= _options.targetIOSSimulator();
+	objOpts.ignoreMismatchPlatform = ((_options.outputKind() == Options::kPreload) || (_options.outputKind() == Options::kStaticExecutable));
 	objOpts.subType				= _options.subArchitecture();
+	objOpts.platform			= _options.platform();
+	objOpts.minOSVersion		= _options.minOSversion();
+	// workaround for strip -S
+	// when ld -r has single input file, set the srcKind to kSourceSingle so __LLVM segment will be kept
+	if (_options.outputKind() == Options::kObjectFile && _options.getInputFiles().size() == 1)
+		objOpts.srcKind			= ld::relocatable::File::kSourceSingle;
+	else
+		objOpts.srcKind				= ld::relocatable::File::kSourceObj;
 	ld::relocatable::File* objResult = mach_o::relocatable::parse(p, len, info.path, info.modTime, info.ordinal, objOpts);
 	if ( objResult != NULL ) {
 		OSAtomicAdd64(len, &_totalObjectSize);
@@ -310,7 +321,7 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
 		return objResult;
 	}
 	
-	// see if it is a dynamic library
+	// see if it is a dynamic library (or text-based dynamic library)
 	ld::dylib::File* dylibResult;
 	bool dylibsNotAllowed = false;
 	switch ( _options.outputKind() ) {
@@ -321,6 +332,10 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
 			if ( dylibResult != NULL ) {
 				return dylibResult;
 			}
+			dylibResult = textstub::dylib::parse(p, len, info.path, info.modTime, _options, info.ordinal, info.options.fBundleLoader, indirectDylib);
+			if ( dylibResult != NULL ) {
+				return dylibResult;
+			}
 			break;
 		case Options::kStaticExecutable:
 		case Options::kDyld:
@@ -331,7 +346,6 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
 			break;
 	}
 
-
 	// see if it is a static library
 	::archive::ParserOptions archOpts;
 	archOpts.objOpts				= objOpts;
@@ -341,6 +355,12 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
 	archOpts.objcABI2				= _options.objCABIVersion2POverride();
 	archOpts.verboseLoad			= _options.whyLoad();
 	archOpts.logAllFiles			= _options.logAllFiles();
+	// Set ObjSource Kind, libclang_rt is compiler static library
+	const char* libName = strrchr(info.path, '/');
+	if ( (libName != NULL) && (strncmp(libName, "/libclang_rt", 12) == 0) )
+		archOpts.objOpts.srcKind = ld::relocatable::File::kSourceCompilerArchive;
+	else
+		archOpts.objOpts.srcKind = ld::relocatable::File::kSourceArchive;
 	ld::archive::File* archiveResult = ::archive::parse(p, len, info.path, info.modTime, info.ordinal, archOpts);
 	if ( archiveResult != NULL ) {
 		OSAtomicAdd64(len, &_totalArchiveSize);
@@ -587,6 +607,7 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan
 				ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
 				if ( dylibReader != NULL ) {
 					if ( ! dylibReader->installPathVersionSpecific() ) {
+						dylibReader->forEachAtom(handler);
 						dylibReader->setImplicitlyLinked();
 						this->addDylib(dylibReader, info);
 					}
@@ -613,6 +634,7 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan
 				ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
 				ld::archive::File* archiveReader = dynamic_cast<ld::archive::File*>(reader);
 				if ( dylibReader != NULL ) {
+					dylibReader->forEachAtom(handler);
 					dylibReader->setImplicitlyLinked();
 					this->addDylib(dylibReader, info);
 				}
@@ -775,20 +797,27 @@ void InputFiles::inferArchitecture(Options& opts, const char** archName)
 	_inferredArch = true;
 	// scan all input files, looking for a thin .o file.
 	// the first one found is presumably the architecture to link
-	uint8_t buffer[sizeof(mach_header_64)];
+	uint8_t buffer[4096];
 	const std::vector<Options::FileInfo>& files = opts.getInputFiles();
 	for (std::vector<Options::FileInfo>::const_iterator it = files.begin(); it != files.end(); ++it) {
 		int fd = ::open(it->path, O_RDONLY, 0);
 		if ( fd != -1 ) {
-			ssize_t amount = read(fd, buffer, sizeof(buffer));
-			::close(fd);
-			if ( amount >= (ssize_t)sizeof(buffer) ) {
-				cpu_type_t type;
-				cpu_subtype_t subtype;
-				if ( mach_o::relocatable::isObjectFile(buffer, &type, &subtype) ) {
-					opts.setArchitecture(type, subtype);
-					*archName = opts.architectureName();
-					return;
+			struct stat stat_buf;
+			if ( fstat(fd, &stat_buf) != -1) {
+				ssize_t readAmount = stat_buf.st_size;
+				if ( 4096 < readAmount )
+					readAmount = 4096;
+				ssize_t amount = read(fd, buffer, readAmount);
+				::close(fd);
+				if ( amount >= readAmount ) {
+					cpu_type_t type;
+					cpu_subtype_t subtype;
+					Options::Platform platform;
+					if ( mach_o::relocatable::isObjectFile(buffer, &type, &subtype, &platform) ) {
+						opts.setArchitecture(type, subtype, platform);
+						*archName = opts.architectureName();
+						return;
+					}
 				}
 			}
 		}
@@ -797,11 +826,11 @@ void InputFiles::inferArchitecture(Options& opts, const char** archName)
 	// no thin .o files found, so default to same architecture this tool was built as
 	warning("-arch not specified");
 #if __i386__
-	opts.setArchitecture(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL);
+	opts.setArchitecture(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL, Options::kPlatformOSX);
 #elif __x86_64__
-	opts.setArchitecture(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL);
+	opts.setArchitecture(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL, Options::kPlatformOSX);
 #elif __arm__
-	opts.setArchitecture(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6);
+	opts.setArchitecture(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6, Options::kPlatformOSX);
 #else
 	#error unknown default architecture
 #endif
diff --git a/src/ld/LinkEdit.hpp b/src/ld/LinkEdit.hpp
index 3420626..c4421ef 100644
--- a/src/ld/LinkEdit.hpp
+++ b/src/ld/LinkEdit.hpp
@@ -32,6 +32,7 @@
 #include <unistd.h>
 
 #include <vector>
+#include <unordered_map>
 
 #include "Options.h"
 #include "ld.hpp"
@@ -81,6 +82,17 @@ public:
 		while( more );
 	}
 	
+	void append_delta_encoded_uleb128_run(uint64_t start, const std::vector<uint64_t>& locations) {
+		uint64_t lastAddr = start;
+		for(std::vector<uint64_t>::const_iterator it = locations.begin(); it != locations.end(); ++it) {
+			uint64_t nextAddr = *it;
+			uint64_t delta = nextAddr - lastAddr;
+			assert(delta != 0);
+			append_uleb128(delta);
+			lastAddr = nextAddr;
+		}
+	}
+
 	void append_string(const char* str) {
 		for (const char* s = str; *s != '\0'; ++s)
 			_data.push_back(*s);
@@ -219,6 +231,8 @@ void RebaseInfoAtom<A>::encode() const
 		}
 		mid.push_back(rebase_tmp(REBASE_OPCODE_DO_REBASE_ULEB_TIMES, 1));
 		address += sizeof(pint_t);
+		if ( address >= curSegEnd )
+			address = 0;
 	}
 	mid.push_back(rebase_tmp(REBASE_OPCODE_DONE, 0));
 
@@ -969,6 +983,7 @@ void ExportInfoAtom<A>::encode() const
 	std::vector<const ld::Atom*>& exports = this->_writer._exportedAtoms;
 	uint64_t imageBaseAddress = this->_writer.headerAndLoadCommandsSection->address;
 	std::vector<mach_o::trie::Entry> entries;
+	unsigned int padding = 0;
 	entries.reserve(exports.size());
 	for (std::vector<const ld::Atom*>::const_iterator it = exports.begin(); it != exports.end(); ++it) {
 		const ld::Atom* atom = *it;
@@ -1035,6 +1050,13 @@ void ExportInfoAtom<A>::encode() const
 			entry.importName = NULL;
 			entries.push_back(entry);
 		}
+
+		if (_options.sharedRegionEligible() && strncmp(atom->section().segmentName(), "__DATA", 6) == 0) {
+			// Maximum address is 64bit which is 10 bytes as a uleb128. Minimum is 1 byte
+			// Pad the section out so we can deal with addresses getting larger when __DATA segment
+			// is moved before __TEXT in dyld shared cache.
+			padding += 9;
+		}
 	}
 
 	// sort vector by -exported_symbols_order, and any others by address
@@ -1043,6 +1065,10 @@ void ExportInfoAtom<A>::encode() const
 	// create trie
 	mach_o::trie::makeTrie(entries, this->_encodedData.bytes());
 
+	//Add additional data padding for the unoptimized shared cache
+	for (unsigned int i = 0; i < padding; ++i)
+		this->_encodedData.append_byte(0);
+
 	// align to pointer size
 	this->_encodedData.pad_to_size(sizeof(pint_t));
 	
@@ -1051,10 +1077,10 @@ void ExportInfoAtom<A>::encode() const
 
 
 template <typename A>
-class SplitSegInfoAtom : public LinkEditAtom
+class SplitSegInfoV1Atom : public LinkEditAtom
 {
 public:
-												SplitSegInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
+												SplitSegInfoV1Atom(const Options& opts, ld::Internal& state, OutputFile& writer)
 													: LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
 
 	// overrides of ld::Atom
@@ -1083,10 +1109,10 @@ private:
 };
 
 template <typename A>
-ld::Section SplitSegInfoAtom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
+ld::Section SplitSegInfoV1Atom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
 
 template <>
-void SplitSegInfoAtom<x86_64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
+void SplitSegInfoV1Atom<x86_64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
 {
 	switch (kind) {
 		case ld::Fixup::kindStoreX86PCRel32:
@@ -1116,7 +1142,7 @@ void SplitSegInfoAtom<x86_64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind
 }
 
 template <>
-void SplitSegInfoAtom<x86>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
+void SplitSegInfoV1Atom<x86>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
 {
 	switch (kind) {
 		case ld::Fixup::kindStoreLittleEndian32:
@@ -1132,7 +1158,7 @@ void SplitSegInfoAtom<x86>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind ki
 }
 
 template <>
-void SplitSegInfoAtom<arm>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
+void SplitSegInfoV1Atom<arm>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
 {
 	switch (kind) {
 		case ld::Fixup::kindStoreLittleEndian32:
@@ -1160,7 +1186,7 @@ void SplitSegInfoAtom<arm>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind ki
 
 #if SUPPORT_ARCH_arm64
 template <>
-void SplitSegInfoAtom<arm64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
+void SplitSegInfoV1Atom<arm64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
 {
 	switch (kind) {
 		case ld::Fixup::kindStoreARM64Page21:
@@ -1188,7 +1214,7 @@ void SplitSegInfoAtom<arm64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind
 #endif
 
 template <typename A>
-void SplitSegInfoAtom<A>::uleb128EncodeAddresses(const std::vector<uint64_t>& locations) const
+void SplitSegInfoV1Atom<A>::uleb128EncodeAddresses(const std::vector<uint64_t>& locations) const
 {
 	pint_t addr = this->_options.baseAddress();
 	for(typename std::vector<uint64_t>::const_iterator it = locations.begin(); it != locations.end(); ++it) {
@@ -1215,12 +1241,12 @@ void SplitSegInfoAtom<A>::uleb128EncodeAddresses(const std::vector<uint64_t>& lo
 
 
 template <typename A>
-void SplitSegInfoAtom<A>::encode() const
+void SplitSegInfoV1Atom<A>::encode() const
 {
 	// sort into group by pointer adjustment kind
 	std::vector<OutputFile::SplitSegInfoEntry>& info = this->_writer._splitSegInfos;
 	for (std::vector<OutputFile::SplitSegInfoEntry>::const_iterator it = info.begin(); it != info.end(); ++it) {
-		this->addSplitSegInfo(it->address, it->kind, it->extra);
+		this->addSplitSegInfo(it->fixupAddress, it->kind, it->extra);
 	}
 
 	// delta compress runs of addresses
@@ -1298,6 +1324,108 @@ void SplitSegInfoAtom<A>::encode() const
 	_64bitPointerLocations.clear();
 }
 
+
+template <typename A>
+class SplitSegInfoV2Atom : public LinkEditAtom
+{
+public:
+												SplitSegInfoV2Atom(const Options& opts, ld::Internal& state, OutputFile& writer)
+													: LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
+
+	// overrides of ld::Atom
+	virtual const char*							name() const		{ return "split seg info"; }
+	// overrides of LinkEditAtom
+	virtual void								encode() const;
+
+private:
+	typedef typename A::P						P;
+	typedef typename A::P::E					E;
+	typedef typename A::P::uint_t				pint_t;
+
+	// Whole		 :== <count> FromToSection+
+	// FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+
+	// ToOffset		 :== <to-sect-offset-delta> <count> FromOffset+
+	// FromOffset	 :== <kind> <count> <from-sect-offset-delta>
+
+	typedef uint32_t SectionIndexes;
+	typedef std::map<uint8_t, std::vector<uint64_t> > FromOffsetMap;
+	typedef std::map<uint64_t, FromOffsetMap> ToOffsetMap;
+	typedef std::map<SectionIndexes, ToOffsetMap> WholeMap;
+
+
+	static ld::Section			_s_section;
+};
+
+template <typename A>
+ld::Section SplitSegInfoV2Atom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
+
+
+template <typename A>
+void SplitSegInfoV2Atom<A>::encode() const
+{
+	// sort into group by adjustment kind
+	//fprintf(stderr, "_splitSegV2Infos.size=%lu\n", this->_writer._splitSegV2Infos.size());
+	WholeMap whole;
+	for (const OutputFile::SplitSegInfoV2Entry&  entry : this->_writer._splitSegV2Infos) {
+		//fprintf(stderr, "from=%d, to=%d\n", entry.fixupSectionIndex, entry.targetSectionIndex);
+		SectionIndexes index = entry.fixupSectionIndex << 16 | entry.targetSectionIndex;
+		ToOffsetMap& toOffsets = whole[index];
+		FromOffsetMap& fromOffsets = toOffsets[entry.targetSectionOffset];
+		fromOffsets[entry.referenceKind].push_back(entry.fixupSectionOffset);
+	}
+
+	// Add marker that this is V2 data
+	this->_encodedData.reserve(8192);
+	this->_encodedData.append_byte(DYLD_CACHE_ADJ_V2_FORMAT); 
+
+	// stream out
+	// Whole :== <count> FromToSection+
+	this->_encodedData.append_uleb128(whole.size());
+	for (auto& fromToSection : whole) {
+		uint8_t fromSectionIndex = fromToSection.first >> 16;
+		uint8_t toSectionIndex   = fromToSection.first & 0xFFFF;
+		ToOffsetMap& toOffsets   = fromToSection.second;
+		// FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+
+		this->_encodedData.append_uleb128(fromSectionIndex);
+		this->_encodedData.append_uleb128(toSectionIndex);
+		this->_encodedData.append_uleb128(toOffsets.size());
+		//fprintf(stderr, "from sect=%d, to sect=%d, count=%lu\n", fromSectionIndex, toSectionIndex, toOffsets.size());
+		uint64_t lastToOffset = 0;
+		for (auto& fromToOffsets : toOffsets) {
+			uint64_t toSectionOffset = fromToOffsets.first;
+			FromOffsetMap& fromOffsets = fromToOffsets.second;
+			// ToOffset	:== <to-sect-offset-delta> <count> FromOffset+
+			this->_encodedData.append_uleb128(toSectionOffset - lastToOffset);
+			this->_encodedData.append_uleb128(fromOffsets.size());
+			for (auto& kindAndOffsets : fromOffsets) {
+				uint8_t kind = kindAndOffsets.first;
+				std::vector<uint64_t>& fromOffsets = kindAndOffsets.second;
+				// FromOffset :== <kind> <count> <from-sect-offset-delta>
+				this->_encodedData.append_uleb128(kind);
+				this->_encodedData.append_uleb128(fromOffsets.size());
+				std::sort(fromOffsets.begin(), fromOffsets.end());
+				uint64_t lastFromOffset = 0;
+				for (uint64_t offset : fromOffsets) {
+					this->_encodedData.append_uleb128(offset - lastFromOffset);
+					lastFromOffset = offset;
+				}
+			}
+			lastToOffset = toSectionOffset;
+		}
+	}
+
+
+	// always add zero byte to mark end
+	this->_encodedData.append_byte(0);
+
+	// align to pointer size
+	this->_encodedData.pad_to_size(sizeof(pint_t));
+	
+	this->_encoded = true;
+}
+
+
+
 template <typename A>
 class FunctionStartsAtom : public LinkEditAtom
 {
@@ -1497,63 +1625,6 @@ void DataInCodeAtom<A>::encode() const
 
 
 
-// <rdar://problem/7209249> linker needs to cache "Designated Requirements" in linked binary
-template <typename A>
-class DependentDRAtom : public LinkEditAtom
-{
-public:
-												DependentDRAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
-													: LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
-
-	// overrides of ld::Atom
-	virtual const char*							name() const		{ return "dependent dylib DR info"; }
-	// overrides of LinkEditAtom
-	virtual void								encode() const;
-
-private:
-	typedef typename A::P						P;
-	typedef typename A::P::E					E;
-	typedef typename A::P::uint_t				pint_t;
-
-	static ld::Section			_s_section;
-
-};
-
-template <typename A>
-ld::Section DependentDRAtom<A>::_s_section("__LINKEDIT", "__dependentDR", ld::Section::typeLinkEdit, true);
-
-
-template <typename A>
-void DependentDRAtom<A>::encode() const
-{
-	Security::SuperBlobCore<Security::SuperBlob<Security::kSecCodeMagicDRList>, Security::kSecCodeMagicDRList, uint32_t>::Maker maker;
-	
-	uint32_t index = 0;
-	for(std::vector<ld::dylib::File*>::iterator it=_state.dylibs.begin(); it != _state.dylibs.end(); ++it) {
-		const ld::dylib::File* dylib = *it;
-		Security::BlobCore* dylibDR = (Security::BlobCore*)dylib->codeSignatureDR();
-		void* dup = NULL;
-		if ( dylibDR != NULL ) {
-			// <rdar://problem/11315321> Maker takes ownership of every blob added
-			// We need to make a copy here because dylib still owns the pointer returned by codeSignatureDR()
-			dup = ::malloc(dylibDR->length());
-			::memcpy(dup, dylibDR, dylibDR->length());
-		}
-		maker.add(index, (Security::BlobCore*)dup);
-		++index;
-	}
-	
-	Security::SuperBlob<Security::kSecCodeMagicDRList>* topBlob = maker.make();
-	const uint8_t* data = (uint8_t*)topBlob->data();
-	for(size_t i=0; i < topBlob->length(); ++i)
-		_encodedData.append_byte(data[i]);
-	
-	this->_encodedData.pad_to_size(sizeof(pint_t));
-
-	this->_encoded = true;
-}
-
-
 
 template <typename A>
 class OptimizationHintsAtom : public LinkEditAtom
diff --git a/src/ld/LinkEditClassic.hpp b/src/ld/LinkEditClassic.hpp
index 3389f5c..ee1c207 100644
--- a/src/ld/LinkEditClassic.hpp
+++ b/src/ld/LinkEditClassic.hpp
@@ -1614,9 +1614,17 @@ void SectionRelocationsAtom<arm>::encodeSectionReloc(ld::Internal::FinalSection*
 			{
 				int len = 0;
 				uint32_t otherHalf = 0;
-				uint32_t value = entry.toTarget->finalAddress()+entry.toAddend;
-				if ( entry.fromTarget != NULL ) 
-					value -= (entry.fromTarget->finalAddress()+entry.fromAddend);
+				uint32_t value;
+				if ( entry.fromTarget != NULL )  {
+				  // this is a sect-diff
+				  value = (entry.toTarget->finalAddress()+entry.toAddend) - (entry.fromTarget->finalAddress()+entry.fromAddend);
+				}
+				else {
+					// this is an absolute address
+					value = entry.toAddend;
+					if ( !external )
+						value += entry.toTarget->finalAddress();
+				}
 				switch ( entry.kind ) {
 					case ld::Fixup::kindStoreARMLow16:
 						len = 0;
diff --git a/src/ld/Options.cpp b/src/ld/Options.cpp
index 228a0df..a638cb4 100644
--- a/src/ld/Options.cpp
+++ b/src/ld/Options.cpp
@@ -36,12 +36,19 @@
 #include <Availability.h>
 
 #include <vector>
+#include <map>
+#include <sstream>
 
 #include "Options.h"
 #include "Architectures.hpp"
 #include "MachOFileAbstraction.hpp"
 #include "Snapshot.h"
 
+
+// from FunctionNameDemangle.h
+extern "C" size_t fnd_get_demangled_name(const char *mangledName, char *outputBuffer, size_t length);
+
+
 // upward dependency on lto::version()
 namespace lto {
 	extern const char* version();
@@ -143,11 +150,11 @@ Options::Options(int argc, const char* argv[])
 	  fCommonsMode(kCommonsIgnoreDylibs),  fUUIDMode(kUUIDContent), fLocalSymbolHandling(kLocalSymbolsAll), fWarnCommons(false), 
 	  fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
 	  fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
-	  fSharedRegionEligible(false), fPrintOrderFileStatistics(false),  
+	  fSharedRegionEligible(false), fSharedRegionEligibleForceOff(false), fPrintOrderFileStatistics(false),
 	  fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fPIEOnCommandLine(false),
 	  fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
 	  fDeadStripDylibs(false),  fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
-	  fUsingLazyDylibLinking(false), fEncryptable(true), 
+	  fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
 	  fOrderData(true), fMarkDeadStrippableDylib(false),
 	  fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
 	  fAllowCpuSubtypeMismatches(false), fUseSimplifiedDylibReExports(false),
@@ -171,16 +178,19 @@ Options::Options(int argc, const char* argv[])
 	  fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
 	  fSourceVersionLoadCommand(false), 
 	  fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false), 
-	  fDependentDRInfo(false), fDependentDRInfoForcedOn(false), fDependentDRInfoForcedOff(false),
 	  fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
 	  fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
 	  fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
 	  fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
 	  fGenerateDtraceDOF(true), fAllowBranchIslands(true), fTraceSymbolLayout(false), 
-	  fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false), 
-	  fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL), 
-	  fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset), 
-	  fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL), 
+	  fMarkAppExtensionSafe(false), fCheckAppExtensionSafe(false), fForceLoadSwiftLibs(false),
+	  fSharedRegionEncodingV2(false), fUseDataConstSegment(false),
+	  fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false),
+	  fBundleBitcode(false), fHideSymbols(false), fReverseMapUUIDRename(false), fReverseMapPath(NULL), fLTOCodegenOnly(false),
+	  fIgnoreAutoLink(false), fPlatform(kPlatformUnknown),
+	  fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
+	  fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset),
+	  fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL),
 	  fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1)
 {
 	this->checkForClassic(argc, argv);
@@ -236,7 +246,7 @@ bool Options::interposable(const char* name) const
 
 bool Options::printWhyLive(const char* symbolName) const
 {
-	return ( fWhyLive.find(symbolName) != fWhyLive.end() );
+	return fWhyLive.contains(symbolName);
 }
 
 
@@ -325,7 +335,7 @@ uint32_t Options::maxSegProtection(const char* segName) const
 {
 	// iPhoneOS always uses same protection for max and initial
 	// <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
-	if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fArchitecture != CPU_TYPE_I386) )
+	if ( (fPlatform != kPlatformOSX) && !fTargetIOSSimulator )
 		return initialSegProtection(segName);
 
 	for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
@@ -391,6 +401,17 @@ uint8_t Options::customSectionAlignment(const char* segName, const char* sectNam
 	return 0;
 }
 
+bool Options::segmentOrderAfterFixedAddressSegment(const char* segName) const
+{
+	bool nowPinned = false;
+	for (std::vector<const char*>::const_iterator it=fSegmentOrder.begin(); it != fSegmentOrder.end(); ++it) {
+		if ( strcmp(*it, segName) == 0 )
+			return nowPinned;
+		if ( hasCustomSegmentAddress(*it) )
+			nowPinned = true;
+	}
+	return false;
+}
 
 bool Options::hasExportedSymbolOrder()
 {
@@ -549,9 +570,26 @@ const std::vector<const char*>* Options::sectionOrder(const char* segName) const
 	return NULL;
 }
 
+uint32_t Options::minOSversion() const
+{
+	switch (fPlatform) {
+		case kPlatformiOS:
+			return iOSVersionMin();
+		case kPlatformOSX:
+			return macosxVersionMin();
+		case kPlatformWatchOS:
+			return watchOSVersionMin();
+#if SUPPORT_APPLE_TV
+		case Options::kPlatform_tvOS:
+			return iOSVersionMin();
+#endif
+		default:
+			break;
+	}
+	return 0;
+}
 
-
-void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
+void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, Options::Platform platform)
 {
 	for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
 		if ( (type == t->cpuType) && (subtype == t->cpuSubType) ) {
@@ -560,10 +598,11 @@ void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
 			fArchitectureName = t->archName;
 			fHasPreferredSubType = t->isSubType;
 			fArchSupportsThumb2 = t->supportsThumb2;
+			fPlatform = platform;
 			switch ( type ) {
 				case CPU_TYPE_I386:
 				case CPU_TYPE_X86_64:
-					if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
+					if ( (fPlatform == kPlatformOSX) && (fOutputKind != Options::kObjectFile) ) {
 				#ifdef DEFAULT_MACOSX_MIN_VERSION
 						warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
 						setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
@@ -575,7 +614,7 @@ void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
 					break;
 				case CPU_TYPE_ARM:
 				case CPU_TYPE_ARM64:
-					if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
+					if ( (fPlatform == kPlatformiOS) && (fOutputKind != Options::kObjectFile) ) {
 				#if defined(DEFAULT_IPHONEOS_MIN_VERSION)
 						warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
 						setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
@@ -672,6 +711,8 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) co
 						 it != fLibrarySearchPaths.end();
 						 it++) {
 						const char* dir = *it;
+						if ( checkForFile("%s/lib%s.tbd", dir, rootName, result) )
+							return result;
 						if ( checkForFile("%s/lib%s.dylib", dir, rootName, result) )
 							return result;
 					}
@@ -701,6 +742,8 @@ Options::FileInfo Options::findLibrary(const char* rootName, bool dylibsOnly) co
 					 it != fLibrarySearchPaths.end();
 					 it++) {
 					const char* dir = *it;
+					if ( lookForDylibs && checkForFile("%s/lib%s.tbd", dir, rootName, result) )
+						return result;
 					if ( lookForDylibs && checkForFile("%s/lib%s.dylib", dir, rootName, result) )
 						return result;
 					if ( lookForDylibs && checkForFile("%s/lib%s.so", dir, rootName, result) )
@@ -732,31 +775,21 @@ Options::FileInfo Options::findFramework(const char* frameworkName) const
 
 Options::FileInfo Options::findFramework(const char* rootName, const char* suffix) const
 {
-	for (std::vector<const char*>::const_iterator it = fFrameworkSearchPaths.begin();
-		 it != fFrameworkSearchPaths.end();
-		 it++) {
-		// ??? Shouldn't we be using String here and just initializing it?
-		// ??? Use str.c_str () to pull out the string for the stat call.
-		const char* dir = *it;
-		char possiblePath[PATH_MAX];
-		strcpy(possiblePath, dir);
-		strcat(possiblePath, "/");
-		strcat(possiblePath, rootName);
-		strcat(possiblePath, ".framework/");
-		strcat(possiblePath, rootName);
-		if ( suffix != NULL ) {
+	for (const auto* path : fFrameworkSearchPaths) {
+		auto possiblePath = std::string(path).append("/").append(rootName).append(".framework/").append(rootName);
+		if ( suffix != nullptr ) {
 			char realPath[PATH_MAX];
 			// no symlink in framework to suffix variants, so follow main symlink
-			if ( realpath(possiblePath, realPath) != NULL ) {
-				strcpy(possiblePath, realPath);
-				strcat(possiblePath, suffix);
-			}
+			if ( realpath(possiblePath.c_str(), realPath) != nullptr )
+				possiblePath = std::string(realPath).append(suffix);
 		}
         FileInfo result;
-		bool found = result.checkFileExists(*this, possiblePath);
+		bool found = result.checkFileExists(*this, (possiblePath + ".tbd").c_str());
+		if ( !found )
+			found = result.checkFileExists(*this, possiblePath.c_str());
 		if ( fTraceDylibSearching )
 			printf("[Logging for XBS]%sfound framework: '%s'\n",
-				   (found ? " " : " not "), possiblePath);
+				   (found ? " " : " not "), possiblePath.c_str());
 		if ( found ) {
 			return result;
 		}
@@ -768,68 +801,84 @@ Options::FileInfo Options::findFramework(const char* rootName, const char* suffi
 		throwf("framework not found %s", rootName);
 }
 
-Options::FileInfo Options::findFile(const char* path) const
+Options::FileInfo Options::findFile(const std::string &path) const
 {
 	FileInfo result;
 
-	// if absolute path and not a .o file, the use SDK prefix
-	if ( (path[0] == '/') && (strcmp(&path[strlen(path)-2], ".o") != 0) ) {
-		const int pathLen = strlen(path);
-		for (std::vector<const char*>::const_iterator it = fSDKPaths.begin(); it != fSDKPaths.end(); it++) {
-			// ??? Shouldn't we be using String here?
-			const char* sdkPathDir = *it;
-			const int sdkPathDirLen = strlen(sdkPathDir);
-			char possiblePath[sdkPathDirLen+pathLen+4];
-			strcpy(possiblePath, sdkPathDir);
-			if ( possiblePath[sdkPathDirLen-1] == '/' )
-				possiblePath[sdkPathDirLen-1] = '\0';
-			strcat(possiblePath, path);
-			if ( result.checkFileExists(*this, possiblePath) ) {
+	// if absolute path and not a .o file, then use SDK prefix
+	if ( (path[0] == '/') && (strcmp(&path[path.size()-2], ".o") != 0) ) {
+		auto tbdFile = path;
+		auto lastSlashIdx = tbdFile.find_last_of('/');
+		auto lastDotIdx = tbdFile.find_last_of('.');
+		if (lastDotIdx != std::string::npos && lastDotIdx > lastSlashIdx)
+			tbdFile.erase(lastDotIdx, std::string::npos);
+		tbdFile.append(".tbd");
+
+		for (const auto* sdkPathDir : fSDKPaths) {
+			auto possiblePath = std::string(sdkPathDir) + tbdFile;
+			if ( result.checkFileExists(*this, possiblePath.c_str()) )
+				return result;
+			possiblePath = std::string(sdkPathDir) + path;
+			if ( result.checkFileExists(*this, possiblePath.c_str()) )
 				return result;
-			}
 		}
 	}
 	// try raw path
-	if ( result.checkFileExists(*this, path) ) {
+	{
+		std::string file = path;
+		auto lastDotIdx = file.find_last_of('.');
+		if (lastDotIdx != std::string::npos)
+			file.erase(lastDotIdx, std::string::npos);
+		if ( result.checkFileExists(*this, file.append(".tbd").c_str()) )
+			return result;
+	}
+	if ( result.checkFileExists(*this, path.c_str()) ) {
 		return result;
 	}
 
+
 	// try @executable_path substitution
-	if ( (strncmp(path, "@executable_path/", 17) == 0) && (fExecutablePath != NULL) ) {
-		char newPath[strlen(fExecutablePath) + strlen(path)];
+	if ( (path.find("@executable_path/") == 0) && (fExecutablePath != nullptr) ) {
+		char newPath[strlen(fExecutablePath) + path.size()];
 		strcpy(newPath, fExecutablePath);
 		char* addPoint = strrchr(newPath,'/');
-		if ( addPoint != NULL )
+		if ( addPoint != nullptr )
 			strcpy(&addPoint[1], &path[17]);
 		else
 			strcpy(newPath, &path[17]);
+
+		std::string file = newPath;
+		auto lastDotIdx = file.find_last_of('.');
+		if (lastDotIdx != std::string::npos)
+			file.erase(lastDotIdx, std::string::npos);
+		if ( result.checkFileExists(*this, file.append(".tbd").c_str()) ) {
+			return result;
+		}
 		if ( result.checkFileExists(*this, newPath) ) {
 			return result;
 		}
 	}
 
 	// not found
-	throwf("file not found: %s", path);
+	throwf("file not found: %s", path.c_str());
 }
 
-Options::FileInfo Options::findFileUsingPaths(const char* path) const 
+Options::FileInfo Options::findFileUsingPaths(const std::string &path) const
 {
 	FileInfo result;
 
-	const char* lastSlash = strrchr(path, '/');
-	const char* leafName = (lastSlash == NULL) ? path : &lastSlash[1];
+	auto lastSlashPos = path.find_last_of('/');
+	auto pos = ( lastSlashPos != std::string::npos ) ? lastSlashPos + 1 : 0;
+	auto leafName = path.substr(pos);
 
 	// 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 )
+	if ( lastSlashPos != std::string::npos ) {
+		auto frameworkDir = std::string("/").append(leafName).append(".framework/");
+		if ( path.rfind(frameworkDir) != std::string::npos )
 			isFramework = true;
 	}
 	
@@ -838,35 +887,28 @@ Options::FileInfo Options::findFileUsingPaths(const char* path) const
 	// 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*>::const_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) )
+		auto endPos = path.rfind(".framework");
+		auto beginPos = path.find_last_of('/', endPos);
+		auto leafPath = path.substr(beginPos);
+		for (const auto* dir : fFrameworkSearchPaths) {
+			auto possiblePath = dir + leafPath;
+			if ( checkForFile("%s.%s", possiblePath.c_str(), "tbd", result) )
+				return result;
+			if ( checkForFile("%s", possiblePath.c_str(), "", result) )
 				return result;
 		}
-	} 
-	else {
+	} else {
 		// if this is a .dylib inside a framework, do not search -L paths
-		// <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard 
-		int leafLen = strlen(leafName);
-		bool embeddedDylib = ( (leafLen > 6) 
-					&& (strcmp(&leafName[leafLen-6], ".dylib") == 0) 
-					&& (strstr(path, ".framework/") != NULL) );
+		// <rdar://problem/5427952> ld64's re-export cycle detection logic prevents use of X11 libGL on Leopard
+		bool embeddedDylib = ( (leafName.size() > 6)
+					&& (leafName.find(".dylib", leafName.size()-6) != std::string::npos)
+					&& (path.find(".framework/") != std::string::npos) );
 		if ( !embeddedDylib ) {
-			for (std::vector<const char*>::const_iterator it = fLibrarySearchPaths.begin();
-				 it != fLibrarySearchPaths.end();
-				 it++) {
-				const char* dir = *it;
+			for (const auto* dir : fLibrarySearchPaths) {
 				//fprintf(stderr,"Finding Library: %s/%s\n", dir, leafName);
-				if ( checkForFile("%s/%s", dir, leafName, result) )
+				if ( checkForFile("%s/%s", dir, std::string(leafName).append(".tbd").c_str(), result) )
+					return result;
+				if ( checkForFile("%s/%s", dir, leafName.c_str(), result) )
 					return result;
 			}
 		}
@@ -1070,6 +1112,23 @@ bool Options::SetWithWildcards::containsNonWildcard(const char* symbol) const
 }
 
 
+std::vector<const char*> Options::exportsData() const
+{
+	return fExportSymbols.data();
+}
+
+
+std::vector<const char*> Options::SetWithWildcards::data() const
+{
+	std::vector<const char*> data;
+	for (NameSet::iterator it=regularBegin(); it != regularEnd(); ++it) {
+		data.push_back(*it);
+	}
+	for (std::vector<const char*>::const_iterator it=fWildCard.begin(); it != fWildCard.end(); ++it) {
+		data.push_back(*it);
+	}
+	return data;
+}
 
 bool Options::SetWithWildcards::inCharRange(const char*& p, unsigned char c) const
 {
@@ -1348,6 +1407,7 @@ void Options::setMacOSXVersionMin(const char* version)
 			minorVersion = 255;
 		}
 		fMacVersionMin = (ld::MacVersionMin)(0x000A0000 | (minorVersion << 8));
+		fPlatform = kPlatformOSX;
 	}
 	else {
 		warning("unknown option to -macosx_version_min, not 10.x");
@@ -1368,18 +1428,52 @@ void Options::setIOSVersionMin(const char* version)
 	unsigned int majorVersion = version[0] - '0';
 	unsigned int minorVersion = version[2] - '0';
 	fIOSVersionMin = (ld::IOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
+	fPlatform = kPlatformiOS;
+}
+
+
+void Options::setWatchOSVersionMin(const char* version)
+{
+	if ( version == NULL )
+		throw "-watchos_version_min argument missing";
+	if ( ! isdigit(version[0]) )
+		throw "-watchos_version_min argument is not a number";
+	if ( version[1] != '.' )
+		throw "-watchos_version_min argument is missing period as second character";
+	if ( ! isdigit(version[2]) )
+		throw "-watchos_version_min argument is not a number";
+
+	unsigned int majorVersion = version[0] - '0';
+	unsigned int minorVersion = version[2] - '0';
+	fWatchOSVersionMin = (ld::WatchOSVersionMin)((majorVersion << 16) | (minorVersion << 8));
+	fPlatform = kPlatformWatchOS;
 }
 
+
 bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
 {
 	if ( fMacVersionMin != ld::macVersionUnset ) {
 		return ( fMacVersionMin >= requiredMacMin );
 	}
+	else if ( fWatchOSVersionMin != ld::wOSVersionUnset ) {
+		// Hack until we fully track watch and ios versions seperately
+		return ( (fWatchOSVersionMin + 0x00070000) >= requirediPhoneOSMin);
+	}
 	else {
-		return ( fIOSVersionMin >= requirediPhoneOSMin);
+		return ( fIOSVersionMin >= requirediPhoneOSMin );
 	}
 }
 
+bool Options::min_iOS(ld::IOSVersionMin requirediOSMin)
+{
+	 if ( fWatchOSVersionMin != ld::wOSVersionUnset ) {
+		// Hack until we fully track watch and ios versions seperately
+		return ( (fWatchOSVersionMin + 0x00070000) >= requirediOSMin);
+	}
+	else {
+		return ( fIOSVersionMin >= requirediOSMin );
+	}
+}
 
 void Options::setWeakReferenceMismatchTreatment(const char* treatment)
 {
@@ -1766,7 +1860,7 @@ void Options::addSection(const char* segment, const char* section, const char* p
 	::close(fd);
 
 	// record section to create
-	ExtraSection info = { segment, section, path, (uint8_t*)p, stat_buf.st_size };
+	ExtraSection info = { segment, section, path, (uint8_t*)p, (uint64_t)stat_buf.st_size };
 	fExtraSections.push_back(info);
 }
 
@@ -1895,7 +1989,188 @@ void Options::warnObsolete(const char* arg)
 }
 
 
+void Options::cannotBeUsedWithBitcode(const char* arg)
+{
+	if ( fBundleBitcode )
+		throwf("%s and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot be used together", arg);
+}
+
+std::string Options::getVersionString32(uint32_t ver) const
+{
+	if (ver == 0 || ver >= 0x10000000)
+		return "0.0.0";
+
+	unsigned microVersion = ver & 0xFF;
+	unsigned minorVersion = (ver >> 8) & 0xFF;
+	unsigned majorVersion = (ver >> 16) & 0xFF;
+	std::stringstream versionString;
+	versionString << majorVersion << "." << minorVersion << "." << microVersion;
+	return versionString.str();
+}
+
+std::string Options::getVersionString64(uint64_t ver) const
+{
+	uint64_t a = (ver >> 40) & 0xFFFFFF;
+	uint64_t b = (ver >> 30) & 0x3FF;
+	uint64_t c = (ver >> 20) & 0x3FF;
+	uint64_t d = (ver >> 10) & 0x3FF;
+	uint64_t e = ver & 0x3FF;
+	std::stringstream versionString;
+	versionString << a << "." << b << "." << c << "." << d << "." << e;
+	return versionString.str();
+}
+
+std::string Options::getSDKVersionStr() const
+{
+	return getVersionString32(fSDKVersion);
+}
+
+std::string Options::getPlatformStr() const
+{
+	switch (fPlatform) {
+		case Options::kPlatformOSX:
+			return "MacOSX";
+		case Options::kPlatformiOS:
+			if (targetIOSSimulator())
+				return "iPhoneSimulator";
+			else
+				return "iPhoneOS";
+		case Options::kPlatformWatchOS:
+			if (targetIOSSimulator())
+				return "watchOS Simulator";
+			else
+				return "watchOS";
+#if SUPPORT_APPLE_TV
+		case Options::kPlatform_tvOS:
+			if (targetIOSSimulator())
+				return "AppleTVSimulator";
+			else
+				return "AppleTVOS";
+			break;
+#endif
+		case Options::kPlatformUnknown:
+			return "Unknown";
+	}
+}
+
+std::vector<std::string> Options::writeBitcodeLinkOptions() const
+{
+	std::vector<std::string> linkCommand;
+	switch ( fOutputKind ) {
+		case Options::kDynamicLibrary:
+			linkCommand.push_back("-dylib");
+			linkCommand.push_back("-compatibility_version");
+			if ( fDylibCompatVersion != 0 ) {
+				linkCommand.push_back(getVersionString32(fDylibCompatVersion));
+			} else {
+				linkCommand.push_back(getVersionString32(currentVersion32()));
+			}
+			if ( fDylibCurrentVersion != 0 ) {
+				linkCommand.push_back("-current_version");
+				linkCommand.push_back(getVersionString64(fDylibCurrentVersion));
+			}
+			linkCommand.push_back("-install_name");
+			linkCommand.push_back(installPath());
+			break;
+		case Options::kDynamicExecutable:
+			linkCommand.push_back("-execute");
+			break;
+		case Options::kObjectFile:
+			linkCommand.push_back("-r");
+			break;
+		default:
+			throwf("could not write bitcode options file output kind\n");
+	}
 
+	if (!fImplicitlyLinkPublicDylibs)
+		linkCommand.push_back("-no_implicit_dylibs");
+
+	// Add deployment target.
+	// Platform is allowed to be unknown for "ld -r".
+	switch (fPlatform) {
+		case Options::kPlatformOSX:
+			linkCommand.push_back("-macosx_version_min");
+			linkCommand.push_back(getVersionString32((unsigned)fMacVersionMin));
+			break;
+		case Options::kPlatformiOS:
+			if (targetIOSSimulator())
+				linkCommand.push_back("-ios_simulator_version_min");
+			else
+				linkCommand.push_back("-ios_version_min");
+			linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
+			break;
+		case Options::kPlatformWatchOS:
+			if (targetIOSSimulator())
+				linkCommand.push_back("-watchos_simulator_version_min");
+			else
+				linkCommand.push_back("-watchos_version_min");
+			linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
+			break;
+#if SUPPORT_APPLE_TV
+		case Options::kPlatform_tvOS:
+			if (targetIOSSimulator())
+				linkCommand.push_back("-tvos_simulator_version_min");
+			else
+				linkCommand.push_back("-tvos_version_min");
+			linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
+			break;
+#endif
+		case Options::kPlatformUnknown:
+			if ( fOutputKind != Options::kObjectFile ) {
+				throwf("platform is unknown for final bitcode bundle,"
+					   "deployment target and min version is required for -bitcode_bundle");
+			}
+			break;
+	}
+
+
+	// entry name
+	if ( fEntryName ) {
+		linkCommand.push_back("-e");
+		linkCommand.push_back(fEntryName);
+	}
+
+	// Write rpaths
+	if (!fRPaths.empty()) {
+		for (std::vector<const char*>::const_iterator it=fRPaths.begin(); it != fRPaths.end(); ++it) {
+			linkCommand.push_back("-rpath");
+			linkCommand.push_back(*it);
+		}
+	}
+
+	// Other bitcode compatiable options
+	if ( fObjCABIVersion1Override ) {
+		linkCommand.push_back("-objc_abi_version");
+		linkCommand.push_back("1");
+	} else if ( fObjCABIVersion2Override ) {
+		linkCommand.push_back("-objc_abi_version");
+		linkCommand.push_back("2");
+	}
+	if ( fExecutablePath ) {
+		linkCommand.push_back("-executable_path");
+		linkCommand.push_back(fExecutablePath);
+	}
+	if ( fDeadStrip )
+		linkCommand.push_back("-dead_strip");
+	if ( fExportDynamic )
+		linkCommand.push_back("-export_dynamic");
+	if ( fMarkAppExtensionSafe && fCheckAppExtensionSafe )
+		linkCommand.push_back("-application_extension");
+
+	if ( fSourceVersionLoadCommandForceOn )
+		linkCommand.push_back("-add_source_version");
+	if ( fSourceVersion != 0 ) {
+		linkCommand.push_back("-source_version");
+		linkCommand.push_back(getVersionString64(fSourceVersion));
+	}
+
+	// linker flag added by swift driver
+	// rdar://problem/20108072
+	if ( !fObjcCategoryMerging )
+		linkCommand.push_back("-no_objc_category_merging");
+
+	return linkCommand;
+}
 
 //
 // Process all command line arguments.
@@ -1957,15 +2232,18 @@ void Options::parse(int argc, const char* argv[])
 				if ( (fOutputKind != kObjectFile) && (fOutputKind != kKextBundle) ) {
 					fOutputKind = kStaticExecutable;
 				}
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-dylib") == 0 ) {
 				fOutputKind = kDynamicLibrary;
 			}
 			else if ( strcmp(arg, "-bundle") == 0 ) {
 				fOutputKind = kDynamicBundle;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-dylinker") == 0 ) {
 				fOutputKind = kDyld;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-execute") == 0 ) {
 				if ( fOutputKind != kStaticExecutable )
@@ -1973,12 +2251,14 @@ void Options::parse(int argc, const char* argv[])
 			}
 			else if ( strcmp(arg, "-preload") == 0 ) {
 				fOutputKind = kPreload;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-r") == 0 ) {
 				fOutputKind = kObjectFile;
 			}
 			else if ( strcmp(arg, "-kext") == 0 ) {
 				fOutputKind = kKextBundle;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-o") == 0 ) {
                 snapshotArgCount = 0;
@@ -1992,6 +2272,7 @@ void Options::parse(int argc, const char* argv[])
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
 				fUsingLazyDylibLinking = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-lto_library") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2018,18 +2299,21 @@ void Options::parse(int argc, const char* argv[])
 			// Avoid lazy binding.
 			else if ( strcmp(arg, "-bind_at_load") == 0 ) {
 				fBindAtLoad = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-twolevel_namespace") == 0 ) {
 				fNameSpace = kTwoLevelNameSpace;
 			}
 			else if ( strcmp(arg, "-flat_namespace") == 0 ) {
 				fNameSpace = kFlatNameSpace;
+				cannotBeUsedWithBitcode(arg);
 			}
 			// Also sets a bit to ensure dyld causes everything
 			// in the namespace to be flat.
 			// ??? Deprecate
 			else if ( strcmp(arg, "-force_flat_namespace") == 0 ) {
 				fNameSpace = kForceFlatNameSpace;
+				cannotBeUsedWithBitcode(arg);
 			}
 			// Similar to --whole-archive.
 			else if ( strcmp(arg, "-all_load") == 0 ) {
@@ -2070,13 +2354,16 @@ void Options::parse(int argc, const char* argv[])
                 snapshotFileArgIndex = 3;
 				parseSectionOrderFile(argv[i+1], argv[i+2], argv[i+3]);
 				i += 3;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-order_file") == 0 ) {
                 snapshotFileArgIndex = 1;
 				parseOrderFile(argv[++i], false);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-order_file_statistics") == 0 ) {
 				fPrintOrderFileStatistics = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			// ??? Deprecate segcreate.
 			// -sectcreate puts whole files into a section in the output.
@@ -2106,6 +2393,7 @@ void Options::parse(int argc, const char* argv[])
 					warning("-seg1addr not %lld byte aligned, rounding up", fSegmentAlignment);
 					fBaseAddress = temp;
 				}
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-e") == 0 ) {
 				fEntryName = argv[++i];
@@ -2120,7 +2408,8 @@ void Options::parse(int argc, const char* argv[])
 				 loadFileList(path, baseOrdinal);
 			}
 			else if ( strcmp(arg, "-keep_private_externs") == 0 ) {
-				 fKeepPrivateExterns = true;
+				cannotBeUsedWithBitcode(arg);
+				fKeepPrivateExterns = true;
 			}
 			else if ( strcmp(arg, "-final_output") == 0 ) {
 				fFinalName = argv[++i];
@@ -2137,11 +2426,13 @@ void Options::parse(int argc, const char* argv[])
 						// do nothing, -interposable_list overrides -interposable"
 						break;
 				}
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-interposable_list") == 0 ) {
                 snapshotFileArgIndex = 1;
 				fInterposeMode = kInterposeSome;
 				loadExportFile(argv[++i], "-interposable_list", fInterposeList);
+				cannotBeUsedWithBitcode(arg);
 			}
 			// Default for -interposable/-multi_module/-single_module.
 			else if ( strcmp(arg, "-single_module") == 0 ) {
@@ -2160,6 +2451,7 @@ void Options::parse(int argc, const char* argv[])
 					throw "can't use -unexported_symbols_list and -exported_symbols_list";
 				fExportMode = kDontExportSome;
 				loadExportFile(argv[++i], "-unexported_symbols_list", fDontExportSymbols);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-exported_symbol") == 0 ) {
 				if ( fExportMode == kDontExportSome )
@@ -2172,6 +2464,7 @@ void Options::parse(int argc, const char* argv[])
 					throw "can't use -unexported_symbol and -exported_symbol";
 				fExportMode = kDontExportSome;
 				fDontExportSymbols.insert(argv[++i]);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2179,6 +2472,7 @@ void Options::parse(int argc, const char* argv[])
 					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);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-non_global_symbols_strip_list") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2186,6 +2480,7 @@ void Options::parse(int argc, const char* argv[])
 					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);
+				cannotBeUsedWithBitcode(arg);
 			}
 			// ??? Deprecate
 			else if ( strcmp(arg, "-no_arch_warnings") == 0 ) {
@@ -2194,6 +2489,7 @@ void Options::parse(int argc, const char* argv[])
 			else if ( strcmp(arg, "-force_cpusubtype_ALL") == 0 ) {
 				fForceSubtypeAll = true;
 				fAllowCpuSubtypeMismatches = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			// Similar to -weak-l but uses the absolute path name to the library.
 			else if ( strcmp(arg, "-weak_library") == 0 ) {
@@ -2203,6 +2499,7 @@ void Options::parse(int argc, const char* argv[])
 				info.options.fWeakImport = true;
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-lazy_library") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2212,6 +2509,7 @@ void Options::parse(int argc, const char* argv[])
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
 				fUsingLazyDylibLinking = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-framework") == 0 ) {
                 snapshotArgCount = 0;
@@ -2235,6 +2533,7 @@ void Options::parse(int argc, const char* argv[])
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
 				fUsingLazyDylibLinking = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-search_paths_first") == 0 ) {
 				// previously handled by buildSearchPaths()
@@ -2244,6 +2543,7 @@ void Options::parse(int argc, const char* argv[])
 			}
 			else if ( strcmp(arg, "-undefined") == 0 ) {
                 setUndefinedTreatment(argv[++i]);
+				cannotBeUsedWithBitcode(arg);
 			}
 			// Debugging output flag.
 			else if ( strcmp(arg, "-arch_multiple") == 0 ) {
@@ -2261,10 +2561,12 @@ void Options::parse(int argc, const char* argv[])
 					case kWarning:
 						fWarnTextRelocs = true;
 						fAllowTextRelocs = true;
+						cannotBeUsedWithBitcode(arg);
 						break;
 					case kSuppress:
 						fWarnTextRelocs = false;
 						fAllowTextRelocs = true;
+						cannotBeUsedWithBitcode(arg);
 						break;
 					case kError:
 						fWarnTextRelocs = false;
@@ -2287,6 +2589,7 @@ void Options::parse(int argc, const char* argv[])
 			// later.  Prebinding is less useful on 10.4 and greater.
 			else if ( strcmp(arg, "-prebind") == 0 ) {
 				fPrebind = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-noprebind") == 0 ) {
 				warnObsolete(arg);
@@ -2310,6 +2613,7 @@ void Options::parse(int argc, const char* argv[])
                 // ignore for snapshot because a stub dylib will be created in the snapshot
                  snapshotArgCount = 0;
 				 addDylibOverride(argv[++i]);
+				cannotBeUsedWithBitcode(arg);
 			}
 			// What to expand @executable_path to if found in dependent dylibs
 			else if ( strcmp(arg, "-executable_path") == 0 ) {
@@ -2340,6 +2644,7 @@ void Options::parse(int argc, const char* argv[])
 					warning("alignment for -segalign %s is not a power of two, using 0x%X", size, p2aligned);
 					fSegmentAlignment = p2aligned;
 				}
+				cannotBeUsedWithBitcode(arg);
 			}
 			// Puts a specified segment at a particular address that must
 			// be a multiple of the segment alignment.
@@ -2353,15 +2658,18 @@ void Options::parse(int argc, const char* argv[])
 				if ( seg.address != temp )
 					warning("-segaddr %s not %lld byte aligned", seg.name, fSegmentAlignment);
 				fCustomSegmentAddresses.push_back(seg);
+				cannotBeUsedWithBitcode(arg);
 			}
 			// ??? Deprecate when we deprecate split-seg.
 			else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
 				fBaseAddress = parseAddress(argv[++i]);
+				cannotBeUsedWithBitcode(arg);
 			}
 			// ??? Deprecate when we deprecate split-seg.
 			else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
 				fBaseWritableAddress = parseAddress(argv[++i]);
 				fSplitSegs = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			// ??? Deprecate when we get rid of basing at build time.
 			else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
@@ -2370,6 +2678,7 @@ void Options::parse(int argc, const char* argv[])
 				if ( name == NULL )
 					throw "-seg_addr_table missing argument";
 				fSegAddrTablePath = name;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
 				warnObsolete(arg);
@@ -2383,6 +2692,7 @@ void Options::parse(int argc, const char* argv[])
 				seg.max = parseProtection(argv[++i]);
 				seg.init = parseProtection(argv[++i]);
 				fCustomSegmentProtections.push_back(seg);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-pagezero_size") == 0 ) {
 				 const char* size = argv[++i];
@@ -2393,12 +2703,14 @@ void Options::parse(int argc, const char* argv[])
 				if ( (fZeroPageSize != temp)  )
 					warning("-pagezero_size not page aligned, rounding down");
 				 fZeroPageSize = temp;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-stack_addr") == 0 ) {
 				 const char* address = argv[++i];
 				 if ( address == NULL )
 					throw "-stack_addr missing <address>";
 				fStackAddr = parseAddress(address);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-stack_size") == 0 ) {
 				 const char* size = argv[++i];
@@ -2411,15 +2723,18 @@ void Options::parse(int argc, const char* argv[])
 			}
 			else if ( strcmp(arg, "-allow_stack_execute") == 0 ) {
 				fExecutableStack = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-allow_heap_execute") == 0 ) {
 				fDisableNonExecutableHeap = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			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;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-sectorder_detail") == 0 ) {
 				warnObsolete(arg);
@@ -2475,6 +2790,24 @@ void Options::parse(int argc, const char* argv[])
 				setIOSVersionMin(argv[++i]);
 				fTargetIOSSimulator = true;
 			}
+			else if ( strcmp(arg, "-watchos_version_min") == 0 ) {
+				setWatchOSVersionMin(argv[++i]);
+			}
+			else if ( strcmp(arg, "-watchos_simulator_version_min") == 0 ) {
+				setWatchOSVersionMin(argv[++i]);
+				fTargetIOSSimulator = true;
+			}
+	#if SUPPORT_APPLE_TV
+			else if ( strcmp(arg, "-tvos_version_min") == 0 ) {
+				setIOSVersionMin(argv[++i]);
+				fPlatform = kPlatform_tvOS;
+			}
+			else if ( strcmp(arg, "-tvos_simulator_version_min") == 0 ) {
+				setIOSVersionMin(argv[++i]);
+				fPlatform = kPlatform_tvOS;
+				fTargetIOSSimulator = true;
+			}
+	#endif
 			else if ( strcmp(arg, "-multiply_defined") == 0 ) {
 				//warnObsolete(arg);
 				++i;
@@ -2515,12 +2848,14 @@ void Options::parse(int argc, const char* argv[])
 				if ( name == NULL )
 					throw "-u missing argument";
 				fInitialUndefines.push_back(name);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-U") == 0 ) {
 				const char* name = argv[++i];
 				if ( name == NULL )
 					throw "-U missing argument";
 				fAllowedUndefined.insert(name);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-s") == 0 ) {
 				warnObsolete(arg);
@@ -2573,9 +2908,15 @@ void Options::parse(int argc, const char* argv[])
 				if ( size == NULL )
 					throw "-headerpad missing argument";
 				 fMinimumHeaderPad = parseAddress(size);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-headerpad_max_install_names") == 0 ) {
-				fMaxMinimumHeaderPad = true;
+				// ignore -headerpad_max_install_names when compiling with bitcode
+				// rdar://problem/20748962
+				if ( fBundleBitcode )
+					warning("-headerpad_max_install_names is ignored when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)");
+				else
+					fMaxMinimumHeaderPad = true;
 			}
 			else if ( strcmp(arg, "-t") == 0 ) {
 				fLogAllFiles = true;
@@ -2592,6 +2933,7 @@ void Options::parse(int argc, const char* argv[])
 				if ( name == NULL )
 					throw "-umbrella missing argument";
 				fUmbrellaName = name;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-allowable_client") == 0 ) {
 				const char* name = argv[++i];
@@ -2600,6 +2942,7 @@ void Options::parse(int argc, const char* argv[])
 					throw "-allowable_client missing argument";
 
 				fAllowableClients.push_back(name);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-client_name") == 0 ) {
 				const char* name = argv[++i];
@@ -2608,30 +2951,35 @@ void Options::parse(int argc, const char* argv[])
 					throw "-client_name missing argument";
 
 				fClientName = name;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-sub_umbrella") == 0 ) {
 				const char* name = argv[++i];
 				if ( name == NULL )
 					throw "-sub_umbrella missing argument";
 				 fSubUmbellas.push_back(name);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-sub_library") == 0 ) {
 				const char* name = argv[++i];
 				if ( name == NULL )
 					throw "-sub_library missing argument";
 				 fSubLibraries.push_back(name);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-init") == 0 ) {
 				const char* name = argv[++i];
 				if ( name == NULL )
 					throw "-init missing argument";
 				fInitFunctionName = name;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-dot") == 0 ) {
 				const char* name = argv[++i];
 				if ( name == NULL )
 					throw "-dot missing argument";
 				fDotOutputFile = name;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-warn_commons") == 0 ) {
 				fWarnCommons = true;
@@ -2665,11 +3013,17 @@ void Options::parse(int argc, const char* argv[])
 				++i;
 				// previously handled by buildSearchPaths()
 			}
+			else if ( strcmp(arg, "-bitcode_bundle") == 0 ) {
+				snapshotArgCount = 0;
+				// previously handled by buildSearchPaths()
+			}
 			else if ( strcmp(arg, "-no_uuid") == 0 ) {
 				fUUIDMode = kUUIDNone;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-random_uuid") == 0 ) {
 				fUUIDMode = kUUIDRandom;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-dtrace") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2677,6 +3031,7 @@ void Options::parse(int argc, const char* argv[])
 				if ( name == NULL )
 					throw "-dtrace missing argument";
 				fDtraceScriptName = name;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-root_safe") == 0 ) {
 				fRootSafe = true;
@@ -2693,14 +3048,45 @@ void Options::parse(int argc, const char* argv[])
 				if ( pair.alias == NULL )
 					throw "missing argument to -alias";
 				fAliases.push_back(pair);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-alias_list") == 0 ) {
                 snapshotFileArgIndex = 1;
 				parseAliasFile(argv[++i]);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-save-temps") == 0 ) {
 				fSaveTempFiles = true;
 			}
+			else if ( strcmp(arg, "-bitcode_hide_symbols") == 0 ) {
+				fHideSymbols = true;
+				if ( !fBundleBitcode )
+					warning("-bitcode_hide_symbols is ignored without -bitcode_bundle");
+			}
+			else if ( strcmp(arg, "-bitcode_symbol_map") == 0) {
+				fReverseMapPath = argv[++i];
+				if ( fReverseMapPath == NULL )
+					throw "missing argument to -bitcode_symbol_map";
+				struct stat statbuf;
+				::stat(fReverseMapPath, &statbuf);
+				if (S_ISDIR(statbuf.st_mode)) {
+					char tempPath[PATH_MAX];
+					sprintf(tempPath, "%s/XXXXXX", fReverseMapPath);
+					int tempFile = ::mkstemp(tempPath);
+					if (tempFile == -1)
+						throwf("could not write file to symbol map directory: %s", fReverseMapPath);
+					::close(tempFile);
+					fReverseMapTempPath = std::string(tempPath);
+					fReverseMapUUIDRename = true;
+				} else
+					fReverseMapTempPath = std::string(fReverseMapPath);
+			}
+			else if ( strcmp(argv[i], "-flto-codegen-only") == 0) {
+				fLTOCodegenOnly = true;
+			}
+			else if ( strcmp(argv[i], "-ignore_auto_link") == 0) {
+				fIgnoreAutoLink = true;
+			}
 			else if ( strcmp(arg, "-rpath") == 0 ) {
 				const char* path = argv[++i];
 				if ( path == NULL )
@@ -2724,6 +3110,7 @@ void Options::parse(int argc, const char* argv[])
 			}
 			else if ( strcmp(arg, "-no_pie") == 0 ) {
 				fDisablePositionIndependentExecutable = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2732,6 +3119,7 @@ void Options::parse(int argc, const char* argv[])
 				info.options.fReExport = true;
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-reexport_library") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2740,6 +3128,7 @@ void Options::parse(int argc, const char* argv[])
 				info.options.fReExport = true;
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-reexport_framework") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2748,6 +3137,7 @@ void Options::parse(int argc, const char* argv[])
 				info.options.fReExport = true;
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strncmp(arg, "-upward-l", 9) == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2756,6 +3146,7 @@ void Options::parse(int argc, const char* argv[])
 				info.options.fUpward = true;
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-upward_library") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2764,6 +3155,7 @@ void Options::parse(int argc, const char* argv[])
 				info.options.fUpward = true;
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-upward_framework") == 0 ) {
                 // SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
@@ -2772,9 +3164,11 @@ void Options::parse(int argc, const char* argv[])
 				info.options.fUpward = true;
 				info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
 				addLibrary(info);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-dead_strip_dylibs") == 0 ) {
 				fDeadStripDylibs = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_implicit_dylibs") == 0 ) {
 				fImplicitlyLinkPublicDylibs = false;
@@ -2783,28 +3177,38 @@ void Options::parse(int argc, const char* argv[])
 				// ignore
 			}
 			else if ( strcmp(arg, "-no_encryption") == 0 ) {
-				fEncryptable = false;
+				fEncryptableForceOff = true;
+				cannotBeUsedWithBitcode(arg);
+			}
+			else if ( strcmp(arg, "-encryptable") == 0 ) {
+				fEncryptableForceOn = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_compact_unwind") == 0 ) {
 				fAddCompactUnwindEncoding = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-mllvm") == 0 ) {
 				const char* opts = argv[++i];
 				if ( opts == NULL )
 					throw "missing argument to -mllvm";
 				fLLVMOptions.push_back(opts);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-mcpu") == 0 ) {
 				const char* cpu = argv[++i];
 				if ( cpu == NULL )
 					throw "missing argument to -mcpu";
 				fLtoCpu = cpu;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_order_inits") == 0 ) {
 				fAutoOrderInitializers = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_order_data") == 0 ) {
 				fOrderData = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-seg_page_size") == 0 ) {
 				SegmentSize seg;
@@ -2816,31 +3220,38 @@ void Options::parse(int argc, const char* argv[])
 				if ( (seg.size != temp)  )
 					warning("-seg_page_size %s not 4K aligned, rounding down", seg.name);
 				fCustomSegmentSizes.push_back(seg);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-mark_dead_strippable_dylib") == 0 ) {
 				fMarkDeadStrippableDylib = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-exported_symbols_order") == 0 ) {
                 snapshotFileArgIndex = 1;
 				loadSymbolOrderFile(argv[++i], fExportSymbolsOrder);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_compact_linkedit") == 0 ) {
 				warnObsolete("-no_compact_linkedit");
 			}
 			else if ( strcmp(arg, "-no_eh_labels") == 0 ) {
 				fNoEHLabels = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-warn_compact_unwind") == 0 ) {
 				fWarnCompactUnwind = true;
 			}
 			else if ( strcmp(arg, "-allow_sub_type_mismatches") == 0 ) {
 				fAllowCpuSubtypeMismatches = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
 				fOptimizeZeroFill = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-merge_zero_fill_sections") == 0 ) {
 				fMergeZeroFill = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
 				const char* version = argv[++i];
@@ -2862,6 +3273,7 @@ void Options::parse(int argc, const char* argv[])
 			}
 			else if ( strcmp(arg, "-objc_gc_compaction") == 0 ) {
 				fObjcGcCompaction = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-objc_gc") == 0 ) {
 				fObjCGc = true;
@@ -2869,6 +3281,7 @@ void Options::parse(int argc, const char* argv[])
 					warning("-objc_gc overriding -objc_gc_only");
 					fObjCGcOnly = false;	
 				}
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
 				fObjCGcOnly = true;
@@ -2876,6 +3289,7 @@ void Options::parse(int argc, const char* argv[])
 					warning("-objc_gc_only overriding -objc_gc");
 					fObjCGc = false;	
 				}
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-demangle") == 0 ) {
 				fDemangle = true;
@@ -2887,6 +3301,7 @@ void Options::parse(int argc, const char* argv[])
 			else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
 				fVersionLoadCommandForcedOff = true;
 				fVersionLoadCommandForcedOn = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-function_starts") == 0 ) {
 				fFunctionStartsForcedOn = true;
@@ -2895,10 +3310,12 @@ void Options::parse(int argc, const char* argv[])
 			else if ( strcmp(arg, "-no_function_starts") == 0 ) {
 				fFunctionStartsForcedOff = true;
 				fFunctionStartsForcedOn = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_data_in_code_info") == 0 ) {
 				fDataInCodeInfoLoadCommandForcedOff = true;
 				fDataInCodeInfoLoadCommandForcedOn = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-data_in_code_info") == 0 ) {
 				fDataInCodeInfoLoadCommandForcedOn  = true;
@@ -2915,22 +3332,26 @@ void Options::parse(int argc, const char* argv[])
 			else if ( strcmp(arg, "-force_symbols_weak_list") == 0 ) {
                 snapshotFileArgIndex = 1;
 				loadExportFile(argv[++i], "-force_symbols_weak_list", fForceWeakSymbols);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-force_symbols_not_weak_list") == 0 ) {
                 snapshotFileArgIndex = 1;
 				loadExportFile(argv[++i], "-force_symbols_not_weak_list", fForceNotWeakSymbols);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-force_symbol_weak") == 0 ) {
 				const char* symbol = argv[++i];
 				if ( symbol == NULL )
 					throw "-force_symbol_weak missing <symbol>";
 				fForceWeakSymbols.insert(symbol);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-force_symbol_not_weak") == 0 ) {
 				const char* symbol = argv[++i];
 				if ( symbol == NULL )
 					throw "-force_symbol_not_weak missing <symbol>";
 				fForceNotWeakSymbols.insert(symbol);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-reexported_symbols_list") == 0 ) {
                 snapshotFileArgIndex = 1;
@@ -2945,13 +3366,16 @@ void Options::parse(int argc, const char* argv[])
 				if ( strchr(envarg, '=') == NULL )
 					throw "-dyld_env missing ENV=VALUE";
 				fDyldEnvironExtras.push_back(envarg);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-page_align_data_atoms") == 0 ) {
 				fPageAlignDataAtoms = true;
+				cannotBeUsedWithBitcode(arg);
 			} 
 			else if (strcmp(arg, "-debug_snapshot") == 0) {
                 fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
                 fSnapshotRequested = true;
+				cannotBeUsedWithBitcode(arg);
             }
  			else if (strcmp(arg, "-snapshot_dir") == 0) {
 				const char* path = argv[++i];
@@ -2960,12 +3384,15 @@ void Options::parse(int argc, const char* argv[])
 				fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_DEBUG);
 				fLinkSnapshot.setSnapshotPath(path);
 				fSnapshotRequested = true;
+				cannotBeUsedWithBitcode(arg);
             }
 			else if ( strcmp(arg, "-new_main") == 0 ) {
 				fEntryPointLoadCommandForceOn = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_new_main") == 0 ) {
 				fEntryPointLoadCommandForceOff = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-source_version") == 0 ) {
 				 const char* vers = argv[++i];
@@ -2978,6 +3405,7 @@ void Options::parse(int argc, const char* argv[])
 			}
 			else if ( strcmp(arg, "-no_source_version") == 0 ) {
 				fSourceVersionLoadCommandForceOff = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-sdk_version") == 0 ) {
 				 const char* vers = argv[++i];
@@ -2986,13 +3414,14 @@ void Options::parse(int argc, const char* argv[])
 				fSDKVersion = parseVersionNumber32(vers);
 			}
 			else if ( strcmp(arg, "-dependent_dr_info") == 0 ) {
-				fDependentDRInfoForcedOn = true;
+				warnObsolete(arg);
 			}
 			else if ( strcmp(arg, "-no_dependent_dr_info") == 0 ) {
-				fDependentDRInfoForcedOff = true;
+				warnObsolete(arg);
 			}
 			else if ( strcmp(arg, "-kexts_use_stubs") == 0 ) {
 				fKextsUseStubs = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
                 snapshotArgCount = 0;
@@ -3027,23 +3456,28 @@ void Options::parse(int argc, const char* argv[])
 					}
 				}
 				fLinkerOptions.push_back(opts);
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-allow_simulator_linking_to_macosx_dylibs") == 0 ) {
 				fAllowSimulatorToLinkWithMacOSX = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-keep_dwarf_unwind") == 0 ) {
 				fKeepDwarfUnwindForcedOn = true;
 				fKeepDwarfUnwindForcedOff = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_keep_dwarf_unwind") == 0 ) {
 				fKeepDwarfUnwindForcedOn = false;
 				fKeepDwarfUnwindForcedOff = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-verbose_optimization_hints") == 0 ) {
 				fVerboseOptimizationHints = true;
 			}
 			else if ( strcmp(arg, "-ignore_optimization_hints") == 0 ) {
 				fIgnoreOptimizationHints = true;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-no_dtrace_dof") == 0 ) {
 				fGenerateDtraceDOF = false;
@@ -3053,30 +3487,35 @@ void Options::parse(int argc, const char* argv[])
 					throw "-rename_section missing <segment> <section> <segment> <section>";
 				addSectionRename(argv[i+1], argv[i+2], argv[i+3], argv[i+4]);
 				i += 4;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-rename_segment") == 0 ) {
 				 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
 					throw "-rename_segment missing <existing-segment> <new-segment>";
 				addSegmentRename(argv[i+1], argv[i+2]);
 				i += 2;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-move_to_ro_segment") == 0 ) {
 				 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
 					throw "-move_to_ro_segment missing <segment> <symbol-list-file>";
 				addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesCode, "-move_to_ro_segment");
 				i += 2;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-move_to_rw_segment") == 0 ) {
 				 if ( (argv[i+1]==NULL) || (argv[i+2]==NULL) )
 					throw "-move_to_rw_segment missing <segment> <symbol-list-file>";
 				addSymbolMove(argv[i+1], argv[i+2], fSymbolsMovesData, "-move_to_rw_segment");
 				i += 2;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-trace_symbol_layout") == 0 ) {
 				fTraceSymbolLayout = true;
 			}
 			else if ( strcmp(arg, "-no_branch_islands") == 0 ) {
 				fAllowBranchIslands = false;
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-segment_order") == 0 ) {
 				// ex: -segment_order __TEXT:__DATA:__JUNK
@@ -3099,6 +3538,7 @@ void Options::parse(int argc, const char* argv[])
 						break;
 					}
 				}
+				cannotBeUsedWithBitcode(arg);
 			}
 			else if ( strcmp(arg, "-section_order") == 0 ) {
 				// ex: -section_order __DATA  __data:__const:__nl_pointers
@@ -3126,6 +3566,7 @@ void Options::parse(int argc, const char* argv[])
 						break;
 					}
 				}
+				cannotBeUsedWithBitcode(arg);
 			}			
 			else if ( strcmp(arg, "-application_extension") == 0 ) {
 				fMarkAppExtensionSafe = true;
@@ -3144,6 +3585,25 @@ void Options::parse(int argc, const char* argv[])
 			else if ( strcmp(arg, "-force_load_swift_libs") == 0 ) {
 				fForceLoadSwiftLibs = true;
 			}
+			else if ( strcmp(arg, "-not_for_dyld_shared_cache") == 0 ) {
+				fSharedRegionEligibleForceOff = true;
+				cannotBeUsedWithBitcode(arg);
+			}
+			else if ( strcmp(arg, "-dirty_data_list") == 0 ) {
+				 if ( argv[i+1] == NULL )
+					throw "-dirty_data_list missing <symbol-list-file>";
+				addSymbolMove("__DATA_DIRTY", argv[i+1], fSymbolsMovesData, "-dirty_data_list");
+				++i;
+				cannotBeUsedWithBitcode(arg);
+			}
+			else if ( strcmp(arg, "-data_const") == 0 ) {
+				fUseDataConstSegmentForceOn = true;
+				cannotBeUsedWithBitcode(arg);
+			}
+			else if ( strcmp(arg, "-no_data_const") == 0 ) {
+				fUseDataConstSegmentForceOff = true;
+				cannotBeUsedWithBitcode(arg);
+			}
 			// put this last so that it does not interfer with other options starting with 'i'
 			else if ( strncmp(arg, "-i", 2) == 0 ) {
 				const char* colon = strchr(arg, ':');
@@ -3291,6 +3751,9 @@ void Options::buildSearchPaths(int argc, const char* argv[])
 				throw "-dependency_info missing <path>";
 			fDependencyInfoPath = path;
 		}
+		else if ( strcmp(argv[i], "-bitcode_bundle") == 0 ) {
+			fBundleBitcode = true;
+		}
 	}
 	int standardLibraryPathsStartIndex = libraryPaths.size();
 	int standardFrameworkPathsStartIndex = frameworkPaths.size();
@@ -3544,21 +4007,20 @@ void Options::reconfigureDefaults()
 	}
 
 	// set default min OS version
-	if ( (fMacVersionMin == ld::macVersionUnset)
-		&& (fIOSVersionMin == ld::iOSVersionUnset) ) {
+	if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fWatchOSVersionMin == ld::wOSVersionUnset) ) {
 		// if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
 		const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
 		const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
 		const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
-		const char* iOSSimulatorVers = getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET");
-		if ( macVers != NULL ) 
+		const char* wOSVers = getenv("WATCHOS_DEPLOYMENT_TARGET");
+		if ( macVers != NULL )
 			setMacOSXVersionMin(macVers);
 		else if ( iPhoneVers != NULL )
 			setIOSVersionMin(iPhoneVers);
 		else if ( iOSVers != NULL )
 			setIOSVersionMin(iOSVers);
-		else if ( iOSSimulatorVers != NULL )
-			setIOSVersionMin(iOSSimulatorVers);
+		else if ( wOSVers != NULL )
+			setWatchOSVersionMin(wOSVers);
 		else {
 			// if still nothing, set default based on architecture
 			switch ( fArchitecture ) {
@@ -3570,7 +4032,7 @@ void Options::reconfigureDefaults()
 						setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
 			#else
 						warning("-macosx_version_min not specified, assuming 10.6");
-						fMacVersionMin = ld::mac10_6;
+						setMacOSXVersionMin("10.6");
 			#endif		
 					}
 					break;
@@ -3580,8 +4042,14 @@ void Options::reconfigureDefaults()
 						warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
 						setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
 			#else
-						warning("-ios_version_min not specified, assuming 6.0");
-						setIOSVersionMin("6.0");
+						if ( fSubArchitecture == CPU_SUBTYPE_ARM_V7K ) {
+							warning("-watchos_version_min not specified, assuming 2.0");
+							setWatchOSVersionMin("2.0");
+						}
+						else {
+							warning("-ios_version_min not specified, assuming 6.0");
+							setIOSVersionMin("6.0");
+						}
 			#endif
 					}
 					break;
@@ -3596,19 +4064,19 @@ void Options::reconfigureDefaults()
 	// adjust min based on architecture
 	switch ( fArchitecture ) {
 		case CPU_TYPE_I386:
-			if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
+			if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
 				//warning("-macosx_version_min should be 10.4 or later for i386");
 				fMacVersionMin = ld::mac10_4;
 			}
 			break;
 		case CPU_TYPE_X86_64:
-			if ( (fMacVersionMin < ld::mac10_4) && (fIOSVersionMin == ld::iOSVersionUnset) ) {
+			if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
 				//warning("-macosx_version_min should be 10.4 or later for x86_64");
 				fMacVersionMin = ld::mac10_4;
 			}
 			break;
 		case CPU_TYPE_ARM64:
-			if ( fIOSVersionMin < ld::iOS_7_0 ) {
+			if ( (fPlatform == kPlatformiOS) && (fIOSVersionMin < ld::iOS_7_0) ) {
 				//warning("-mios_version_min should be 7.0 or later for arm64");
 				fIOSVersionMin = ld::iOS_7_0;
 			}
@@ -3661,12 +4129,12 @@ void Options::reconfigureDefaults()
 				fUndefinedTreatment = kUndefinedDynamicLookup;
 				break;
 			case CPU_TYPE_ARM:
-				if ( fIOSVersionMin >= ld::iOS_5_0 ) {
+				if ( min_iOS(ld::iOS_5_0) ) {
                     // iOS 5.0 and later use new MH_KEXT_BUNDLE type
                     fMakeCompressedDyldInfo = false;
                     fMakeCompressedDyldInfoForceOff = true;
 					// kexts are PIC in iOS 6.0 and later
-					fAllowTextRelocs = (fIOSVersionMin < ld::iOS_6_0);
+					fAllowTextRelocs = !min_iOS(ld::iOS_6_0);
 					fKextsUseStubs = !fAllowTextRelocs;
                     fUndefinedTreatment = kUndefinedDynamicLookup;
 					break;
@@ -3841,7 +4309,7 @@ void Options::reconfigureDefaults()
 	// determine if info for shared region should be added
 	if ( fOutputKind == Options::kDynamicLibrary ) {
 		if ( minOS(ld::mac10_5, ld::iOS_3_1) )
-			if ( !fPrebind )
+			if ( !fPrebind && !fSharedRegionEligibleForceOff )
 				if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0)
 					|| (strncmp(this->installPath(), "/System/Library/", 16) == 0) )
 					fSharedRegionEligible = true;
@@ -3850,7 +4318,41 @@ void Options::reconfigureDefaults()
         // <rdar://problem/10111122> Enable dyld to be put into the dyld shared cache
         fSharedRegionEligible = true;
 	}
-    
+
+	// <rdar://problem/18719327> warn if -rpath is used with OS dylibs
+	if ( fSharedRegionEligible && !fRPaths.empty() ) 
+		warning("-rpath cannot be used with dylibs that will be in the dyld shared cache");
+
+	// automatically use __DATA_CONST in iOS dylibs
+	if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0) && !fUseDataConstSegmentForceOff ) {
+		fUseDataConstSegment = true;
+	}
+	if ( fUseDataConstSegmentForceOn ) {
+		fUseDataConstSegment = true;
+	}
+	if ( fUseDataConstSegment ) {
+		addSectionRename("__DATA", "__got",				"__DATA_CONST", "__got");
+		addSectionRename("__DATA", "__la_symbol_ptr",	"__DATA_CONST", "__la_symbol_ptr");
+		addSectionRename("__DATA", "__nl_symbol_ptr",	"__DATA_CONST", "__nl_symbol_ptr");
+		addSectionRename("__DATA", "__const",			"__DATA_CONST", "__const");
+		addSectionRename("__DATA", "__cfstring",		"__DATA_CONST", "__cfstring");
+		addSectionRename("__DATA", "__mod_init_func",   "__DATA_CONST", "__mod_init_func");
+		addSectionRename("__DATA", "__mod_term_func",   "__DATA_CONST", "__mod_term_func");
+		addSectionRename("__DATA", "__objc_classlist",  "__DATA_CONST", "__objc_classlist");
+		addSectionRename("__DATA", "__objc_nlclslist",	"__DATA_CONST", "__objc_nlclslist");
+		addSectionRename("__DATA", "__objc_catlist",	"__DATA_CONST", "__objc_catlist");
+		addSectionRename("__DATA", "__objc_nlcatlist",	"__DATA_CONST", "__objc_nlcatlist");
+		addSectionRename("__DATA", "__objc_protolist",	"__DATA_CONST", "__objc_protolist");
+		addSectionRename("__DATA", "__objc_imageinfo",	"__DATA_CONST", "__objc_imageinfo");
+		addSectionRename("__DATA", "__objc_const",	    "__DATA_CONST", "__objc_const");
+	}
+	
+	// Use V2 shared cache info when targetting newer OSs
+	if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0)) {
+		fSharedRegionEncodingV2 = true;
+		fIgnoreOptimizationHints = true;
+	}
+
 	// figure out if module table is needed for compatibility with old ld/dyld
 	if ( fOutputKind == Options::kDynamicLibrary ) {
 		switch ( fArchitecture ) {
@@ -3935,12 +4437,16 @@ void Options::reconfigureDefaults()
 		case Options::kDynamicLibrary:
 		case Options::kDynamicBundle:
 			// <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
-			if ( fIOSVersionMin < ld::iOS_8_0 )
+			if ( !min_iOS(ld::iOS_7_0) )
 				fEncryptable = false;
 			break;
 	}
 	if ( (fArchitecture != CPU_TYPE_ARM) && (fArchitecture != CPU_TYPE_ARM64) )
 		fEncryptable = false;
+	if ( fEncryptableForceOn )
+		fEncryptable = true;
+	else if ( fEncryptableForceOff )
+		fEncryptable = false;
 
 	// don't move inits in dyld because dyld wants certain
 	// entries point at stable locations at the start of __text
@@ -4045,7 +4551,7 @@ void Options::reconfigureDefaults()
 	if ( (fArchitecture == CPU_TYPE_ARM) 
 		&& fArchSupportsThumb2
 		&& (fOutputKind == kDynamicExecutable) 
-		&& (fIOSVersionMin >= ld::iOS_4_3) ) {
+		&& min_iOS(ld::iOS_4_3) ) {
 			fPositionIndependentExecutable = true;
 	}
 
@@ -4086,7 +4592,10 @@ void Options::reconfigureDefaults()
 	if ( fMacVersionMin >= ld::mac10_7 ) {
 		fTLVSupport = true;
 	}
-	else if ( (fArchitecture == CPU_TYPE_ARM64) && (fIOSVersionMin >= ld::iOS_8_0) ) {
+	else if ( (fArchitecture == CPU_TYPE_ARM64) && min_iOS(ld::iOS_8_0) ) {
+		fTLVSupport = true;
+	}
+	else if ( (fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_9_0) ) {
 		fTLVSupport = true;
 	}
 
@@ -4208,35 +4717,7 @@ void Options::reconfigureDefaults()
 			fSourceVersionLoadCommand = false;
 			break;
 	}
-	
-	
-	// add LC_DYLIB_CODE_SIGN_DRS
-	switch ( fOutputKind ) {
-		case Options::kDynamicExecutable:
-		case Options::kDynamicLibrary:
-		case Options::kDynamicBundle:
-			if ( fDependentDRInfoForcedOn ) {
-				fDependentDRInfo = true;
-			}
-			else if ( fDependentDRInfoForcedOff ) {
-				fDependentDRInfo = false;
-			}
-			else {
-				if ( minOS(ld::mac10_8, ld::iOS_6_0) ) 
-					fDependentDRInfo = true;
-				else
-					fDependentDRInfo = false;
-			}
-			break;
-		case Options::kKextBundle:
-		case Options::kDyld:
-		case Options::kStaticExecutable:
-		case Options::kObjectFile:
-		case Options::kPreload:
-			fDependentDRInfo = false;
-			break;
-	}
-	
+
 	// if -sdk_version not on command line, infer from -syslibroot
 	if ( (fSDKVersion == 0) && (fSDKPaths.size() > 0) ) {
 		const char* sdkPath = fSDKPaths.front();
@@ -4275,9 +4756,7 @@ void Options::reconfigureDefaults()
 	// allow trie based absolute symbols if targeting new enough OS
 	if ( fMakeCompressedDyldInfo ) {
 		if ( minOS(ld::mac10_9, ld::iOS_7_0) ) {
-			// <rdar://problem/13179029> Allow absolute symbols in export trie for device but not simulator
-			if ( !fTargetIOSSimulator ) 
-				fAbsoluteSymbols = true;
+			fAbsoluteSymbols = true;
 		}
 	}
 	
@@ -4299,15 +4778,14 @@ void Options::reconfigureDefaults()
 			case Options::kDynamicBundle:
 			case Options::kDyld:
 				if ( (fArchitecture == CPU_TYPE_ARM64) 
-				|| ((fArchitecture == CPU_TYPE_ARM) && (fIOSVersionMin >= ld::iOS_8_0) && 
-					((fSubArchitecture == CPU_SUBTYPE_ARM_V7S) || (fSubArchitecture == CPU_SUBTYPE_ARM_V7))) ) {
+				|| ((fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_7_0)) ) {
 					fSegmentAlignment = 4096*4;
 				}
 				break;
 			case Options::kStaticExecutable:
 			case Options::kKextBundle:
 				// <rdar://problem/14676611> 16KB segments for arm64 kexts
-				if ( (fArchitecture == CPU_TYPE_ARM64) && (fIOSVersionMin >= ld::iOS_9_0) ) {
+				if ( (fArchitecture == CPU_TYPE_ARM64) && min_iOS(ld::iOS_9_0) ) {
 					fSegmentAlignment = 4096*4;
 				}
 				break;
@@ -4353,6 +4831,21 @@ void Options::reconfigureDefaults()
 		fBaseAddress = alignedBaseAddress;
 	}
 
+	// If -dirty_data_list not specified, look in $SDKROOT/AppleInternal/DirtyDataFiles/<dylib>.dirty for dirty data list
+	if ( fSymbolsMovesData.empty() && fUseDataConstSegment && ( fDylibInstallName != NULL) && !fSDKPaths.empty() ) {
+		const char* dylibLeaf = strrchr(fDylibInstallName, '/');
+		if ( dylibLeaf ) {
+			char path[PATH_MAX];
+			strlcpy(path , fSDKPaths.front(), sizeof(path));
+			strlcat(path , "/AppleInternal/DirtyDataFiles", sizeof(path));
+			strlcat(path , dylibLeaf, sizeof(path));
+			strlcat(path , ".dirty", sizeof(path));
+			FileInfo info;
+			if ( info.checkFileExists(*this, path) )
+				addSymbolMove("__DATA_DIRTY", path, fSymbolsMovesData, "-dirty_data_list");
+		}
+	}
+
 }
 
 void Options::checkIllegalOptionCombinations()
@@ -4798,8 +5291,9 @@ void Options::checkIllegalOptionCombinations()
 		throw "-segment_order can only used used with -preload output";
 
 	// <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
+	// <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or laterÓ when building XCTest?
 	if ( (fOutputKind == Options::kDynamicLibrary) && (fIOSVersionMin != ld::iOSVersionUnset) && (fDylibInstallName != NULL) ) {
-		if ( (fIOSVersionMin < ld::iOS_8_0) && (fDylibInstallName[0] == '@') ) 
+		if ( !min_iOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff )
 			warning("embedded dylibs/frameworks only run on iOS 8 or later");
 	}
 }	
@@ -4937,14 +5431,28 @@ const char* Options::demangleSymbol(const char* sym) const
 	if ( !fDemangle )
 		return sym;
 
+	static size_t size = 1024;
+	static char* buff = (char*)malloc(size);
+	
+#if DEMANGLE_SWIFT
+	// only try to demangle symbols that look like Swift symbols
+	if ( strncmp(sym, "__T", 3) == 0 ) {
+		size_t demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
+		if ( demangledSize > size ) {
+			size = demangledSize+2;
+			buff = (char*)realloc(buff, size);
+			demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
+		}
+		if ( demangledSize != 0 )
+			return buff;
+	}
+#endif
+
 	// only try to demangle symbols that look like C++ symbols
 	if ( strncmp(sym, "__Z", 3) != 0 )
 		return sym;
 
-	static size_t size = 1024;
-	static char* buff = (char*)malloc(size);
 	int status;
-	
 	char* result = abi::__cxa_demangle(&sym[1], buff, &size, &status); 
 	if ( result != NULL ) {
 		// if demangling successful, keep buffer for next demangle
diff --git a/src/ld/Options.h b/src/ld/Options.h
index 39ee6fe..bc70e7f 100644
--- a/src/ld/Options.h
+++ b/src/ld/Options.h
@@ -35,6 +35,7 @@
 
 #include "ld.hpp"
 #include "Snapshot.h"
+#include "MachOFileAbstraction.hpp"
 
 extern void throwf (const char* format, ...) __attribute__ ((noreturn,format(printf, 1, 2)));
 extern void warning(const char* format, ...) __attribute__((format(printf, 1, 2)));
@@ -86,6 +87,46 @@ public:
 	enum UUIDMode { kUUIDNone, kUUIDRandom, kUUIDContent };
 	enum LocalSymbolHandling { kLocalSymbolsAll, kLocalSymbolsNone, kLocalSymbolsSelectiveInclude, kLocalSymbolsSelectiveExclude };
 	enum DebugInfoStripping { kDebugInfoNone, kDebugInfoMinimal, kDebugInfoFull };
+#if SUPPORT_APPLE_TV
+	enum Platform { kPlatformUnknown, kPlatformOSX, kPlatformiOS, kPlatformWatchOS, kPlatform_tvOS };
+#else
+	enum Platform { kPlatformUnknown, kPlatformOSX, kPlatformiOS, kPlatformWatchOS };
+#endif
+
+	static Platform platformForLoadCommand(uint32_t lc) {
+		switch (lc) {
+			case LC_VERSION_MIN_MACOSX:
+				return kPlatformOSX;
+			case LC_VERSION_MIN_IPHONEOS:
+				return kPlatformiOS;
+			case LC_VERSION_MIN_WATCHOS:
+				return kPlatformWatchOS;
+		#if SUPPORT_APPLE_TV
+			case LC_VERSION_MIN_TVOS:
+				return kPlatform_tvOS;
+		#endif
+		}
+		assert(!lc && "unknown LC_VERSION_MIN load command");
+		return kPlatformUnknown;
+	}
+
+	static const char* platformName(Platform platform) {
+		switch (platform) {
+			case kPlatformOSX:
+				return "OSX";
+			case kPlatformiOS:
+				return "iOS";
+			case kPlatformWatchOS:
+				return "watchOS";
+		#if SUPPORT_APPLE_TV
+			case kPlatform_tvOS:
+				return "tvOS";
+		#endif
+			case kPlatformUnknown:
+			default:
+				return "(unknown)";
+		}
+	}
 
 	class FileInfo {
     public:
@@ -208,7 +249,7 @@ public:
 	bool						allowSubArchitectureMismatches() const { return fAllowCpuSubtypeMismatches; }
 	bool						forceCpuSubtypeAll() const { return fForceSubtypeAll; }
 	const char*					architectureName() const { return fArchitectureName; }
-	void						setArchitecture(cpu_type_t, cpu_subtype_t subtype);
+	void						setArchitecture(cpu_type_t, cpu_subtype_t subtype, Options::Platform platform);
 	bool						archSupportsThumb2() const { return fArchSupportsThumb2; }
 	OutputKind					outputKind() const { return fOutputKind; }
 	bool						prebind() const { return fPrebind; }
@@ -233,6 +274,7 @@ public:
 	bool						allGlobalsAreDeadStripRoots() const;
 	bool						shouldExport(const char*) const;
 	bool						shouldReExport(const char*) const;
+	std::vector<const char*>	exportsData() const;
 	bool						ignoreOtherArchInputFiles() const { return fIgnoreOtherArchFiles; }
 	bool						traceDylibs() const	{ return fTraceDylibs; }
 	bool						traceArchives() const { return fTraceArchives; }
@@ -240,7 +282,10 @@ public:
 	UndefinedTreatment			undefinedTreatment() const { return fUndefinedTreatment; }
 	ld::MacVersionMin			macosxVersionMin() const { return fMacVersionMin; }
 	ld::IOSVersionMin			iOSVersionMin() const { return fIOSVersionMin; }
+	ld::WatchOSVersionMin		watchOSVersionMin() const { return fWatchOSVersionMin; }
+	uint32_t					minOSversion() const;
 	bool						minOS(ld::MacVersionMin mac, ld::IOSVersionMin iPhoneOS);
+	bool						min_iOS(ld::IOSVersionMin requirediOSMin);
 	bool						messagesPrefixedWithArchitecture();
 	Treatment					picTreatment();
 	WeakReferenceMismatchTreatment	weakReferenceMismatchTreatment() const { return fWeakReferenceMismatchTreatment; }
@@ -266,7 +311,7 @@ public:
 	CommonsMode					commonsMode() const { return fCommonsMode; }
 	bool						warnCommons() const { return fWarnCommons; }
 	bool						keepRelocations();
-	FileInfo					findFile(const char* path) const;
+	FileInfo					findFile(const std::string &path) const;
 	UUIDMode					UUIDMode() const { return fUUIDMode; }
 	bool						warnStabs();
 	bool						pauseAtEnd() { return fPause; }
@@ -296,7 +341,7 @@ public:
 	const std::vector<DylibOverride>&	dylibOverrides() const { return fDylibOverrides; }
 	const char*					generatedMapPath() const { return fMapPath; }
 	bool						positionIndependentExecutable() const { return fPositionIndependentExecutable; }
-	Options::FileInfo			findFileUsingPaths(const char* path) const;
+	Options::FileInfo			findFileUsingPaths(const std::string &path) const;
 	bool						deadStripDylibs() const { return fDeadStripDylibs; }
 	bool						allowedUndefined(const char* name) const { return ( fAllowedUndefined.find(name) != fAllowedUndefined.end() ); }
 	bool						someAllowedUndefines() const { return (fAllowedUndefined.size() != 0); }
@@ -311,6 +356,7 @@ public:
 	bool						needsUnwindInfoSection() const { return fAddCompactUnwindEncoding; }
 	const std::vector<const char*>&	llvmOptions() const{ return fLLVMOptions; }
 	const std::vector<const char*>&	segmentOrder() const{ return fSegmentOrder; }
+	bool						segmentOrderAfterFixedAddressSegment(const char* segName) const;
 	const std::vector<const char*>* sectionOrder(const char* segName) const;
 	const std::vector<const char*>&	dyldEnvironExtras() const{ return fDyldEnvironExtras; }
 	const std::vector<const char*>&	astFilePaths() const{ return fASTFilePaths; }
@@ -346,7 +392,7 @@ public:
 	bool						objcGc() const { return fObjCGc; }
 	bool						objcGcOnly() const { return fObjCGcOnly; }
 	bool						canUseThreadLocalVariables() const { return fTLVSupport; }
-	bool						addVersionLoadCommand() const { return fVersionLoadCommand; }
+	bool						addVersionLoadCommand() const { return fVersionLoadCommand && (fPlatform != kPlatformUnknown); }
 	bool						addFunctionStarts() const { return fFunctionStartsLoadCommand; }
 	bool						addDataInCodeInfo() const { return fDataInCodeInfoLoadCommand; }
 	bool						canReExportSymbols() const { return fCanReExportSymbols; }
@@ -364,6 +410,15 @@ public:
 	bool						markAppExtensionSafe() const { return fMarkAppExtensionSafe; }
 	bool						checkDylibsAreAppExtensionSafe() const { return fCheckAppExtensionSafe; }
 	bool						forceLoadSwiftLibs() const { return fForceLoadSwiftLibs; }
+	bool						bundleBitcode() const { return fBundleBitcode; }
+	bool						hideSymbols() const { return fHideSymbols; }
+	bool						renameReverseSymbolMap() const { return fReverseMapUUIDRename; }
+	const char*					reverseSymbolMapPath() const { return fReverseMapPath; }
+	std::string					reverseMapTempPath() const { return fReverseMapTempPath; }
+	bool						ltoCodegenOnly() const { return fLTOCodegenOnly; }
+	bool						ignoreAutoLink() const { return fIgnoreAutoLink; }
+	bool						sharedRegionEncodingV2() const { return fSharedRegionEncodingV2; }
+	bool						useDataConstSegment() const { return fUseDataConstSegment; }
 	bool						hasWeakBitTweaks() const;
 	bool						forceWeak(const char* symbolName) const;
 	bool						forceNotWeak(const char* symbolName) const;
@@ -375,7 +430,6 @@ public:
 	bool						needsThreadLoadCommand() const { return fNeedsThreadLoadCommand; }
 	bool						needsEntryPointLoadCommand() const { return fEntryPointLoadCommand; }
 	bool						needsSourceVersionLoadCommand() const { return fSourceVersionLoadCommand; }
-	bool						needsDependentDRInfo() const { return fDependentDRInfo; }
 	bool						canUseAbsoluteSymbols() const { return fAbsoluteSymbols; }
 	bool						allowSimulatorToLinkWithMacOSX() const { return fAllowSimulatorToLinkWithMacOSX; }
 	uint64_t					sourceVersion() const { return fSourceVersion; }
@@ -395,6 +449,11 @@ public:
 	const std::vector<SegmentRename>& segmentRenames() const { return fSegmentRenames; }
 	bool						moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const;
 	bool						moveRwSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const;
+	Platform					platform() const { return fPlatform; }
+	const std::vector<const char*>&	sdkPaths() const { return fSDKPaths; }
+	std::vector<std::string>	writeBitcodeLinkOptions() const;
+	std::string					getSDKVersionStr() const;
+	std::string					getPlatformStr() const;
 
 private:
 	typedef std::unordered_map<const char*, unsigned int, ld::CStringHash, ld::CStringEquals> NameToOrder;
@@ -414,6 +473,7 @@ private:
 		NameSet::iterator		regularBegin() const	{ return fRegular.begin(); }
 		NameSet::iterator		regularEnd() const		{ return fRegular.end(); }
 		void					remove(const NameSet&); 
+		std::vector<const char*>		data() const;
 	private:
 		static bool				hasWildCards(const char*);
 		bool					wildCardMatch(const char* pattern, const char* candidate) const;
@@ -437,6 +497,8 @@ private:
 											 FileInfo& result) const;
 	uint64_t					parseVersionNumber64(const char*);
 	uint32_t					parseVersionNumber32(const char*);
+	std::string					getVersionString32(uint32_t ver) const;
+	std::string					getVersionString64(uint64_t ver) const;
 	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);
@@ -450,6 +512,7 @@ private:
 	void						setUndefinedTreatment(const char* treatment);
 	void						setMacOSXVersionMin(const char* version);
 	void						setIOSVersionMin(const char* version);
+	void						setWatchOSVersionMin(const char* version);
 	void						setWeakReferenceMismatchTreatment(const char* treatment);
 	void						addDylibOverride(const char* paths);
 	void						addSectionAlignment(const char* segment, const char* section, const char* alignment);
@@ -465,6 +528,7 @@ private:
 	void						addSectionRename(const char* srcSegment, const char* srcSection, const char* dstSegment, const char* dstSection);
 	void						addSegmentRename(const char* srcSegment, const char* dstSegment);
 	void						addSymbolMove(const char* dstSegment, const char* symbolList, std::vector<SymbolsMove>& list, const char* optionName);
+	void						cannotBeUsedWithBitcode(const char* arg);
 
 
 //	ObjectFile::ReaderOptions			fReaderOptions;
@@ -550,6 +614,7 @@ private:
 	bool								fStatistics;
 	bool								fPrintOptions;
 	bool								fSharedRegionEligible;
+	bool								fSharedRegionEligibleForceOff;
 	bool								fPrintOrderFileStatistics;
 	bool								fReadOnlyx86Stubs;
 	bool								fPositionIndependentExecutable;
@@ -562,6 +627,8 @@ private:
 	bool								fKextsUseStubs;
 	bool								fUsingLazyDylibLinking;
 	bool								fEncryptable;
+	bool								fEncryptableForceOn;
+	bool								fEncryptableForceOff;
 	bool								fOrderData;
 	bool								fMarkDeadStrippableDylib;
 	bool								fMakeCompressedDyldInfo;
@@ -621,9 +688,6 @@ private:
 	bool								fSourceVersionLoadCommand;
 	bool								fSourceVersionLoadCommandForceOn;
 	bool								fSourceVersionLoadCommandForceOff;	
-	bool								fDependentDRInfo;
-	bool								fDependentDRInfoForcedOn;
-	bool								fDependentDRInfoForcedOff;
 	bool								fTargetIOSSimulator;
 	bool								fExportDynamic;
 	bool								fAbsoluteSymbols;
@@ -639,14 +703,27 @@ private:
 	bool								fMarkAppExtensionSafe;
 	bool								fCheckAppExtensionSafe;
 	bool								fForceLoadSwiftLibs;
+	bool								fSharedRegionEncodingV2;
+	bool								fUseDataConstSegment;
+	bool								fUseDataConstSegmentForceOn;
+	bool								fUseDataConstSegmentForceOff;
+	bool								fBundleBitcode;
+	bool								fHideSymbols;
+	bool								fReverseMapUUIDRename;
+	const char*							fReverseMapPath;
+	std::string							fReverseMapTempPath;
+	bool								fLTOCodegenOnly;
+	bool								fIgnoreAutoLink;
+	Platform							fPlatform;
 	DebugInfoStripping					fDebugInfoStripping;
 	const char*							fTraceOutputFile;
 	ld::MacVersionMin					fMacVersionMin;
 	ld::IOSVersionMin					fIOSVersionMin;
+	ld::WatchOSVersionMin				fWatchOSVersionMin;
 	std::vector<AliasPair>				fAliases;
 	std::vector<const char*>			fInitialUndefines;
 	NameSet								fAllowedUndefined;
-	NameSet								fWhyLive;
+	SetWithWildcards					fWhyLive;
 	std::vector<ExtraSection>			fExtraSections;
 	std::vector<SectionAlignment>		fSectionAlignments;
 	std::vector<OrderedSymbol>			fOrderedSymbols;
diff --git a/src/ld/OutputFile.cpp b/src/ld/OutputFile.cpp
index 1680ade..dd0e5b2 100644
--- a/src/ld/OutputFile.cpp
+++ b/src/ld/OutputFile.cpp
@@ -51,6 +51,7 @@
 #include <list>
 #include <algorithm>
 #include <unordered_set>
+#include <utility>
 
 #include <CommonCrypto/CommonDigest.h>
 #include <AvailabilityMacros.h>
@@ -65,7 +66,6 @@
 #include "LinkEdit.hpp"
 #include "LinkEditClassic.hpp"
 
-
 namespace ld {
 namespace tool {
 
@@ -82,7 +82,7 @@ OutputFile::OutputFile(const Options& opts)
 		rebaseSection(NULL), bindingSection(NULL), weakBindingSection(NULL), 
 		lazyBindingSection(NULL), exportSection(NULL), 
 		splitSegInfoSection(NULL), functionStartsSection(NULL), 
-		dataInCodeSection(NULL), optimizationHintsSection(NULL), dependentDRsSection(NULL), 
+		dataInCodeSection(NULL), optimizationHintsSection(NULL),
 		symbolTableSection(NULL), stringPoolSection(NULL), 
 		localRelocationsSection(NULL), externalRelocationsSection(NULL), 
 		sectionRelocationsSection(NULL), 
@@ -94,7 +94,6 @@ OutputFile::OutputFile(const Options& opts)
 		_hasSplitSegInfo(opts.sharedRegionEligible()),
 		_hasFunctionStartsInfo(opts.addFunctionStarts()),
 		_hasDataInCodeInfo(opts.addDataInCodeInfo()),
-		_hasDependentDRInfo(opts.needsDependentDRInfo()),
 		_hasDynamicSymbolTable(true),
 		_hasLocalRelocations(!opts.makeCompressedDyldInfo()),
 		_hasExternalRelocations(!opts.makeCompressedDyldInfo()),
@@ -120,7 +119,6 @@ OutputFile::OutputFile(const Options& opts)
 		_splitSegInfoAtom(NULL),
 		_functionStartsAtom(NULL),
 		_dataInCodeAtom(NULL),
-		_dependentDRInfoAtom(NULL),
 		_optimizationHintsAtom(NULL)
 {
 }
@@ -156,7 +154,10 @@ void OutputFile::write(ld::Internal& state)
 	this->synthesizeDebugNotes(state);
 	this->buildSymbolTable(state);
 	this->generateLinkEditInfo(state);
-	this->makeSplitSegInfo(state);
+	if ( _options.sharedRegionEncodingV2() )
+		this->makeSplitSegInfoV2(state);
+	else
+		this->makeSplitSegInfo(state);
 	this->updateLINKEDITAddresses(state);
 	//this->dumpAtomsBySection(state, false);
 	this->writeOutputFile(state);
@@ -267,13 +268,7 @@ void OutputFile::updateLINKEDITAddresses(ld::Internal& state)
 		_optimizationHintsAtom->encode();
 	}
 	
-	if ( _options.needsDependentDRInfo() ) {
-		// build dependent dylib DR info  
-		assert(_dependentDRInfoAtom != NULL);
-		_dependentDRInfoAtom->encode();
-	}
-
-	// build classic symbol table  
+	// build classic symbol table
 	assert(_symbolTableAtom != NULL);
 	_symbolTableAtom->encode();
 	assert(_indirectSymbolTableAtom != NULL);
@@ -1233,6 +1228,8 @@ static bool isPageKind(const ld::Fixup* fixup, bool mustBeGOT=false)
 			return !mustBeGOT;
 		case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
 		case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
+		case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
+		case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
 			return true;
 		case ld::Fixup::kindSetTargetAddress:
 			f = fixup;
@@ -1244,6 +1241,8 @@ static bool isPageKind(const ld::Fixup* fixup, bool mustBeGOT=false)
 					return !mustBeGOT;
 				case ld::Fixup::kindStoreARM64GOTLoadPage21:
 				case ld::Fixup::kindStoreARM64GOTLeaPage21:
+				case ld::Fixup::kindStoreARM64TLVPLoadPage21:
+				case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
 					return true;
 				default:
 					break;
@@ -1265,6 +1264,8 @@ static bool isPageOffsetKind(const ld::Fixup* fixup, bool mustBeGOT=false)
 			return !mustBeGOT;
 		case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
 		case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
+		case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
+		case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
 			return true;
 		case ld::Fixup::kindSetTargetAddress:
 			f = fixup;
@@ -1276,6 +1277,8 @@ static bool isPageOffsetKind(const ld::Fixup* fixup, bool mustBeGOT=false)
 					return !mustBeGOT;
 				case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
 				case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
+				case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
+				case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
 					return true;
 				default:
 					break;
@@ -1295,7 +1298,6 @@ static bool isPageOffsetKind(const ld::Fixup* fixup, bool mustBeGOT=false)
 		break; \
 	} 
 
-
 void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::Atom* atom, uint8_t* buffer)
 {
 	//fprintf(stderr, "applyFixUps() on %s\n", atom->name());
@@ -2098,10 +2100,25 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 				setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta3 << 2), &infoC);
 			if ( alt.info.count > 2 )
 				setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta4 << 2), &infoD);
-				
+
+			if ( _options.sharedRegionEligible() ) {
+				if ( _options.sharedRegionEncodingV2() ) {
+					// In v2 format, all references might be move at dyld shared cache creation time
+					usableSegment = false;
+				}
+				else {
+					// In v1 format, only references to something in __TEXT segment could be optimized
+					usableSegment = (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0);
+				}
+			}
+			else {
+				// main executables can optimize any reference
+				usableSegment = true;
+			}
+
 			switch ( alt.info.kind ) {
 				case LOH_ARM64_ADRP_ADRP:
-					// processed in pass 2 beacuse some ADRP may have been removed
+					// processed in pass 2 because some ADRP may have been removed
 					break;
 				case LOH_ARM64_ADRP_LDR:
 					LOH_ASSERT(alt.info.count == 1);
@@ -2109,10 +2126,12 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 					LOH_ASSERT(isPageOffsetKind(infoB.fixup));
 					LOH_ASSERT(infoA.target == infoB.target);
 					LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
-					usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 					isADRP = parseADRP(infoA.instruction, adrpInfoA);
 					LOH_ASSERT(isADRP);
 					isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
+					// silently ignore LDRs transformed to ADD by TLV pass
+					if ( !isLDR && infoB.fixup->kind == ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12 )
+						break;
 					LOH_ASSERT(isLDR);
 					LOH_ASSERT(ldrInfoB.baseReg == adrpInfoA.destReg);
 					LOH_ASSERT(ldrInfoB.offset == (infoA.targetAddress & 0x00000FFF));
@@ -2122,7 +2141,7 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 						set32LE(infoA.instructionContent, makeNOP());
 						set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
 						if ( _options.verboseOptimizationHints() )
-							fprintf(stderr, "adrp-ldr at 0x%08llX transformed to LDR literal\n", infoB.instructionAddress);
+							fprintf(stderr, "adrp-ldr at 0x%08llX transformed to LDR literal, usableSegment=%d usableSegment\n", infoB.instructionAddress, usableSegment);
 					}
 					else {
 						if ( _options.verboseOptimizationHints() )
@@ -2137,7 +2156,6 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 					LOH_ASSERT(infoC.fixup == NULL);
 					LOH_ASSERT(infoA.target == infoB.target);
 					LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
-					usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 					isADRP = parseADRP(infoA.instruction, adrpInfoA);
 					LOH_ASSERT(isADRP);
 					isADD = parseADD(infoB.instruction, addInfoB);
@@ -2193,7 +2211,6 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 					isADD = parseADD(infoB.instruction, addInfoB);
 					LOH_ASSERT(isADD);
 					LOH_ASSERT(adrpInfoA.destReg == addInfoB.srcReg);
-					usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 					if ( usableSegment && withinOneMeg(infoA.targetAddress, infoA.instructionAddress) ) {
 						// can do T4 transformation and use ADR 
 						set32LE(infoA.instructionContent, makeADR(addInfoB.destReg, infoA.targetAddress, infoA.instructionAddress));
@@ -2227,7 +2244,6 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 						LOH_ASSERT(!ldrInfoB.isFloat);
 						LOH_ASSERT(ldrInfoC.baseReg == ldrInfoB.reg);
 						//fprintf(stderr, "infoA.target=%p, %s, infoA.targetAddress=0x%08llX\n", infoA.target, infoA.target->name(), infoA.targetAddress);
-						usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 						targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
 						if ( usableSegment && targetFourByteAligned && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
 							// can do T5 transform
@@ -2246,7 +2262,6 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 						// target of GOT is in same linkage unit and B instruction was changed to ADD to compute LEA of target
 						LOH_ASSERT(addInfoB.srcReg == adrpInfoA.destReg);
 						LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
-						usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 						targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
 						literalableSize  = ( (ldrInfoC.size != 1) && (ldrInfoC.size != 2) );
 						if ( usableSegment && literalableSize && targetFourByteAligned && withinOneMeg(infoC.instructionAddress, infoA.targetAddress) ) {
@@ -2295,7 +2310,6 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 					LOH_ASSERT(infoC.fixup == NULL);
 					LOH_ASSERT(infoA.target == infoB.target);
 					LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
-					usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 					isADRP = parseADRP(infoA.instruction, adrpInfoA);
 					LOH_ASSERT(isADRP);
 					isADD = parseADD(infoB.instruction, addInfoB);
@@ -2348,7 +2362,6 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 						LOH_ASSERT(ldrInfoB.size == 8);
 						LOH_ASSERT(!ldrInfoB.isFloat);
 						LOH_ASSERT(ldrInfoC.baseReg == ldrInfoB.reg);
-						usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 						targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
 						if ( usableSegment && targetFourByteAligned && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
 							// can do T5 transform
@@ -2367,7 +2380,6 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 						// target of GOT is in same linkage unit and B instruction was changed to ADD to compute LEA of target
 						LOH_ASSERT(addInfoB.srcReg == adrpInfoA.destReg);
 						LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
-						usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 						targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
 						literalableSize  = ( (ldrInfoC.size != 1) && (ldrInfoC.size != 2) );
 						if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress) ) {
@@ -2410,7 +2422,6 @@ void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::
 					isADRP = parseADRP(infoA.instruction, adrpInfoA);
 					isADD = parseADD(infoB.instruction, addInfoB);
 					isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
-					usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
 					if ( isADRP ) {
 						if ( isLDR ) {
 							if ( usableSegment && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
@@ -2599,12 +2610,32 @@ void OutputFile::writeAtoms(ld::Internal& state, uint8_t* wholeBuffer)
 	}
 }
 
-
 void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer)
 {
 	const bool log = false;
 	if ( (_options.outputKind() != Options::kObjectFile) || state.someObjectFileHasDwarf ) {
 		uint8_t digest[CC_MD5_DIGEST_LENGTH];
+		std::vector<std::pair<uint64_t, uint64_t>> excludeRegions;
+		uint64_t bitcodeCmdOffset;
+		uint64_t bitcodeCmdEnd;
+		uint64_t bitcodeSectOffset;
+		uint64_t bitcodePaddingEnd;
+		if ( _headersAndLoadCommandAtom->bitcodeBundleCommand(bitcodeCmdOffset, bitcodeCmdEnd,
+															  bitcodeSectOffset, bitcodePaddingEnd) ) {
+			// Exclude embedded bitcode bundle section which contains timestamps in XAR header
+			// Note the timestamp is in the compressed XML header which means it might change the size of
+			// bitcode section. The load command which include the size of the section and the padding after
+			// the bitcode section should also be excluded in the UUID computation.
+			// Bitcode section should appears before LINKEDIT
+			// Exclude section cmd
+			if ( log ) fprintf(stderr, "bundle cmd start=0x%08llX, bundle cmd end=0x%08llX\n",
+							   bitcodeCmdOffset, bitcodeCmdEnd);
+			excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(bitcodeCmdOffset, bitcodeCmdEnd));
+			// Exclude section content
+			if ( log ) fprintf(stderr, "bundle start=0x%08llX, bundle end=0x%08llX\n",
+							   bitcodeSectOffset, bitcodePaddingEnd);
+			excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(bitcodeSectOffset, bitcodePaddingEnd));
+		}
 		uint32_t	stabsStringsOffsetStart;
 		uint32_t	tabsStringsOffsetEnd;
 		uint32_t	stabsOffsetStart;
@@ -2631,20 +2662,30 @@ void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer)
 			if ( log ) fprintf(stderr, "firstStabStringFileOffset=0x%08llX\n", firstStabStringFileOffset);
 			if ( log ) fprintf(stderr, "lastStabStringFileOffset=0x%08llX\n", lastStabStringFileOffset);
 			assert(firstStabNlistFileOffset <= firstStabStringFileOffset);
-			
+			excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(firstStabNlistFileOffset, lastStabNlistFileOffset));
+			excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(firstStabStringFileOffset, lastStabStringFileOffset));
+		}
+		if ( !excludeRegions.empty() ) {
 			CC_MD5_CTX md5state;
 			CC_MD5_Init(&md5state);
-			// checksum everything up to first stabs nlist
-			if ( log ) fprintf(stderr, "checksum 0x%08X -> 0x%08llX\n", 0, firstStabNlistFileOffset);
-			CC_MD5_Update(&md5state, &wholeBuffer[0], firstStabNlistFileOffset);
-			// checkusm everything after last stabs nlist and up to first stabs string
-			if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", lastStabNlistFileOffset, firstStabStringFileOffset);
-			CC_MD5_Update(&md5state, &wholeBuffer[lastStabNlistFileOffset], firstStabStringFileOffset-lastStabNlistFileOffset);
-			// checksum everything after last stabs string to end of file
-			if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", lastStabStringFileOffset, _fileSize);
-			CC_MD5_Update(&md5state, &wholeBuffer[lastStabStringFileOffset], _fileSize-lastStabStringFileOffset);
+			// rdar://problem/19487042 include the output leaf file name in the hash
+			const char* lastSlash = strrchr(_options.outputFilePath(), '/');
+			if ( lastSlash !=  NULL ) {
+				CC_MD5_Update(&md5state, lastSlash, strlen(lastSlash));
+			}
+			uint64_t checksumStart = 0;
+			for ( auto& region : excludeRegions ) {
+				uint64_t regionStart = region.first;
+				uint64_t regionEnd = region.second;
+				assert(checksumStart <= regionStart && regionStart <= regionEnd && "Region overlapped");
+				if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", checksumStart, regionStart);
+				CC_MD5_Update(&md5state, &wholeBuffer[checksumStart], regionStart - checksumStart);
+				checksumStart = regionEnd;
+			}
+			if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", checksumStart, _fileSize);
+			CC_MD5_Update(&md5state, &wholeBuffer[checksumStart], _fileSize-checksumStart);
 			CC_MD5_Final(digest, &md5state);
-			if ( log ) fprintf(stderr, "uuid=%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", digest[0], digest[1], digest[2], 
+			if ( log ) fprintf(stderr, "uuid=%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", digest[0], digest[1], digest[2],
 							   digest[3], digest[4], digest[5], digest[6],  digest[7]);
 		}
 		else {
@@ -2658,7 +2699,18 @@ void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer)
 		_headersAndLoadCommandAtom->recopyUUIDCommand();
 	}
 }
-	
+
+static int sDescriptorOfPathToRemove = -1;
+static void removePathAndExit(int sig)
+{
+	if ( sDescriptorOfPathToRemove != -1 ) {
+		char path[MAXPATHLEN];
+		if ( ::fcntl(sDescriptorOfPathToRemove, F_GETPATH, path) == 0 )
+			::unlink(path);
+	}
+	fprintf(stderr, "ld: interrupted\n");
+	exit(1);
+}
 	
 void OutputFile::writeOutputFile(ld::Internal& state)
 {
@@ -2724,12 +2776,16 @@ void OutputFile::writeOutputFile(ld::Internal& state)
 	char tmpOutput[PATH_MAX];
 	uint8_t *wholeBuffer;
 	if ( outputIsRegularFile && outputIsMappableFile ) {
+		// <rdar://problem/20959031> ld64 should clean up temporary files on SIGINT
+		::signal(SIGINT, removePathAndExit);
+
 		strcpy(tmpOutput, _options.outputFilePath());
 		// If the path is too long to add a suffix for a temporary name then
 		// just fall back to using the output path. 
 		if (strlen(tmpOutput)+strlen(filenameTemplate) < PATH_MAX) {
 			strcat(tmpOutput, filenameTemplate);
 			fd = mkstemp(tmpOutput);
+			sDescriptorOfPathToRemove = fd;
 		} 
 		else {
 			fd = open(tmpOutput, O_RDWR|O_CREAT, permissions);
@@ -2788,11 +2844,24 @@ void OutputFile::writeOutputFile(ld::Internal& state)
 		if ( ::write(fd, wholeBuffer, _fileSize) == -1 ) {
 			throwf("can't write to output file: %s, errno=%d", _options.outputFilePath(), errno);
 		}
+		sDescriptorOfPathToRemove = -1;
 		::close(fd);
 		// <rdar://problem/13118223> NFS: iOS incremental builds in Xcode 4.6 fail with codesign error
 		// NFS seems to pad the end of the file sometimes.  Calling trunc seems to correct it...
 		::truncate(_options.outputFilePath(), _fileSize);
 	}
+
+	// Rename symbol map file if needed
+	if ( _options.renameReverseSymbolMap() ) {
+		assert(_options.hideSymbols() && _options.reverseSymbolMapPath() != NULL && "Must hide symbol and specify a path");
+		uuid_string_t UUIDString;
+		const uint8_t* rawUUID = _headersAndLoadCommandAtom->getUUID();
+		uuid_unparse_upper(rawUUID, UUIDString);
+		char outputMapPath[PATH_MAX];
+		sprintf(outputMapPath, "%s/%s.bcsymbolmap", _options.reverseSymbolMapPath(), UUIDString);
+		if ( ::rename(_options.reverseMapTempPath().c_str(), outputMapPath) != 0 )
+			throwf("could not create bcsymbolmap file: %s", outputMapPath);
+	}
 }
 
 struct AtomByNameSorter
@@ -3114,7 +3183,7 @@ void OutputFile::addLinkEdit(ld::Internal& state)
 				localRelocationsSection = state.addAtom(*_localRelocsAtom);
 			}
 			if  ( _hasSplitSegInfo ) {
-				_splitSegInfoAtom = new SplitSegInfoAtom<x86>(_options, state, *this);
+				_splitSegInfoAtom = new SplitSegInfoV1Atom<x86>(_options, state, *this);
 				splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
 			}
 			if ( _hasFunctionStartsInfo ) {
@@ -3129,10 +3198,6 @@ void OutputFile::addLinkEdit(ld::Internal& state)
 				_optimizationHintsAtom = new OptimizationHintsAtom<x86>(_options, state, *this);
 				optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
 			}
-			if ( _hasDependentDRInfo ) {
-				_dependentDRInfoAtom = new DependentDRAtom<x86>(_options, state, *this);
-				dependentDRsSection = state.addAtom(*_dependentDRInfoAtom);
-			}
 			if ( _hasSymbolTable ) {
 				_symbolTableAtom = new SymbolTableAtom<x86>(_options, state, *this);
 				symbolTableSection = state.addAtom(*_symbolTableAtom);
@@ -3176,7 +3241,7 @@ void OutputFile::addLinkEdit(ld::Internal& state)
 				localRelocationsSection = state.addAtom(*_localRelocsAtom);
 			}
 			if  ( _hasSplitSegInfo ) {
-				_splitSegInfoAtom = new SplitSegInfoAtom<x86_64>(_options, state, *this);
+				_splitSegInfoAtom = new SplitSegInfoV1Atom<x86_64>(_options, state, *this);
 				splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
 			}
 			if ( _hasFunctionStartsInfo ) {
@@ -3191,10 +3256,6 @@ void OutputFile::addLinkEdit(ld::Internal& state)
 				_optimizationHintsAtom = new OptimizationHintsAtom<x86_64>(_options, state, *this);
 				optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
 			}
-			if ( _hasDependentDRInfo ) {
-				_dependentDRInfoAtom = new DependentDRAtom<x86_64>(_options, state, *this);
-				dependentDRsSection = state.addAtom(*_dependentDRInfoAtom);
-			}
 			if ( _hasSymbolTable ) {
 				_symbolTableAtom = new SymbolTableAtom<x86_64>(_options, state, *this);
 				symbolTableSection = state.addAtom(*_symbolTableAtom);
@@ -3238,7 +3299,10 @@ void OutputFile::addLinkEdit(ld::Internal& state)
 				localRelocationsSection = state.addAtom(*_localRelocsAtom);
 			}
 			if  ( _hasSplitSegInfo ) {
-				_splitSegInfoAtom = new SplitSegInfoAtom<arm>(_options, state, *this);
+				if ( _options.sharedRegionEncodingV2() )
+					_splitSegInfoAtom = new SplitSegInfoV2Atom<arm>(_options, state, *this);
+				else
+					_splitSegInfoAtom = new SplitSegInfoV1Atom<arm>(_options, state, *this);
 				splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
 			}
 			if ( _hasFunctionStartsInfo ) {
@@ -3253,10 +3317,6 @@ void OutputFile::addLinkEdit(ld::Internal& state)
 				_optimizationHintsAtom = new OptimizationHintsAtom<arm>(_options, state, *this);
 				optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
 			}
-			if ( _hasDependentDRInfo ) {
-				_dependentDRInfoAtom = new DependentDRAtom<arm>(_options, state, *this);
-				dependentDRsSection = state.addAtom(*_dependentDRInfoAtom);
-			}
 			if ( _hasSymbolTable ) {
 				_symbolTableAtom = new SymbolTableAtom<arm>(_options, state, *this);
 				symbolTableSection = state.addAtom(*_symbolTableAtom);
@@ -3300,7 +3360,10 @@ void OutputFile::addLinkEdit(ld::Internal& state)
 				localRelocationsSection = state.addAtom(*_localRelocsAtom);
 			}
 			if  ( _hasSplitSegInfo ) {
-				_splitSegInfoAtom = new SplitSegInfoAtom<arm64>(_options, state, *this);
+				if ( _options.sharedRegionEncodingV2() )
+					_splitSegInfoAtom = new SplitSegInfoV2Atom<arm64>(_options, state, *this);
+				else
+					_splitSegInfoAtom = new SplitSegInfoV1Atom<arm64>(_options, state, *this);
 				splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
 			}
 			if ( _hasFunctionStartsInfo ) {
@@ -3315,10 +3378,6 @@ void OutputFile::addLinkEdit(ld::Internal& state)
 				_optimizationHintsAtom = new OptimizationHintsAtom<arm64>(_options, state, *this);
 				optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
 			}
-			if ( _hasDependentDRInfo ) {
-				_dependentDRInfoAtom = new DependentDRAtom<arm64>(_options, state, *this);
-				dependentDRsSection = state.addAtom(*_dependentDRInfoAtom);
-			}
 			if ( _hasSymbolTable ) {
 				_symbolTableAtom = new SymbolTableAtom<arm64>(_options, state, *this);
 				symbolTableSection = state.addAtom(*_symbolTableAtom);
@@ -4401,7 +4460,6 @@ void OutputFile::addSectionRelocs(ld::Internal& state, ld::Internal::FinalSectio
 
 }
 
-
 void OutputFile::makeSplitSegInfo(ld::Internal& state)
 {
 	if ( !_options.sharedRegionEligible() )
@@ -4503,6 +4561,183 @@ void OutputFile::makeSplitSegInfo(ld::Internal& state)
 	}
 }
 
+void OutputFile::makeSplitSegInfoV2(ld::Internal& state)
+{
+	static const bool log = false;
+	if ( !_options.sharedRegionEligible() )
+		return;
+	
+	for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
+		ld::Internal::FinalSection* sect = *sit;
+		if ( sect->isSectionHidden() )
+			continue;
+		bool codeSection = (sect->type() == ld::Section::typeCode);
+		if (log) fprintf(stderr, "sect: %s, address=0x%llX\n", sect->sectionName(), sect->address);
+		for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
+			const ld::Atom* atom = *ait;
+			const ld::Atom* target = NULL;
+			const ld::Atom* fromTarget = NULL;
+			uint32_t picBase = 0;
+            uint64_t accumulator = 0;
+            bool thumbTarget;
+			bool hadSubtract = false;
+			uint8_t fromSectionIndex = atom->machoSection();
+			uint8_t toSectionIndex;
+			uint8_t kind = 0;
+			uint64_t fromOffset = 0;
+			uint64_t toOffset = 0;
+			uint64_t addend = 0;
+			for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
+				if ( fit->firstInCluster() ) {
+					target = NULL;
+					fromTarget = NULL;
+					kind = 0;
+					addend = 0;
+					toSectionIndex = 255;
+					fromOffset = atom->finalAddress() + fit->offsetInAtom - sect->address;
+				}
+				if ( this->setsTarget(fit->kind) ) {
+					accumulator = addressOf(state, fit, &target);			
+					thumbTarget = targetIsThumb(state, fit);
+					if ( thumbTarget ) 
+						accumulator |= 1;
+					toOffset = accumulator - state.atomToSection[target]->address;
+					if ( target->definition() != ld::Atom::definitionProxy ) {
+						if ( target->section().type() == ld::Section::typeMachHeader )
+							toSectionIndex = 0;
+						else
+							toSectionIndex = target->machoSection();
+					}
+				}
+				switch ( fit->kind ) {
+					case ld::Fixup::kindSubtractTargetAddress:
+                        accumulator -= addressOf(state, fit, &fromTarget);
+						hadSubtract = true;
+						break;
+                    case ld::Fixup::kindAddAddend:
+						accumulator += fit->u.addend;
+						addend = fit->u.addend;
+						break;
+                    case ld::Fixup::kindSubtractAddend:
+						accumulator -= fit->u.addend;
+						picBase = fit->u.addend;
+						break;
+					case ld::Fixup::kindSetLazyOffset:
+						break;
+					case ld::Fixup::kindStoreBigEndian32:
+					case ld::Fixup::kindStoreLittleEndian32:
+					case ld::Fixup::kindStoreTargetAddressLittleEndian32:
+						if ( kind != DYLD_CACHE_ADJ_V2_IMAGE_OFF_32 ) {
+							if ( hadSubtract )
+								kind = DYLD_CACHE_ADJ_V2_DELTA_32;
+							else
+								kind = DYLD_CACHE_ADJ_V2_POINTER_32;
+						}
+						break;
+					case ld::Fixup::kindStoreLittleEndian64:
+					case ld::Fixup::kindStoreTargetAddressLittleEndian64:
+						if ( hadSubtract )
+							kind = DYLD_CACHE_ADJ_V2_DELTA_64;
+						else
+							kind = DYLD_CACHE_ADJ_V2_POINTER_64;
+						break;
+					case ld::Fixup::kindStoreX86PCRel32:
+					case ld::Fixup::kindStoreX86PCRel32_1:
+					case ld::Fixup::kindStoreX86PCRel32_2:
+					case ld::Fixup::kindStoreX86PCRel32_4:
+					case ld::Fixup::kindStoreX86PCRel32GOTLoad:
+					case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
+					case ld::Fixup::kindStoreX86PCRel32GOT:
+					case ld::Fixup::kindStoreX86PCRel32TLVLoad:
+					case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
+					case ld::Fixup::kindStoreTargetAddressX86PCRel32:
+					case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
+					case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
+					case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
+					case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
+#if SUPPORT_ARCH_arm64
+					case ld::Fixup::kindStoreARM64PCRelToGOT:
+#endif
+						if ( (fromSectionIndex != toSectionIndex) || !codeSection )
+							kind = DYLD_CACHE_ADJ_V2_DELTA_32;
+						break;
+#if SUPPORT_ARCH_arm64
+					case ld::Fixup::kindStoreARM64Page21:
+					case ld::Fixup::kindStoreARM64GOTLoadPage21:
+					case ld::Fixup::kindStoreARM64GOTLeaPage21:
+					case ld::Fixup::kindStoreARM64TLVPLoadPage21:
+					case ld::Fixup::kindStoreTargetAddressARM64Page21:
+					case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
+					case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
+						if ( fromSectionIndex != toSectionIndex )
+							kind = DYLD_CACHE_ADJ_V2_ARM64_ADRP;
+						break;
+					case ld::Fixup::kindStoreARM64PageOff12:
+					case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
+					case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
+					case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
+					case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
+					case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
+					case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
+					case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
+						if ( fromSectionIndex != toSectionIndex )
+							kind = DYLD_CACHE_ADJ_V2_ARM64_OFF12;
+						break;
+					case ld::Fixup::kindStoreARM64Branch26:
+					case ld::Fixup::kindStoreTargetAddressARM64Branch26:
+						if ( fromSectionIndex != toSectionIndex )
+							kind = DYLD_CACHE_ADJ_V2_ARM64_BR26;
+						break;
+#endif
+                    case ld::Fixup::kindStoreARMHigh16:
+                    case ld::Fixup::kindStoreARMLow16:
+						if ( (fromSectionIndex != toSectionIndex) && (fromTarget == atom) ) {
+							kind = DYLD_CACHE_ADJ_V2_ARM_MOVW_MOVT;
+						}
+						break;
+ 					case ld::Fixup::kindStoreARMBranch24:
+					case ld::Fixup::kindStoreTargetAddressARMBranch24:
+						if ( fromSectionIndex != toSectionIndex )
+							kind = DYLD_CACHE_ADJ_V2_ARM_BR24;
+						break;
+                    case ld::Fixup::kindStoreThumbLow16:
+                    case ld::Fixup::kindStoreThumbHigh16:
+						if ( (fromSectionIndex != toSectionIndex) && (fromTarget == atom) ) {
+							kind = DYLD_CACHE_ADJ_V2_THUMB_MOVW_MOVT;
+						}
+						break;
+					case ld::Fixup::kindStoreThumbBranch22:
+					case ld::Fixup::kindStoreTargetAddressThumbBranch22:
+						if ( fromSectionIndex != toSectionIndex )
+							kind = DYLD_CACHE_ADJ_V2_THUMB_BR22;
+						break;
+					case ld::Fixup::kindSetTargetImageOffset:
+						kind = DYLD_CACHE_ADJ_V2_IMAGE_OFF_32;
+						accumulator = addressOf(state, fit, &target);			
+						assert(target != NULL);
+						toSectionIndex = target->machoSection();
+						toOffset = accumulator - state.atomToSection[target]->address;
+						hadSubtract = true;
+						break;
+					default:
+						break;
+				}
+				if ( fit->lastInCluster() ) {
+					if ( (kind != 0) && (target != NULL) && (target->definition() != ld::Atom::definitionProxy) ) {
+						if ( !hadSubtract && addend )
+							toOffset += addend;
+						assert(toSectionIndex != 255);
+						if (log) fprintf(stderr, "from (%d.%s + 0x%llX) to (%d.%s + 0x%llX), kind=%d, atomAddr=0x%llX, sectAddr=0x%llx\n",
+										fromSectionIndex, sect->sectionName(), fromOffset, toSectionIndex, state.atomToSection[target]->sectionName(),
+										toOffset, kind, atom->finalAddress(), sect->address);
+						_splitSegV2Infos.push_back(SplitSegInfoV2Entry(fromSectionIndex, fromOffset, toSectionIndex, toOffset, kind));
+					}
+				}
+			}
+		}
+	}
+}
+
 
 void OutputFile::writeMapFile(ld::Internal& state)
 {
@@ -4618,7 +4853,6 @@ void OutputFile::writeMapFile(ld::Internal& state)
 	}
 }
 
-
 // used to sort atoms with debug notes
 class DebugNoteSorter
 {
diff --git a/src/ld/OutputFile.h b/src/ld/OutputFile.h
index 6bb793b..cbb1cfe 100644
--- a/src/ld/OutputFile.h
+++ b/src/ld/OutputFile.h
@@ -83,7 +83,6 @@ public:
 	ld::Internal::FinalSection*	functionStartsSection;
 	ld::Internal::FinalSection*	dataInCodeSection;
 	ld::Internal::FinalSection*	optimizationHintsSection;
-	ld::Internal::FinalSection*	dependentDRsSection;
 	ld::Internal::FinalSection*	symbolTableSection;
 	ld::Internal::FinalSection*	stringPoolSection;
 	ld::Internal::FinalSection*	localRelocationsSection;
@@ -132,12 +131,23 @@ public:
 	};
 	
 	struct SplitSegInfoEntry {
-						SplitSegInfoEntry(uint64_t a, ld::Fixup::Kind k, uint32_t e=0) : address(a), kind(k), extra(e) {}
-		uint64_t		address;
+						SplitSegInfoEntry(uint64_t a, ld::Fixup::Kind k, uint32_t e=0)
+							: fixupAddress(a), kind(k), extra(e) {}
+		uint64_t		fixupAddress;
 		ld::Fixup::Kind	kind;
         uint32_t        extra;
 	};
 	
+	struct SplitSegInfoV2Entry {
+						SplitSegInfoV2Entry(uint8_t fi, uint64_t fo, uint8_t ti, uint64_t to, uint8_t k)
+							: fixupSectionOffset(fo), targetSectionOffset(to), fixupSectionIndex(fi), targetSectionIndex(ti), referenceKind(k) {}
+		uint64_t		fixupSectionOffset;
+		uint64_t		targetSectionOffset;
+		uint8_t			fixupSectionIndex;
+		uint8_t			targetSectionIndex;
+		uint8_t			referenceKind;
+	};
+
 private:
 	void						writeAtoms(ld::Internal& state, uint8_t* wholeBuffer);
 	void						computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer);
@@ -192,6 +202,7 @@ private:
 	void						makeSectionRelocations(ld::Internal& state);
 	void						makeDyldInfo(ld::Internal& state);
 	void						makeSplitSegInfo(ld::Internal& state);
+	void						makeSplitSegInfoV2(ld::Internal& state);
 	void						writeMapFile(ld::Internal& state);
 	uint64_t					lookBackAddend(ld::Fixup::iterator fit);
 	bool						takesNoDiskSpace(const ld::Section* sect);
@@ -271,7 +282,6 @@ private:
 	const bool								_hasSplitSegInfo;
 	const bool								_hasFunctionStartsInfo;
 	const bool								_hasDataInCodeInfo;
-	const bool								_hasDependentDRInfo;
 		  bool								_hasDynamicSymbolTable;
 		  bool								_hasLocalRelocations;
 		  bool								_hasExternalRelocations;
@@ -296,6 +306,7 @@ public:
 	std::vector<BindingInfo>				_lazyBindingInfo;
 	std::vector<BindingInfo>				_weakBindingInfo;
 	std::vector<SplitSegInfoEntry>			_splitSegInfos;
+	std::vector<SplitSegInfoV2Entry>		_splitSegV2Infos;
 	class HeaderAndLoadCommandsAbtract*		_headersAndLoadCommandAtom;
 	class RelocationsAtomAbstract*			_sectionsRelocationsAtom;
 	class RelocationsAtomAbstract*			_localRelocsAtom;
@@ -311,7 +322,6 @@ public:
 	class LinkEditAtom*						_splitSegInfoAtom;
 	class LinkEditAtom*						_functionStartsAtom;
 	class LinkEditAtom*						_dataInCodeAtom;
-	class LinkEditAtom*						_dependentDRInfoAtom;
 	class LinkEditAtom*						_optimizationHintsAtom;
 };
 
diff --git a/src/ld/Resolver.cpp b/src/ld/Resolver.cpp
index 8a72b67..094c98d 100644
--- a/src/ld/Resolver.cpp
+++ b/src/ld/Resolver.cpp
@@ -53,6 +53,7 @@
 #include "Options.h"
 
 #include "ld.hpp"
+#include "Bitcode.hpp"
 #include "InputFiles.h"
 #include "SymbolTable.h"
 #include "Resolver.h"
@@ -282,6 +283,8 @@ void Resolver::initializeState()
 		_internal.objcObjectConstraint = ld::File::objcConstraintGC;
 	
 	_internal.cpuSubType = _options.subArchitecture();
+	_internal.minOSVersion = _options.minOSversion();
+	_internal.derivedPlatformLoadCommand = 0;
 	
 	// In -r mode, look for -linker_option additions
 	if ( _options.outputKind() == Options::kObjectFile ) {
@@ -330,14 +333,20 @@ void Resolver::doLinkerOption(const std::vector<const char*>& linkerOption, cons
 	}
 }
 
-static void userReadableSwiftVersion(uint8_t value, char versionString[32])
+static void userReadableSwiftVersion(uint8_t value, char versionString[64])
 {
 	switch (value) {
 		case 1:
 			strcpy(versionString, "1.0");
 			break;
+		case 2:
+			strcpy(versionString, "1.1");
+			break;
+		case 3:
+			strcpy(versionString, "2.0");
+			break;
 		default:
-			sprintf(versionString, "0x%02X", value);
+			sprintf(versionString, "unknown ABI version 0x%02X", value);
 	}
 }
 
@@ -349,12 +358,67 @@ void Resolver::doFile(const ld::File& file)
 	if ( objFile != NULL ) {
 		// if file has linker options, process them
 		ld::relocatable::File::LinkerOptionsList* lo = objFile->linkerOptions();
-		if ( lo != NULL ) {
+		if ( lo != NULL && !_options.ignoreAutoLink() ) {
 			for (relocatable::File::LinkerOptionsList::const_iterator it=lo->begin(); it != lo->end(); ++it) {
 				this->doLinkerOption(*it, file.path());
 			}
 		}
-		
+
+		// Resolve bitcode section in the object file
+		if ( _options.bundleBitcode() ) {
+			if ( objFile->getBitcode() == NULL ) {
+				// No bitcode section, figure out if the object file comes from LTO/compiler static library
+				if (objFile->sourceKind() != ld::relocatable::File::kSourceLTO &&
+					objFile->sourceKind() != ld::relocatable::File::kSourceCompilerArchive ) {
+					switch ( _options.platform() ) {
+					case Options::kPlatformOSX:
+					case Options::kPlatformUnknown:
+						warning("all bitcode will be dropped because '%s' was built without bitcode. "
+								"You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. ", file.path());
+						_internal.filesWithBitcode.clear();
+						_internal.dropAllBitcode = true;
+						break;
+					case Options::kPlatformiOS:
+						throwf("'%s' does not contain bitcode. "
+							   "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
+						break;
+					case Options::kPlatformWatchOS:
+						throwf("'%s' does not contain bitcode. "
+								"You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor", file.path());
+						break;
+			#if SUPPORT_APPLE_TV
+					case Options::kPlatform_tvOS:
+						warning("URGENT: all bitcode will be dropped because '%s' was built without bitcode. "
+								"You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor. "
+								"Note: This will be an error in the future.", file.path());
+						_internal.filesWithBitcode.clear();
+						_internal.dropAllBitcode = true;
+						break;
+			#endif
+					}
+				}
+			} else {
+				// contains bitcode, check if it is just a marker
+				if ( objFile->getBitcode()->isMarker() ) {
+					// if the bitcode is just a marker,
+					// the executable will be created without bitcode section.
+					// Otherwise, create a marker.
+					if ( _options.outputKind() != Options::kDynamicExecutable &&
+						 _options.outputKind() != Options::kStaticExecutable )
+						_internal.embedMarkerOnly = true;
+					// Issue a warning if the marker is in the static library and filesWithBitcode is not empty.
+					// That means there are object files actually compiled with full bitcode but the archive only has marker.
+					// Don't warn on normal object files because it can be a debug build using archives with full bitcode.
+					if ( !_internal.filesWithBitcode.empty() && objFile->sourceKind() == ld::relocatable::File::kSourceArchive )
+						warning("full bitcode bundle could not be generated because '%s' was built only with bitcode marker. "
+								"The library must be generated from Xcode archive build with bitcode enabled (Xcode setting ENABLE_BITCODE)", objFile->path());
+					_internal.filesWithBitcode.clear();
+					_internal.dropAllBitcode = true;
+				} else if ( !_internal.dropAllBitcode )
+					_internal.filesWithBitcode.push_back(objFile);
+			}
+		}
+
 		// update which form of ObjC is being used
 		switch ( file.objCConstraint() ) {
 			case ld::File::objcConstraintNone:
@@ -400,8 +464,8 @@ void Resolver::doFile(const ld::File& file)
 				_internal.swiftVersion = file.swiftVersion();
 			}
 			else if ( file.swiftVersion() != _internal.swiftVersion ) {
-				char fileVersion[32];
-				char otherVersion[32];
+				char fileVersion[64];
+				char otherVersion[64];
 				userReadableSwiftVersion(file.swiftVersion(), fileVersion);
 				userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
 				if ( file.swiftVersion() > _internal.swiftVersion ) {
@@ -423,6 +487,18 @@ void Resolver::doFile(const ld::File& file)
 		if ( ! objFile->canScatterAtoms() )
 			_internal.allObjectFilesScatterable = false;
 	
+		// update minOSVersion off all .o files
+		uint32_t objMinOS = objFile->minOSVersion();
+		if ( !objMinOS )
+			_internal.objectFileFoundWithNoVersion = true;
+
+		uint32_t objPlatformLC = objFile->platformLoadCommand();
+		if ( (objPlatformLC != 0) && (_internal.derivedPlatformLoadCommand == 0) && (_options.outputKind() == Options::kObjectFile) )
+			_internal.derivedPlatformLoadCommand = objPlatformLC;
+
+		if ( (_options.outputKind() == Options::kObjectFile) && (objMinOS > _internal.minOSVersion) )
+			_internal.minOSVersion = objMinOS;
+
 		// update cpu-sub-type
 		cpu_subtype_t nextObjectSubType = file.cpuSubType();
 		switch ( _options.architecture() ) {
@@ -464,6 +540,57 @@ void Resolver::doFile(const ld::File& file)
 		}
 	}
 	if ( dylibFile != NULL ) {
+		// Check dylib for bitcode, if the library install path is relative path or @rpath, it has to contain bitcode
+		if ( _options.bundleBitcode() ) {
+			if ( dylibFile->getBitcode() == NULL &&
+				 dylibFile->installPath()[0] != '/' ) {
+				// Check if the dylib is from toolchain by checking the path
+				char tcLibPath[PATH_MAX];
+				char ldPath[PATH_MAX];
+				char tempPath[PATH_MAX];
+				uint32_t bufSize = PATH_MAX;
+				// toolchain library path should pointed to *.xctoolchain/usr/lib
+				if ( _NSGetExecutablePath(ldPath, &bufSize) != -1 ) {
+					if ( realpath(ldPath, tempPath) != NULL ) {
+						char* lastSlash = strrchr(tempPath, '/');
+						if ( lastSlash != NULL )
+							strcpy(lastSlash, "/../lib");
+					}
+				}
+				// Compare toolchain library path to the dylib path
+				if ( realpath(tempPath, tcLibPath) == NULL ||
+					 realpath(dylibFile->path(), tempPath) == NULL ||
+					 strncmp(tcLibPath, tempPath, strlen(tcLibPath)) != 0 ) {
+					switch ( _options.platform() ) {
+					case Options::kPlatformOSX:
+					case Options::kPlatformUnknown:
+						warning("all bitcode will be dropped because '%s' was built without bitcode. "
+								"You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
+						_internal.filesWithBitcode.clear();
+						_internal.dropAllBitcode = true;
+						break;
+					case Options::kPlatformiOS:
+						throwf("'%s' does not contain bitcode. "
+							   "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
+						break;
+					case Options::kPlatformWatchOS:
+						throwf("'%s' does not contain bitcode. "
+								"You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor", file.path());
+						break;
+			#if SUPPORT_APPLE_TV
+					case Options::kPlatform_tvOS:
+						warning("URGENT: all bitcode will be dropped because '%s' was built without bitcode. "
+								"You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE) or obtain an updated library from the vendor. "
+								"Note: This will be an error in the future.", file.path());
+						_internal.filesWithBitcode.clear();
+						_internal.dropAllBitcode = true;
+						break;
+			#endif
+					}
+				}
+			}
+		}
+
 		// update which form of ObjC dylibs are being linked
 		switch ( dylibFile->objCConstraint() ) {
 			case ld::File::objcConstraintNone:
@@ -509,18 +636,19 @@ void Resolver::doFile(const ld::File& file)
 		if ( (depInstallName != NULL) && (depInstallName[0] != '/') ) {
 			if ( (_options.iOSVersionMin() != iOSVersionUnset) && (_options.iOSVersionMin() < iOS_8_0) ) {
 				// <rdar://problem/17598404> only warn about linking against embedded dylib if it is built for iOS 8 or later
-				if ( dylibFile->iOSMinVersion() >= iOS_8_0 )
-					warning("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName);
+				if ( dylibFile->minOSVersion() >= iOS_8_0 )
+					throwf("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName);
 			}
 		}
 		if ( _options.sharedRegionEligible() ) {
 			assert(depInstallName != NULL);
-			if ( depInstallName[0] == '@' )
+			if ( depInstallName[0] == '@' ) {
 				warning("invalid -install_name (%s) in dependent dylib (%s). Dylibs/frameworks which might go in dyld shared cache "
-						"cannot link with dylib that uses @rpath, @loaderpath, etc.", depInstallName, dylibFile->path());
-			if ( (strncmp(depInstallName, "/usr/lib/", 9) != 0) && (strncmp(depInstallName, "/System/Library/", 16) != 0) )
+						"cannot link with dylib that uses @rpath, @loader_path, etc.", depInstallName, dylibFile->path());
+			} else if ( (strncmp(depInstallName, "/usr/lib/", 9) != 0) && (strncmp(depInstallName, "/System/Library/", 16) != 0) ) {
 				warning("invalid -install_name (%s) in dependent dylib (%s). Dylibs/frameworks which might go in dyld shared cache "
 						"cannot link with dylibs that won't be in the shared cache", depInstallName, dylibFile->path());
+			}
 		}
 	}
 
@@ -631,6 +759,8 @@ void Resolver::doAtom(const ld::Atom& atom)
 		// add to set of dead-strip-roots, all symbols that the compiler marks as don't strip
 		if ( atom.dontDeadStrip() )
 			_deadStripRoots.insert(&atom);
+		else if ( atom.dontDeadStripIfReferencesLive() )
+			_dontDeadStripIfReferencesLive.push_back(&atom);
 			
 		if ( atom.scope() == ld::Atom::scopeGlobal ) {
 			// <rdar://problem/5524973> -exported_symbols_list that has wildcards and -dead_strip
@@ -883,6 +1013,8 @@ void Resolver::markLive(const ld::Atom& atom, WhyLiveBackChain* previous)
 			case ld::Fixup::kindStoreTargetAddressARM64Page21:
 			case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
 			case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
+			case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
+			case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
 #endif
 				if ( fit->binding == ld::Fixup::bindingByContentBound ) {
 					// normally this was done in convertReferencesToIndirect()
@@ -1015,6 +1147,38 @@ void Resolver::deadStripOptimize(bool force)
 		this->markLive(**it, &rootChain);
 	}
 	
+	// special case atoms that need to be live if they reference something live
+	if ( ! _dontDeadStripIfReferencesLive.empty() ) {
+		for (std::vector<const ld::Atom*>::iterator it=_dontDeadStripIfReferencesLive.begin(); it != _dontDeadStripIfReferencesLive.end(); ++it) {
+			const Atom* liveIfRefLiveAtom = *it;
+			//fprintf(stderr, "live-if-live atom: %s\n", liveIfRefLiveAtom->name());
+			if ( liveIfRefLiveAtom->live() )
+				continue;
+			bool hasLiveRef = false;
+			for (ld::Fixup::iterator fit=liveIfRefLiveAtom->fixupsBegin(); fit != liveIfRefLiveAtom->fixupsEnd(); ++fit) {
+				const Atom* target = NULL;
+				switch ( fit->binding ) {
+					case ld::Fixup::bindingDirectlyBound:
+						target = fit->u.target;
+						break;
+					case ld::Fixup::bindingsIndirectlyBound:
+						target = _internal.indirectBindingTable[fit->u.bindingIndex];
+						break;
+					default:
+						break;
+				}
+				if ( (target != NULL) && target->live() ) 
+					hasLiveRef = true;
+			}
+			if ( hasLiveRef ) {
+				WhyLiveBackChain rootChain;
+				rootChain.previous = NULL;
+				rootChain.referer = liveIfRefLiveAtom;
+				this->markLive(*liveIfRefLiveAtom, &rootChain);
+			}
+		}
+	}
+	
 	// now remove all non-live atoms from _atoms
 	const bool log = false;
 	if ( log ) {
@@ -1538,6 +1702,7 @@ void Resolver::linkTimeOptimize()
 	optOpt.preserveAllGlobals			= _options.allGlobalsAreDeadStripRoots() || _options.hasExportRestrictList();
 	optOpt.verbose						= _options.verbose();
 	optOpt.saveTemps					= _options.saveTempFiles();
+	optOpt.ltoCodegenOnly					= _options.ltoCodegenOnly();
 	optOpt.pie							= _options.positionIndependentExecutable();
 	optOpt.mainExecutable				= _options.linkingMainExecutable();;
 	optOpt.staticExecutable 			= (_options.outputKind() == Options::kStaticExecutable);
@@ -1548,8 +1713,12 @@ void Resolver::linkTimeOptimize()
 	optOpt.keepDwarfUnwind				= _options.keepDwarfUnwind();
 	optOpt.verboseOptimizationHints     = _options.verboseOptimizationHints();
 	optOpt.armUsesZeroCostExceptions    = _options.armUsesZeroCostExceptions();
+	optOpt.simulator					= _options.targetIOSSimulator();
+	optOpt.ignoreMismatchPlatform		= ((_options.outputKind() == Options::kPreload) || (_options.outputKind() == Options::kStaticExecutable));
+	optOpt.bitcodeBundle				= _options.bundleBitcode();
 	optOpt.arch							= _options.architecture();
 	optOpt.mcpu							= _options.mcpuLTO();
+	optOpt.platform						= _options.platform();
 	optOpt.llvmOptions					= &_options.llvmOptions();
 	optOpt.initialUndefines				= &_options.initialUndefines();
 	
diff --git a/src/ld/Resolver.h b/src/ld/Resolver.h
index 975772b..6631d11 100644
--- a/src/ld/Resolver.h
+++ b/src/ld/Resolver.h
@@ -126,6 +126,7 @@ private:
 	ld::Internal&					_internal;
 	std::vector<const ld::Atom*>	_atoms;
 	std::set<const ld::Atom*>		_deadStripRoots;
+	std::vector<const ld::Atom*>	_dontDeadStripIfReferencesLive;
 	std::vector<const ld::Atom*>	_atomsWithUnresolvedReferences;
 	std::vector<const class AliasAtom*>	_aliasesFromCmdLine;
 	SymbolTable						_symbolTable;
diff --git a/src/ld/SymbolTable.cpp b/src/ld/SymbolTable.cpp
index ea552f4..6014779 100644
--- a/src/ld/SymbolTable.cpp
+++ b/src/ld/SymbolTable.cpp
@@ -813,6 +813,15 @@ SymbolTable::IndirectBindingSlot SymbolTable::findSlotForReferences(const ld::At
 			slot = _indirectBindingTable.size();
 			_pointerToCStringTable[atom] = slot;
 			break;
+		case ld::Section::typeTLVPointers:
+			pos = _threadPointerTable.find(atom);
+			if ( pos != _threadPointerTable.end() ) {
+				*existingAtom = _indirectBindingTable[pos->second];
+				return pos->second;
+			}
+			slot = _indirectBindingTable.size();
+			_threadPointerTable[atom] = slot;
+			break;
 		default:
 			assert(0 && "section type does not support coalescing by references");
 	}
diff --git a/src/ld/SymbolTable.h b/src/ld/SymbolTable.h
index 14c7a9e..ce2f1dc 100644
--- a/src/ld/SymbolTable.h
+++ b/src/ld/SymbolTable.h
@@ -155,6 +155,7 @@ private:
 	CStringToSlot					_cstringTable;
 	NameToMap						_nonStdCStringSectionToMap;
 	ReferencesToSlot				_nonLazyPointerTable;
+	ReferencesToSlot				_threadPointerTable;
 	ReferencesToSlot				_cfStringTable;
 	ReferencesToSlot				_objc2ClassRefTable;
 	ReferencesToSlot				_pointerToCStringTable;
diff --git a/src/ld/code-sign-blobs/memutils.h b/src/ld/code-sign-blobs/memutils.h
index 391ddc1..9e752f4 100644
--- a/src/ld/code-sign-blobs/memutils.h
+++ b/src/ld/code-sign-blobs/memutils.h
@@ -50,8 +50,11 @@ static const size_t systemAlignment = 4;
 //
 // Get the local alignment for a type, as used by the acting compiler.
 //
-template <class T>
-inline size_t alignof() { struct { char c; T t; } s; return sizeof(s) - sizeof(T); }
+template <typename T>
+unsigned long myalignof() {
+	struct { char c; T t; } s;
+	return sizeof(s) - sizeof(T);
+}
 
 
 //
diff --git a/src/ld/ld.cpp b/src/ld/ld.cpp
index 4ef1f14..0b5bc4a 100644
--- a/src/ld/ld.cpp
+++ b/src/ld/ld.cpp
@@ -79,6 +79,7 @@ extern "C" double log2 ( double );
 #include "passes/branch_shim.h"
 #include "passes/objc.h"
 #include "passes/dylibs.h"
+#include "passes/bitcode_bundle.h"
 
 #include "parsers/archive_file.h"
 #include "parsers/macho_relocatable_file.h"
@@ -112,6 +113,8 @@ public:
 	void									setSectionSizesAndAlignments();
 	void									sortSections();
 	void									markAtomsOrdered() { _atomsOrderedInSections = true; }
+	bool									hasReferenceToWeakExternal(const ld::Atom& atom);
+
 	virtual									~InternalState() {}
 private:
 
@@ -137,6 +140,8 @@ private:
 		static ld::Section		_s_DATA_nl_symbol_ptr;
 		static ld::Section		_s_DATA_common;
 		static ld::Section		_s_DATA_zerofill;
+		static ld::Section		_s_DATA_DIRTY_data;
+		static ld::Section		_s_DATA_CONST_const;
 	};
 	
 	bool hasZeroForFileOffset(const ld::Section* sect);
@@ -164,6 +169,9 @@ ld::Section	InternalState::FinalSection::_s_TEXT_const("__TEXT", "__const", ld::
 ld::Section	InternalState::FinalSection::_s_DATA_nl_symbol_ptr("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
 ld::Section	InternalState::FinalSection::_s_DATA_common("__DATA", "__common", ld::Section::typeZeroFill);
 ld::Section	InternalState::FinalSection::_s_DATA_zerofill("__DATA", "__zerofill", ld::Section::typeZeroFill);
+ld::Section	InternalState::FinalSection::_s_DATA_DIRTY_data( "__DATA_DIRTY", "__data",  ld::Section::typeUnclassified);
+ld::Section	InternalState::FinalSection::_s_DATA_CONST_const( "__DATA_CONST", "__const",  ld::Section::typeUnclassified);
+
 std::vector<const char*> InternalState::FinalSection::_s_segmentsSeen;
 
 
@@ -212,6 +220,14 @@ const ld::Section& InternalState::FinalSection::outputSection(const ld::Section&
 				if ( strcmp(sect.sectionName(), "__const_coal") == 0 )
 					return _s_TEXT_const;
 			}
+			else if ( strcmp(sect.segmentName(), "__DATA_DIRTY") == 0 ) {
+				if ( strcmp(sect.sectionName(), "__datacoal_nt") == 0 )
+					return _s_DATA_DIRTY_data;
+			}
+			else if ( strcmp(sect.segmentName(), "__DATA_CONST") == 0 ) {
+				if ( strcmp(sect.sectionName(), "__const_coal") == 0 )
+					return _s_DATA_CONST_const;
+			}
 			break;
 		case ld::Section::typeZeroFill:
 			if ( mergeZeroFill )
@@ -304,7 +320,7 @@ uint32_t InternalState::FinalSection::sectionOrder(const ld::Section& sect, uint
 	if ( sect.type() == ld::Section::typeLastSection )
 		return INT_MAX;
 	const std::vector<const char*>* sectionList = options.sectionOrder(sect.segmentName());
-	if ( (options.outputKind() == Options::kPreload) && (sectionList != NULL) ) {
+	if ( ((options.outputKind() == Options::kPreload) || (options.outputKind() == Options::kDyld)) && (sectionList != NULL) ) {
 		uint32_t count = 10;
 		for (std::vector<const char*>::const_iterator it=sectionList->begin(); it != sectionList->end(); ++it, ++count) {
 			if ( strcmp(*it, sect.sectionName()) == 0 ) 
@@ -335,7 +351,7 @@ uint32_t InternalState::FinalSection::sectionOrder(const ld::Section& sect, uint
 				return sectionsSeen+20;
 		}
 	}
-	else if ( strcmp(sect.segmentName(), "__DATA") == 0 ) {
+	else if ( strncmp(sect.segmentName(), "__DATA", 6) == 0 ) {
 		switch ( sect.type() ) {
 			case ld::Section::typeLazyPointerClose:
 				return 8;
@@ -492,6 +508,34 @@ static void validateFixups(const ld::Atom& atom)
 }
 #endif
 
+bool InternalState::hasReferenceToWeakExternal(const ld::Atom& atom)
+{
+	// if __DATA,__const atom has pointer to weak external symbol, don't move to __DATA_CONST
+	const ld::Atom* target = NULL;
+	for (ld::Fixup::iterator fit=atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) {
+		if ( fit->firstInCluster() ) {
+			target = NULL;
+		}
+		switch ( fit->binding ) {
+			case ld::Fixup::bindingNone:
+			case ld::Fixup::bindingByNameUnbound:
+				break;
+			case ld::Fixup::bindingByContentBound:
+			case ld::Fixup::bindingDirectlyBound:
+				target = fit->u.target;
+				break;
+			case ld::Fixup::bindingsIndirectlyBound:
+				target = indirectBindingTable[fit->u.bindingIndex];
+				break;
+		}
+		if ( (target != NULL) && (target->definition() == ld::Atom::definitionRegular)
+			&& (target->combine() == ld::Atom::combineByName) && (target->scope() == ld::Atom::scopeGlobal) ) {
+			return true;
+		}
+	}
+	return false;
+}
+
 ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom)
 {
 	ld::Internal::FinalSection* fs = NULL;
@@ -515,7 +559,8 @@ ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom)
 		if ( _options.moveRwSymbol(atom.name(), path, dstSeg, wildCardMatch) ) {
 			if ( (sectType != ld::Section::typeZeroFill) 
 			  && (sectType != ld::Section::typeUnclassified) 
-			  && (sectType != ld::Section::typeTentativeDefs) ) {
+			  && (sectType != ld::Section::typeTentativeDefs)
+			  && (sectType != ld::Section::typeDyldInfo) ) {
 				if ( !wildCardMatch )
 					warning("cannot move symbol '%s' from file %s to segment '%s' because symbol is not data (is %d)", atom.name(), path, dstSeg, sectType);
 			}
@@ -526,7 +571,8 @@ ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom)
 			}
 		}
 		if ( (fs == NULL) && _options.moveRoSymbol(atom.name(), path, dstSeg, wildCardMatch) ) {
-			if ( atom.section().type() != ld::Section::typeCode ) {
+			if ( (sectType != ld::Section::typeCode)
+			  && (sectType != ld::Section::typeUnclassified) ) {
 				if ( !wildCardMatch )
 					warning("cannot move symbol '%s' from file %s to segment '%s' because symbol is not code (is %d)", atom.name(), path, dstSeg, sectType);
 			}
@@ -543,9 +589,24 @@ ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom)
 		const std::vector<Options::SegmentRename>& segRenames = _options.segmentRenames();
 		for ( std::vector<Options::SectionRename>::const_iterator it=sectRenames.begin(); it != sectRenames.end(); ++it) {
 			if ( (strcmp(sectName, it->fromSection) == 0) && (strcmp(atom.section().segmentName(), it->fromSegment) == 0) ) {
-				if ( _options.traceSymbolLayout() )
-					printf("symbol '%s', -rename_section mapped it to %s/%s\n", atom.name(), it->toSegment, it->toSection);
-				fs = this->getFinalSection(it->toSegment, it->toSection, sectType);
+				if ( _options.useDataConstSegment() && (strcmp(sectName, "__const") == 0)
+						&& (strcmp(atom.section().segmentName(), "__DATA") == 0) && hasReferenceToWeakExternal(atom) ) {
+					// if __DATA,__const atom has pointer to weak external symbol, don't move to __DATA_CONST
+					fs = this->getFinalSection("__DATA", "__const_weak", sectType);
+					if ( _options.traceSymbolLayout() )
+						printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/_const_weak\n", atom.name());
+				}
+				else if ( _options.useDataConstSegment() && (sectType == ld::Section::typeNonLazyPointer) && hasReferenceToWeakExternal(atom) ) {
+					// if __DATA,__nl_symbol_ptr atom has pointer to weak external symbol, don't move to __DATA_CONST
+					fs = this->getFinalSection("__DATA", "__got_weak", sectType);
+					if ( _options.traceSymbolLayout() )
+						printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/__got_weak\n", atom.name());
+				}
+				else {
+					fs = this->getFinalSection(it->toSegment, it->toSection, sectType);
+					if ( _options.traceSymbolLayout() )
+						printf("symbol '%s', -rename_section mapped it to %s/%s\n", atom.name(), fs->segmentName(), fs->sectionName());
+				}
 			}
 		}
 		if ( fs == NULL ) {
@@ -558,8 +619,7 @@ ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom)
 			}
 		}
 	}
-	
-	
+
 	// if no override, use default location
 	if ( fs == NULL ) {
 		fs = this->getFinalSection(atom.section());
@@ -589,6 +649,7 @@ ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom)
 		// normal case
 		fs->atoms.push_back(&atom);
 	}
+	this->atomToSection[&atom] = fs;
 	return fs;
 }
 
@@ -731,7 +792,7 @@ void InternalState::setSectionSizesAndAlignments()
 				bool pagePerAtom = false;
 				uint32_t atomAlignmentPowerOf2 = atom->alignment().powerOf2;
 				uint32_t atomModulus = atom->alignment().modulus;
-				if ( _options.pageAlignDataAtoms() && ( strcmp(atom->section().segmentName(), "__DATA") == 0) ) { 
+				if ( _options.pageAlignDataAtoms() && ( strncmp(atom->section().segmentName(), "__DATA", 6) == 0) ) {
 					// most objc sections cannot be padded
 					bool contiguousObjCSection = ( strncmp(atom->section().sectionName(), "__objc_", 7) == 0 );
 					if ( strcmp(atom->section().sectionName(), "__objc_const") == 0 )
@@ -811,13 +872,22 @@ uint64_t InternalState::assignFileOffsets()
 	uint64_t address = 0;
 	const char* lastSegName = "";
 	uint64_t floatingAddressStart = _options.baseAddress();
+	bool haveFixedSegments = false;
 	
+	// mark all sections as not having an address yet
+	for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
+		ld::Internal::FinalSection* sect = *it;
+		sect->alignmentPaddingBytes = 0;
+		sect->address = ULLONG_MAX;
+	}
+
 	// first pass, assign addresses to sections in segments with fixed start addresses
 	if ( log ) fprintf(stderr, "Fixed address segments:\n");
 	for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
 		ld::Internal::FinalSection* sect = *it;
 		if ( ! _options.hasCustomSegmentAddress(sect->segmentName()) ) 
 			continue;
+		haveFixedSegments = true;
 		if ( segmentsArePageAligned ) {
 			if ( strcmp(lastSegName, sect->segmentName()) != 0 ) {
 				address = _options.customSegmentAddress(sect->segmentName());
@@ -850,8 +920,38 @@ uint64_t InternalState::assignFileOffsets()
 			floatingAddressStart = address;
 		}
 	}
-	
-	// second pass, assign section address to sections in segments that are contiguous with previous segment
+
+	// second pass, assign section addresses to sections in segments that are ordered after a segment with a fixed address
+	if ( haveFixedSegments && !_options.segmentOrder().empty() ) {
+		if ( log ) fprintf(stderr, "After Fixed address segments:\n");
+		lastSegName = "";
+		ld::Internal::FinalSection* lastSect = NULL; 
+		for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
+			ld::Internal::FinalSection* sect = *it;
+			if ( (sect->address == ULLONG_MAX) && _options.segmentOrderAfterFixedAddressSegment(sect->segmentName()) ) {
+				address = lastSect->address + lastSect->size;
+				if ( (strcmp(lastSegName, sect->segmentName()) != 0) && segmentsArePageAligned ) {
+					// round up size of last segment
+					address = pageAlign(address, _options.segPageSize(lastSegName));
+				}
+				// adjust section address based on alignment
+				uint64_t unalignedAddress = address;
+				uint64_t alignment = (1 << sect->alignment);
+				address = ( (unalignedAddress+alignment-1) & (-alignment) );
+				sect->alignmentPaddingBytes = (address - unalignedAddress);
+				sect->address = address;
+				if ( log ) fprintf(stderr, "  address=0x%08llX, hidden=%d, alignment=%02d, section=%s,%s\n",
+									sect->address, sect->isSectionHidden(), sect->alignment, sect->segmentName(), sect->sectionName());
+				// update running totals
+				if ( !sect->isSectionHidden() || hiddenSectionsOccupyAddressSpace )
+					address += sect->size;
+			}
+			lastSegName = sect->segmentName();
+			lastSect = sect;
+		}
+	}
+
+	// last pass, assign addresses to remaining sections
 	address = floatingAddressStart;
 	lastSegName = "";
 	ld::Internal::FinalSection* overlappingFixedSection = NULL;
@@ -859,7 +959,7 @@ uint64_t InternalState::assignFileOffsets()
 	if ( log ) fprintf(stderr, "Regular layout segments:\n");
 	for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
 		ld::Internal::FinalSection* sect = *it;
-		if ( _options.hasCustomSegmentAddress(sect->segmentName()) ) 
+		if ( sect->address != ULLONG_MAX )
 			continue;
 		if ( (_options.outputKind() == Options::kPreload) && (sect->type() == ld::Section::typeMachHeader) ) {
 			sect->alignmentPaddingBytes = 0;
@@ -876,6 +976,7 @@ uint64_t InternalState::assignFileOffsets()
 				lastSegName = sect->segmentName();
 			}
 		}
+		
 		// adjust section address based on alignment
 		uint64_t unalignedAddress = address;
 		uint64_t alignment = (1 << sect->alignment);
@@ -1116,7 +1217,8 @@ int main(int argc, const char* argv[])
 		ld::passes::branch_island::doPass(options, state);	// must be after stubs and order pass
 		ld::passes::dtrace::doPass(options, state);
 		ld::passes::compact_unwind::doPass(options, state);  // must be after order pass
- 		
+		ld::passes::bitcode_bundle::doPass(options, state);  // must be after dylib
+		
 		// sort final sections
 		state.sortSections();
 
diff --git a/src/ld/ld.hpp b/src/ld/ld.hpp
index 889cf2c..c8f272e 100644
--- a/src/ld/ld.hpp
+++ b/src/ld/ld.hpp
@@ -31,13 +31,19 @@
 #include <unistd.h>
 #include <assert.h>
 
+#include <set>
+#include <map>
 #include <vector>
+#include <string>
 #include <unordered_set>
 
 #include "configure.h"
 
 namespace ld {
 
+// Forward declaration for bitcode support
+class Bitcode;
+
 //
 // ld::File 
 //
@@ -149,8 +155,11 @@ public:
 	virtual uint8_t						swiftVersion() const			{ return 0; }
 	virtual uint32_t					cpuSubType() const		{ return 0; }
 	virtual uint32_t					subFileCount() const	{ return 1; }
+	virtual uint32_t					minOSVersion() const	{ return 0; }
+	virtual uint32_t					platformLoadCommand() const		{ return 0; }
     bool								fileExists() const     { return _modTime != 0; }
 	Type								type() const { return _type; }
+	virtual Bitcode*					getBitcode() const		{ return NULL; }
 private:
 	const char*							_path;
 	time_t								_modTime;
@@ -169,7 +178,9 @@ enum IOSVersionMin { iOSVersionUnset=0, iOS_2_0=0x00020000, iOS_3_1=0x00030100,
 						iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000,
 						iOS_6_0=0x00060000, iOS_7_0=0x00070000, iOS_8_0=0x00080000,
 						iOS_9_0=0x00090000, iOS_Future=0x10000000};
- 
+enum WatchOSVersionMin  { wOSVersionUnset=0, wOS_1_0=0x00010000, wOS_2_0=0x00020000 };
+
+
 namespace relocatable {
 	//
 	// ld::relocatable::File 
@@ -191,6 +202,7 @@ namespace relocatable {
 	{
 	public:
 		enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 };
+		enum SourceKind { kSourceUnknown=0, kSourceObj, kSourceLTO, kSourceArchive, kSourceCompilerArchive, kSourceSingle };
 		struct Stab {
 			const class Atom*	atom;
 			uint8_t				type;
@@ -211,6 +223,7 @@ namespace relocatable {
 		virtual bool						canScatterAtoms() const = 0;
 		virtual bool						hasLongBranchStubs()		{ return false; }
 		virtual LinkerOptionsList*			linkerOptions() const = 0;
+		virtual SourceKind					sourceKind() const { return kSourceUnknown; }
 	};
 } // namespace relocatable
 
@@ -269,13 +282,15 @@ namespace dylib {
 		virtual bool						hasWeakDefinition(const char* name) const = 0;
 		virtual bool						hasPublicInstallName() const = 0;
 		virtual bool						allSymbolsAreWeakImported() const = 0;
-		virtual const void*					codeSignatureDR() const = 0;
 		virtual bool						installPathVersionSpecific() const { return false; }
 		virtual bool						appExtensionSafe() const = 0;
-		virtual MacVersionMin				macMinVersion() const { return macVersionUnset; }
-		virtual IOSVersionMin				iOSMinVersion() const { return iOSVersionUnset; }
 
 	protected:
+		struct ReExportChain { ReExportChain* prev; const File* file; };
+		virtual std::pair<bool, bool>		hasWeakDefinitionImpl(const char* name) const = 0;
+		virtual bool						containsOrReExports(const char* name, bool& weakDef, bool& tlv, uint64_t& defAddress) const = 0;
+		virtual void						assertNoReExportCycles(ReExportChain*) const = 0;
+
 		const char*							_dylibInstallPath;
 		uint32_t							_dylibTimeStamp;
 		uint32_t							_dylibCurrentVersion;
@@ -322,7 +337,7 @@ public:
 				typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
 				typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols, 
 				typeTLVDefs, typeTLVZeroFill, typeTLVInitialValues, typeTLVInitializerPointers, typeTLVPointers,
-				typeFirstSection, typeLastSection, typeDebug };
+				typeFirstSection, typeLastSection, typeDebug, typeSectCreate };
 
 
 					Section(const char* sgName, const char* sctName,
@@ -644,7 +659,7 @@ public:
 					typeSectionEnd, typeBranchIsland, typeLazyPointer, typeStub, typeNonLazyPointer, 
 					typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
 					typeLTOtemporary, typeResolver,
-					typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers };
+					typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers, typeTLVPointer };
 
 	enum SymbolTableInclusion { symbolTableNotIn, symbolTableNotInFinalLinkedImages, symbolTableIn,
 								symbolTableInAndNeverStrip, symbolTableInAsAbsolute, 
@@ -679,7 +694,8 @@ public:
 													_contentType(ct), _symbolTableInclusion(i),
 													_scope(s), _mode(modeSectionOffset), 
 													_overridesADylibsWeakDef(false), _coalescedAway(false),
-													_live(false), _machoSection(0), _weakImportState(weakImportUnset)
+													_live(false), _dontDeadStripIfRefLive(false),
+													_machoSection(0), _weakImportState(weakImportUnset)
 													 {
 													#ifndef NDEBUG
 														switch ( _combine ) {
@@ -703,6 +719,7 @@ public:
 	ContentType								contentType() const			{ return _contentType; }
 	SymbolTableInclusion					symbolTableInclusion() const{ return _symbolTableInclusion; }
 	bool									dontDeadStrip() const		{ return _dontDeadStrip; }
+	bool									dontDeadStripIfReferencesLive() const { return _dontDeadStripIfRefLive; }
 	bool									isThumb() const				{ return _thumb; }
 	bool									isAlias() const				{ return _alias; }
 	Alignment								alignment() const			{ return Alignment(_alignmentPowerOf2, _alignmentModulus); }
@@ -722,6 +739,7 @@ public:
 	void									setCoalescedAway()			{ _coalescedAway = true; }
 	void									setWeakImportState(bool w)	{ assert(_definition == definitionProxy); _weakImportState = ( w ? weakImportTrue : weakImportFalse); }
 	void									setAutoHide()				{ _autoHide = true; }
+	void									setDontDeadStripIfReferencesLive() { _dontDeadStripIfRefLive = true; }
 	void									setLive()					{ _live = true; }
 	void									setLive(bool value)			{ _live = value; }
 	void									setMachoSection(unsigned x) { assert(x != 0); assert(x < 256); _machoSection = x; }
@@ -794,6 +812,7 @@ protected:
 	bool								_overridesADylibsWeakDef : 1;
 	bool								_coalescedAway : 1;
 	bool								_live : 1;
+	bool								_dontDeadStripIfRefLive : 1;
 	unsigned							_machoSection : 8;
 	WeakImportState						_weakImportState : 2;
 };
@@ -824,6 +843,7 @@ struct CStringEquals
 
 typedef	std::unordered_set<const char*, ld::CStringHash, ld::CStringEquals>  CStringSet;
 
+
 class Internal
 {
 public:
@@ -848,6 +868,8 @@ public:
 		bool							hasExternalRelocs;
 	};
 	
+	typedef std::map<const ld::Atom*, FinalSection*>	AtomToSection;		
+
 	virtual uint64_t					assignFileOffsets() = 0;
 	virtual void						setSectionSizesAndAlignments() = 0;
 	virtual ld::Internal::FinalSection*	addAtom(const Atom&) = 0;
@@ -858,19 +880,23 @@ public:
 											lazyBindingHelper(NULL), compressedFastBinderProxy(NULL),
 											objcObjectConstraint(ld::File::objcConstraintNone), 
 											objcDylibConstraint(ld::File::objcConstraintNone), 
-											swiftVersion(0), cpuSubType(0), 
+											swiftVersion(0), cpuSubType(0), minOSVersion(0),
+											objectFileFoundWithNoVersion(false),
 											allObjectFilesScatterable(true), 
 											someObjectFileHasDwarf(false), usingHugeSections(false),
 											hasThreadLocalVariableDefinitions(false),
 											hasWeakExternalSymbols(false),
-											someObjectHasOptimizationHints(false) { }
-										
+											someObjectHasOptimizationHints(false),
+											dropAllBitcode(false), embedMarkerOnly(false)	{ }
+
 	std::vector<FinalSection*>					sections;
 	std::vector<ld::dylib::File*>				dylibs;
 	std::vector<ld::relocatable::File::Stab>	stabs;
+	AtomToSection								atomToSection;		
 	CStringSet									linkerOptionLibraries;
 	CStringSet									linkerOptionFrameworks;
 	std::vector<const ld::Atom*>				indirectBindingTable;
+	std::vector<const ld::relocatable::File*>	filesWithBitcode;
 	const ld::dylib::File*						bundleLoader;
 	const Atom*									entryPoint;
 	const Atom*									classicBindingHelper;
@@ -880,12 +906,18 @@ public:
 	ld::File::ObjcConstraint					objcDylibConstraint;
 	uint8_t										swiftVersion;
 	uint32_t									cpuSubType;
+	uint32_t									minOSVersion;
+	uint32_t									derivedPlatformLoadCommand;
+	bool										objectFileFoundWithNoVersion;
 	bool										allObjectFilesScatterable;
 	bool										someObjectFileHasDwarf;
 	bool										usingHugeSections;
 	bool										hasThreadLocalVariableDefinitions;
 	bool										hasWeakExternalSymbols;
 	bool										someObjectHasOptimizationHints;
+	bool										dropAllBitcode;
+	bool										embedMarkerOnly;
+	std::string									ltoBitcodePath;
 };
 
 
@@ -894,10 +926,6 @@ public:
 
 
 
-
-
-
-
 } // namespace ld 
 
 #endif // __LD_HPP__
diff --git a/src/ld/lto_file.hpp b/src/ld/lto_file.hpp
deleted file mode 100644
index 24d3f58..0000000
--- a/src/ld/lto_file.hpp
+++ /dev/null
@@ -1,642 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
- *
- * Copyright (c) 2006-2009 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __LTO_READER_H__
-#define __LTO_READER_H__
-
-#include <stdlib.h>
-#include <mach-o/dyld.h>
-#include <vector>
-#include <ext/hash_set>
-#include <ext/hash_map>
-
-#include "MachOFileAbstraction.hpp"
-#include "Architectures.hpp"
-#include "ld.hpp"
-
-#include "llvm-c/lto.h"
-
-
-namespace lto {
-	  
-
-//
-// ld64 only tracks non-internal symbols from an llvm bitcode file.  
-// We model this by having an InternalAtom which represent all internal functions and data.
-// All non-interal symbols from a bitcode file are represented by an Atom
-// and each Atom has a reference to the InternalAtom.  The InternalAtom
-// also has references to each symbol external to the bitcode file. 
-//
-class InternalAtom : public ld::Atom
-{
-public:
-												InternalAtom(class File& f);
-	// overrides of ld::Atom
-	virtual ld::File*							file() const		{ return &_file; }
-	virtual bool								translationUnitSource(const char** dir, const char** nm) const
-																	{ return false; }
-	virtual const char*							name() const		{ return "import-atom"; }
-	virtual uint64_t							size() const		{ return 0; }
-	virtual uint64_t							objectAddress() const { return 0; }
-	virtual void								copyRawContent(uint8_t buffer[]) const { }
-	virtual void								setScope(Scope)		{ }
-	virtual ld::Fixup::iterator					fixupsBegin()		{ return &_undefs[0]; }
-	virtual ld::Fixup::iterator					fixupsEnd()			{ return &_undefs[_undefs.size()]; }
-
-	// for adding references to symbols outside bitcode file
-	void										addReference(const char* name)
-																	{ _undefs.push_back(ld::Fixup(0, ld::Fixup::k1of1, 
-																				ld::Fixup::fixupNone, false, name)); }
-private:
-
-	ld::File&									_file;
-	std::vector<ld::Fixup>						_undefs;
-};
-
-
-//
-// LLVM bitcode file 
-//
-class File : public ld::relocatable::File
-{
-public:
-											File(const char* path, time_t mTime, const uint8_t* content, 
-													uint32_t contentLength, uint32_t ordinal, cpu_type_t arch);
-	virtual									~File();
-
-	// overrides of ld::File
-	virtual bool										forEachAtom(ld::File::AtomHandler&);
-	virtual bool										justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) 
-																					{ return false; }
-	
-	// overrides of ld::relocatable::File 
-	virtual bool										objcReplacementClasses()	{ return false; }
-	virtual DebugInfoKind								debugInfo()					{ return ld::relocatable::File::kDebugInfoNone; }
-	virtual std::vector<ld::relocatable::File::Stab>*	stabs()						{ return NULL; }
-	virtual bool										canScatterAtoms()			{ return true; }
-
-	lto_module_t										module()					{ return _module; }
-	class InternalAtom&									internalAtom()				{ return _internalAtom; }
-private:
-	friend class Atom;
-	friend class InternalAtom;
-	
-	cpu_type_t								_architecture;
-	class InternalAtom						_internalAtom;
-	class Atom*								_atomArray;
-	uint32_t								_atomArrayCount;
-	lto_module_t							_module;
-	ld::Section								_section;
-};
-
-//
-// Atom acts as a proxy Atom for the symbols that are exported by LLVM bitcode file. Initially,
-// Reader creates Atoms 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. Atom holds real Atom and forwards appropriate
-// methods to real atom.
-//
-class Atom : public ld::Atom
-{
-public:
-										Atom(File& f, const char* name, ld::Atom::Scope s, 
-													ld::Atom::Definition d, ld::Atom::Alignment a);
-
-	// overrides of ld::Atom
-	virtual ld::File*					file() const		{ return &_file; }
-	virtual bool						translationUnitSource(const char** dir, const char** nm) const
-															{ return (_compiledAtom ? _compiledAtom->translationUnitSource(dir, nm) : false); }
-	virtual const char*					name() const		{ return _name; }
-	virtual uint64_t					size() const		{ return (_compiledAtom ? _compiledAtom->size() : 0); }
-	virtual uint64_t					objectAddress() const { return (_compiledAtom ? _compiledAtom->objectAddress() : 0); }
-	virtual void						copyRawContent(uint8_t buffer[]) const 
-															{ if (_compiledAtom) _compiledAtom->copyRawContent(buffer); }
-															
-	ld::Atom*							compiledAtom()		{ return _compiledAtom; }
-	void								setCompiledAtom(ld::Atom& atom) 
-															{ _compiledAtom = &atom; }
-private:
-
-	File&								_file;
-	const char*							_name;
-	ld::Atom*							_compiledAtom;
-};
-
-											
-
-
-
-
-
-class Parser 
-{
-public:
-	static bool						validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture);
-	static const char*				fileKind(const uint8_t* fileContent);
-	static File*					parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, 
-											time_t modTime, uint32_t ordinal, cpu_type_t architecture);
-	static bool						libLTOisLoaded() { return (::lto_get_version() != NULL); }
-	static bool						optimize(const std::vector<ld::Atom*>& allAtoms, std::vector<ld::Atom*>& newAtoms, 
-												std::vector<const char*>& additionalUndefines, 
-												const std::set<ld::Atom*>&,
-												std::vector<ld::Atom*>& newDeadAtoms,
-												uint32_t nextInputOrdinal, 
-												ld::OutFile* writer, ld::Atom* entryPointAtom,
-												const std::vector<const char*>& llvmOptions,
-												bool allGlobalsAReDeadStripRoots,
-												bool verbose, bool saveTemps, 
-												const char* outputFilePath,
-												bool pie,  bool mainExecutable, bool staticExecutable, bool relocatable,
-												bool allowTextRelocs, cpu_type_t arch);
-
-	static const char*			ltoVersion()	{ return ::lto_get_version(); }
-
-private:
-	static const char*				tripletPrefixForArch(cpu_type_t arch);
-	static ld::relocatable::File*	parseMachOFile(const uint8_t* p, size_t len, uint32_t nextInputOrdinal, cpu_type_t arch);
-
-	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>  CStringSet;
-	typedef __gnu_cxx::hash_map<const char*, Atom*, __gnu_cxx::hash<const char*>, CStringEquals> CStringToAtom;
-	
-	class AtomSyncer : public ld::File::AtomHandler {
-	public:
-							AtomSyncer(std::vector<const char*>& a, std::vector<ld::Atom*>&na,
-										CStringToAtom la, CStringToAtom dla) :
-										additionalUndefines(a), newAtoms(na), llvmAtoms(la), deadllvmAtoms(dla) { }
-		virtual void		doAtom(class ld::Atom&);
-		
-		std::vector<const char*>&		additionalUndefines;
-		std::vector<ld::Atom*>&			newAtoms;
-		CStringToAtom					llvmAtoms;
-		CStringToAtom					deadllvmAtoms;
-	};
-
-	static std::vector<File*>		_s_files;
-};
-
-std::vector<File*> Parser::_s_files;
-
-
-const char* Parser::tripletPrefixForArch(cpu_type_t arch)
-{
-	switch (arch) {
-		case CPU_TYPE_POWERPC:
-			return "powerpc-";
-		case CPU_TYPE_POWERPC64:
-			return "powerpc64-";
-		case CPU_TYPE_I386:
-			return "i386-";
-		case CPU_TYPE_X86_64:
-			return "x86_64-";
-		case CPU_TYPE_ARM:
-			return "arm";
-	}
-	return "";
-}
-
-bool Parser::validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture)
-{
-	return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, tripletPrefixForArch(architecture));
-}
-
-const char* Parser::fileKind(const uint8_t* p)
-{
-	if ( (p[0] == 0xDE) && (p[1] == 0xC0) && (p[2] == 0x17) && (p[3] == 0x0B) ) {
-		uint32_t arch = LittleEndian::get32(*((uint32_t*)(&p[16])));
-		switch (arch) {
-			case CPU_TYPE_POWERPC:
-				return "ppc";
-			case CPU_TYPE_I386:
-				return "i386";
-			case CPU_TYPE_X86_64:
-				return "x86_64";
-			case CPU_TYPE_ARM:
-				return "arm";
-		}
-		return "unknown bitcode architecture";
-	}
-	return NULL;
-}
-
-File* Parser::parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, 
-																uint32_t ordinal, cpu_type_t architecture) 
-{
-	File* f = new File(path, modTime, fileContent, fileLength, ordinal, architecture);
-	_s_files.push_back(f);
-	return f;
-}
-
-
-ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, uint32_t nextInputOrdinal, cpu_type_t arch) 
-{
-	switch ( arch ) {
-		case CPU_TYPE_POWERPC:
-			if ( mach_o::relocatable::Parser<ppc>::validFile(p) )
-				return mach_o::relocatable::Parser<ppc>::parse(p, len, "/tmp/lto.o", 0, nextInputOrdinal);
-			break;
-		case CPU_TYPE_POWERPC64:
-			if ( mach_o::relocatable::Parser<ppc64>::validFile(p) )
-				return mach_o::relocatable::Parser<ppc64>::parse(p, len, "/tmp/lto.o", 0, nextInputOrdinal);
-			break;
-		case CPU_TYPE_I386:
-			if ( mach_o::relocatable::Parser<x86>::validFile(p) )
-				return mach_o::relocatable::Parser<x86>::parse(p, len, "/tmp/lto.o", 0, nextInputOrdinal);
-			break;
-		case CPU_TYPE_X86_64:
-			if ( mach_o::relocatable::Parser<x86_64>::validFile(p) )
-				return mach_o::relocatable::Parser<x86_64>::parse(p, len, "/tmp/lto.o", 0, nextInputOrdinal);
-			break;
-		case CPU_TYPE_ARM:
-			if ( mach_o::relocatable::Parser<arm>::validFile(p) )
-				return mach_o::relocatable::Parser<arm>::parse(p, len, "/tmp/lto.o", 0, nextInputOrdinal);
-			break;
-	}
-	throw "LLVM LTO, file is not of required architecture";
-}
-
-
-
-File::File(const char* path, time_t mTime, const uint8_t* content, uint32_t contentLength, uint32_t ordinal, cpu_type_t arch) 
-	: ld::relocatable::File(path,mTime,ordinal), _architecture(arch), _internalAtom(*this), 
-	_atomArray(NULL), _atomArrayCount(0), _module(NULL),
-	_section("__TEXT_", "__tmp_lto", ld::Section::typeUnclassified)
-{
-	// create llvm module
-	_module = ::lto_module_create_from_memory(content, contentLength);
-    if ( _module == NULL )
-		throwf("could not parse object file %s: %s", path, lto_get_error_message());
-	
-	// create atom for each global symbol in module
-	uint32_t count = ::lto_module_get_num_symbols(_module);
-	_atomArray = (Atom*)malloc(sizeof(Atom)*count);
-	for (uint32_t i=0; i < count; ++i) {
-		const char* name = ::lto_module_get_symbol_name(_module, i);
-		lto_symbol_attributes attr = lto_module_get_symbol_attribute(_module, i);
-
-		// <rdar://problem/6378110> LTO doesn't like dtrace symbols
-		// ignore dtrace static probes for now
-		// later when codegen is done and a mach-o file is produces the probes will be processed
-		if ( (strncmp(name, "___dtrace_probe$", 16) == 0) || (strncmp(name, "___dtrace_isenabled$", 20) == 0) )
-			continue;
-				
-		ld::Atom::Definition def;
-		switch ( attr & LTO_SYMBOL_DEFINITION_MASK ) {
-			case LTO_SYMBOL_DEFINITION_REGULAR:
-				def = ld::Atom::definitionRegular;
-				break;
-			case LTO_SYMBOL_DEFINITION_TENTATIVE:
-				def = ld::Atom::definitionTentative;
-				break;
-			case LTO_SYMBOL_DEFINITION_WEAK:
-				def = ld::Atom::definitionRegular;
-				break;
-			case LTO_SYMBOL_DEFINITION_UNDEFINED:
-			case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
-				def = ld::Atom::definitionProxy;
-				break;
-			default:
-				throwf("unknown definition kind for symbol %s in bitcode file %s", name, path);
-		}
-
-		// make LLVM atoms for definitions and a reference for undefines
-		if ( def != ld::Atom::definitionProxy ) {
-			ld::Atom::Scope scope;
-			switch ( attr & LTO_SYMBOL_SCOPE_MASK) {
-				case LTO_SYMBOL_SCOPE_INTERNAL:
-					scope = ld::Atom::scopeTranslationUnit;
-					break;
-				case LTO_SYMBOL_SCOPE_HIDDEN:
-					scope = ld::Atom::scopeLinkageUnit;
-					break;
-				case LTO_SYMBOL_SCOPE_DEFAULT:
-					scope = ld::Atom::scopeGlobal;
-					break;
-				default:
-					throwf("unknown scope for symbol %s in bitcode file %s", name, path);
-			}
-			// only make atoms for non-internal symbols 
-			if ( scope == ld::Atom::scopeTranslationUnit )
-				continue;
-			uint8_t alignment = (attr & LTO_SYMBOL_ALIGNMENT_MASK);
-			// make Atom using placement new operator
-			new (&_atomArray[_atomArrayCount++]) Atom(*this, name, scope, def, alignment);
-		}
-		else {
-			// add to list of external references
-			_internalAtom.addReference(name);
-		}
-	}
-}
-
-File::~File()
-{
-	if ( _module != NULL )
-		::lto_module_dispose(_module);
-}
-
-bool File::forEachAtom(ld::File::AtomHandler& handler)
-{
-	handler.doAtom(_internalAtom);
-	for(uint32_t i=0; i < _atomArrayCount; ++i) {
-		handler.doAtom(_atomArray[i]);
-	}
-	return true;
-}
-
-InternalAtom::InternalAtom(File& f)
-	: ld::Atom(f._section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeTranslationUnit, 
-				ld::Atom::typeLTOtemporary, ld::Atom::symbolTableNotIn, false, false, ld::Atom::Alignment(0)),
-		_file(f)
-{
-}
-
-Atom::Atom(File& f, const char* name, ld::Atom::Scope s, ld::Atom::Definition d, ld::Atom::Alignment a)
-	: ld::Atom(f._section, d, ld::Atom::combineNever, s, ld::Atom::typeLTOtemporary, ld::Atom::symbolTableIn, false, false, a),
-		_file(f), _name(name), _compiledAtom(NULL)
-{
-}
-
-
-
-
-bool Parser::optimize(const std::vector<ld::Atom*>& allAtoms, std::vector<ld::Atom*>& newAtoms, 
-												std::vector<const char*>& additionalUndefines, 
-												const std::set<ld::Atom*>& deadAtoms,
-												std::vector<ld::Atom*>& newlyDeadAtoms,
-												uint32_t nextInputOrdinal, 
-												ld::OutFile* writer, ld::Atom* entryPointAtom,
-												const std::vector<const char*>& llvmOptions,
-												bool allGlobalsAReDeadStripRoots,
-												bool verbose, bool saveTemps, 
-												const char* outputFilePath,
-												bool pie, bool mainExecutable, bool staticExecutable, bool relocatable,
-												bool allowTextRelocs, cpu_type_t arch)
-{ 
-	// exit quickly if nothing to do
-	if ( _s_files.size() == 0 ) 
-		return false;
-	
-	// print out LTO version string if -v was used
-	if ( verbose )
-		fprintf(stderr, "%s\n", lto_get_version());
-	
-	// create optimizer and add each Reader
-	lto_code_gen_t generator = ::lto_codegen_create();
-	for (std::vector<File*>::iterator it=_s_files.begin(); it != _s_files.end(); ++it) {
-		if ( ::lto_codegen_add_module(generator, (*it)->module()) )
-			throwf("lto: could not merge in %s because %s", (*it)->path(), ::lto_get_error_message());
-	}
-
-	// add any -mllvm command line options
-	for (std::vector<const char*>::const_iterator it=llvmOptions.begin(); it != llvmOptions.end(); ++it) {
-		::lto_codegen_debug_options(generator, *it);
-	}
-
-	// The atom graph uses directed edges (references). Collect all references where 
-	// originating atom is not part of any LTO Reader. This allows optimizer to optimize an 
-	// external (i.e. not originated from same .o file) reference if all originating atoms are also 
-	// defined in llvm bitcode file.
-	CStringSet nonLLVMRefs;
-	CStringToAtom llvmAtoms;
-    bool hasNonllvmAtoms = false;
-	for (std::vector<ld::Atom*>::const_iterator it = allAtoms.begin(); it != allAtoms.end(); ++it) {
-		ld::Atom* atom = *it;
-		// only look at references that come from an atom that is not an llvm atom
-		if ( atom->contentType() != ld::Atom::typeLTOtemporary ) {
-			// remember if we've seen any atoms not from an llvm reader and not from the writer
-//			if ( atom->getFile() != writer )
-//				hasNonllvmAtoms = true;
-			for (ld::Fixup::iterator fit=atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
-				if ( fit->binding != ld::Fixup::bindingByNameBound )
-					continue;
-				// and reference an llvm atom
-				if ( fit->u.target->contentType() == ld::Atom::typeLTOtemporary ) 
-					nonLLVMRefs.insert(fit->u.target->name());
-			}
-		}
-		else {
-			llvmAtoms[atom->name()] = (Atom*)atom;
-		}
-	}
-	// if entry point is in a llvm bitcode file, it must be preserved by LTO
-	if ( entryPointAtom != NULL ) {
-		if ( entryPointAtom->contentType() == ld::Atom::typeLTOtemporary ) 
-			nonLLVMRefs.insert(entryPointAtom->name());
-	}
-	
-	// deadAtoms are the atoms that the linker coalesced.  For instance weak or tentative definitions
-	// overriden by another atom.  If any of these deadAtoms are llvm atoms and they were replaced
-	// with a mach-o atom, we need to tell the lto engine to preserve (not optimize away) its dead 
-	// atom so that the linker can replace it with the mach-o one later.
-	CStringToAtom deadllvmAtoms;
-	for (std::set<ld::Atom*>::iterator it = deadAtoms.begin(); it != deadAtoms.end(); ++it) {
-		ld::Atom* atom = *it;
-		if ( atom->contentType() == ld::Atom::typeLTOtemporary ) {
-			const char* name = atom->name();
-			::lto_codegen_add_must_preserve_symbol(generator, name);
-			deadllvmAtoms[name] = (Atom*)atom;
-		}
-	}
-
-	
-	// tell code generator about symbols that must be preserved
-	for (CStringToAtom::iterator it = llvmAtoms.begin(); it != llvmAtoms.end(); ++it) {
-		const char* name = it->first;
-		Atom* atom = it->second;
-		// Include llvm Symbol in export list if it meets one of following two conditions
-		// 1 - atom scope is global (and not linkage unit).
-		// 2 - included in nonLLVMRefs set.
-		// If a symbol is not listed in exportList then LTO is free to optimize it away.
-		if ( (atom->scope() == ld::Atom::scopeGlobal) ) 
-			::lto_codegen_add_must_preserve_symbol(generator, name);
-		else if ( nonLLVMRefs.find(name) != nonLLVMRefs.end() ) 
-			::lto_codegen_add_must_preserve_symbol(generator, name);
-	}
-	
-    // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o)
-    if ( relocatable && !hasNonllvmAtoms ) {
-		if ( ! ::lto_codegen_write_merged_modules(generator, outputFilePath) ) {
-			// HACK, no good way to tell linker we are all done, so just quit
-			exit(0);
-		}
-		warning("could not produce merged bitcode file");
-    }
-    
-	// set code-gen model
-	lto_codegen_model model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
-	if ( mainExecutable ) {
-		if ( staticExecutable ) {
-			// darwin x86_64 "static" code model is really dynamic code model
-			if ( arch == CPU_TYPE_X86_64 )
-				model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
-			else
-				model = LTO_CODEGEN_PIC_MODEL_STATIC;
-		}
-		else {
-			if ( pie )
-				model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
-			else
-				model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
-		}
-	}
-	else {
-		if ( allowTextRelocs )
-			model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
-		else
-			model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
-	}
-	if ( ::lto_codegen_set_pic_model(generator, model) )
-		throwf("could not create set codegen model: %s", lto_get_error_message());
-
-    // if requested, save off merged bitcode file
-    if ( saveTemps ) {
-        char tempBitcodePath[MAXPATHLEN];
-        strcpy(tempBitcodePath, outputFilePath);
-        strcat(tempBitcodePath, ".lto.bc");
-        ::lto_codegen_write_merged_modules(generator, tempBitcodePath);
-    }
-
-#if LTO_API_VERSION >= 3
-	// find assembler next to linker
-	char path[PATH_MAX];
-	uint32_t bufSize = PATH_MAX;
-	if ( _NSGetExecutablePath(path, &bufSize) != -1 ) {
-		char* lastSlash = strrchr(path, '/');
-		if ( lastSlash != NULL ) {
-			strcpy(lastSlash+1, "as");
-			struct stat statInfo;
-			if ( stat(path, &statInfo) == 0 )
-				::lto_codegen_set_assembler_path(generator, path);
-		}
-	}
-#endif
-	// run code generator
-	size_t machOFileLen;
-	const uint8_t* machOFile = (uint8_t*)::lto_codegen_compile(generator, &machOFileLen);
-	if ( machOFile == NULL ) 
-		throwf("could not do LTO codegen: %s", ::lto_get_error_message());
-	
-    // if requested, save off temp mach-o file
-    if ( saveTemps ) {
-        char tempMachoPath[MAXPATHLEN];
-        strcpy(tempMachoPath, outputFilePath);
-        strcat(tempMachoPath, ".lto.o");
-        int fd = ::open(tempMachoPath, O_CREAT | O_WRONLY | O_TRUNC, 0666);
-		if ( fd != -1) {
-			::write(fd, machOFile, machOFileLen);
-			::close(fd);
-		}
-		//	save off merged bitcode file
-		char tempOptBitcodePath[MAXPATHLEN];
-        strcpy(tempOptBitcodePath, outputFilePath);
-        strcat(tempOptBitcodePath, ".lto.opt.bc");
-        ::lto_codegen_write_merged_modules(generator, tempOptBitcodePath);
-	}
-
-	// parse generated mach-o file into a MachOReader
-	ld::File* machoFile = parseMachOFile(machOFile, machOFileLen, nextInputOrdinal, arch);
-	
-	// sync generated mach-o atoms with existing atoms ld knows about
-	AtomSyncer syncer(additionalUndefines,newAtoms,llvmAtoms,deadllvmAtoms);
-	machoFile->forEachAtom(syncer);
-			
-	// Remove InternalAtoms from ld
-	for (std::vector<File*>::iterator it=_s_files.begin(); it != _s_files.end(); ++it) {
-		newlyDeadAtoms.push_back(&((*it)->internalAtom()));
-	}
-	// Remove Atoms from ld if code generator optimized them away
-	for (CStringToAtom::iterator li = llvmAtoms.begin(), le = llvmAtoms.end(); li != le; ++li) {
-		// check if setRealAtom() called on this Atom
-		if ( li->second->compiledAtom() == NULL )
-			newlyDeadAtoms.push_back(li->second);
-	}
-	
-	return true;
-}
-
-
-void Parser::AtomSyncer::doAtom(ld::Atom& machoAtom)
-{
-	// update proxy atoms to point to real atoms and find new atoms
-	const char* name = machoAtom.name();
-	if ( machoAtom.scope() >= ld::Atom::scopeLinkageUnit ) {
-		CStringToAtom::iterator pos = llvmAtoms.find(name);
-		if ( pos != llvmAtoms.end() ) {
-			// turn Atom into a proxy for this mach-o atom
-			pos->second->setCompiledAtom(machoAtom);
-		}
-		else {
-			// an atom of this name was not in the allAtoms list the linker gave us
-			if ( deadllvmAtoms.find(name) != deadllvmAtoms.end() ) {
-				// this corresponding to an atom that the linker coalesced away.  
-				// Don't pass it back as a new atom
-			}
-			else
-			{
-				// this is something new that lto conjured up, tell ld its new
-				newAtoms.push_back(&machoAtom);
-			}
-		}
-	}
-	else {
-		// ld only knew about non-satic atoms, so this one must be new
-		newAtoms.push_back(&machoAtom);
-	}
-	
-	// adjust fixups to go through proxy atoms
-	for (ld::Fixup::iterator fit=machoAtom.fixupsBegin(); fit != machoAtom.fixupsEnd(); ++fit) {
-		switch ( fit->binding ) {
-			case ld::Fixup::bindingNone:
-				break;
-			case ld::Fixup::bindingByNameUnbound:
-				// don't know if this target has been seen by linker before or if it is new
-				// be conservitive and tell linker it is new
-				additionalUndefines.push_back(fit->u.name);
-				break;
-			case ld::Fixup::bindingByNameBound:
-				break;
-			case ld::Fixup::bindingDirectlyBound:
-				// If mach-o atom is referencing another mach-o atom then 
-				// reference is not going through Atom proxy. Fix it here to ensure that all
-				// llvm symbol references always go through Atom proxy.
-				break;
-			case ld::Fixup::bindingByContentBound:
-				break;
-		}
-	}
-
-}
-	
-
-
-}; // namespace lto
-
-
-#endif
-
diff --git a/src/ld/parsers/lto_file.cpp b/src/ld/parsers/lto_file.cpp
index fbba237..26d70be 100644
--- a/src/ld/parsers/lto_file.cpp
+++ b/src/ld/parsers/lto_file.cpp
@@ -33,6 +33,7 @@
 #include <pthread.h>
 #include <mach-o/dyld.h>
 #include <vector>
+#include <map>
 #include <unordered_set>
 #include <unordered_map>
 
@@ -118,6 +119,9 @@ public:
 																						_debugInfoModTime = modTime; 
 																						_cpuSubType = subtype;}
 
+    static bool                                         sSupportsLocalContext;
+    static bool                                         sHasTriedLocalContext;
+    bool                                                mergeIntoGenerator(lto_code_gen_t generator, bool useSetModule);
 private:
 	friend class Atom;
 	friend class InternalAtom;
@@ -128,6 +132,9 @@ private:
 	class Atom*								_atomArray;
 	uint32_t								_atomArrayCount;
 	lto_module_t							_module;
+	const char*                             _path;
+	const uint8_t*                          _content;
+	uint32_t                                _contentLength;
 	const char*								_debugInfoPath;
 	time_t									_debugInfoModTime;
 	ld::Section								_section;
@@ -303,8 +310,11 @@ ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, cons
 	objOpts.neverConvertDwarf   = false;
 	objOpts.verboseOptimizationHints = options.verboseOptimizationHints;
 	objOpts.armUsesZeroCostExceptions = options.armUsesZeroCostExceptions;
-
+	objOpts.simulator			= options.simulator;
+	objOpts.ignoreMismatchPlatform = options.ignoreMismatchPlatform;
+	objOpts.platform			= options.platform;
 	objOpts.subType				= 0;
+	objOpts.srcKind				= ld::relocatable::File::kSourceLTO;
 	
 	// mach-o parsing is done in-memory, but need path for debug notes
 	const char* path = "/tmp/lto.o";
@@ -326,7 +336,8 @@ ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, cons
 
 File::File(const char* pth, time_t mTime, ld::File::Ordinal ordinal, const uint8_t* content, uint32_t contentLength, cpu_type_t arch) 
 	: ld::relocatable::File(pth,mTime,ordinal), _architecture(arch), _internalAtom(*this), 
-	_atomArray(NULL), _atomArrayCount(0), _module(NULL), _debugInfoPath(pth), 
+	_atomArray(NULL), _atomArrayCount(0), _module(NULL), _path(pth),
+	_content(content), _contentLength(contentLength), _debugInfoPath(pth),
 	_section("__TEXT_", "__tmp_lto", ld::Section::typeTempLTO),
 	_fixupToInternal(0, ld::Fixup::k1of1, ld::Fixup::kindNone, &_internalAtom),
 	_debugInfo(ld::relocatable::File::kDebugInfoNone), _cpuSubType(0)
@@ -334,9 +345,19 @@ File::File(const char* pth, time_t mTime, ld::File::Ordinal ordinal, const uint8
 	const bool log = false;
 	
 	// create llvm module
+#if LTO_API_VERSION >= 11
+	if ( sSupportsLocalContext || !sHasTriedLocalContext ) {
+		_module = ::lto_module_create_in_local_context(content, contentLength, pth);
+	}
+	if ( !sHasTriedLocalContext ) {
+		sHasTriedLocalContext = true;
+		sSupportsLocalContext = (_module != NULL);
+	}
+	if ( (_module == NULL) && !sSupportsLocalContext )
+#endif
 #if LTO_API_VERSION >= 9
 	_module = ::lto_module_create_from_memory_with_path(content, contentLength, pth);
-	if ( _module == NULL )
+	if ( _module == NULL && !sSupportsLocalContext )
 #endif
 	_module = ::lto_module_create_from_memory(content, contentLength);
     if ( _module == NULL )
@@ -417,6 +438,11 @@ File::File(const char* pth, time_t mTime, ld::File::Ordinal ordinal, const uint8
 			if ( log ) fprintf(stderr, "\t%s (undefined)\n", name);
 		}
 	}
+
+#if LTO_API_VERSION >= 11
+	if ( sSupportsLocalContext )
+		this->release();
+#endif
 }
 
 File::~File()
@@ -424,6 +450,34 @@ File::~File()
 	this->release();
 }
 
+bool File::mergeIntoGenerator(lto_code_gen_t generator, bool useSetModule) {
+#if LTO_API_VERSION >= 11
+    if ( sSupportsLocalContext ) {
+        assert(!_module && "Expected module to be disposed");
+        _module = ::lto_module_create_in_codegen_context(_content, _contentLength,
+                                                        _path, generator);
+        if ( _module == NULL )
+            throwf("could not reparse object file %s: '%s', using libLTO version '%s'",
+                  _path, ::lto_get_error_message(), ::lto_get_version());
+    }
+#endif
+    assert(_module && "Expected module to stick around");
+#if LTO_API_VERSION >= 13
+    if (useSetModule) {
+        // lto_codegen_set_module will transfer ownership of the module to LTO code generator,
+        // so we don't need to release the module here.
+        ::lto_codegen_set_module(generator, _module);
+        return false;
+    }
+#endif
+    if ( ::lto_codegen_add_module(generator, _module) )
+        return true;
+
+    // <rdar://problem/15471128> linker should release module as soon as possible
+    this->release();
+    return false;
+}
+
 void File::release()
 {
 	if ( _module != NULL )
@@ -486,6 +540,8 @@ void Parser::ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity, co
 	switch ( severity ) {
 #if LTO_API_VERSION >= 10
 		case LTO_DS_REMARK:
+			fprintf(stderr, "ld: LTO remark: %s\n", message);
+			break;
 #endif
 		case LTO_DS_NOTE:
 		case LTO_DS_WARNING:
@@ -518,7 +574,13 @@ bool Parser::optimize(  const std::vector<const ld::Atom*>&	allAtoms,
 		fprintf(stderr, "%s\n", ::lto_get_version());
 	
 	// create optimizer and add each Reader
-	lto_code_gen_t generator = ::lto_codegen_create();
+	lto_code_gen_t generator = NULL;
+#if LTO_API_VERSION >= 11
+	if ( File::sSupportsLocalContext )
+		generator = ::lto_codegen_create_in_local_context();
+	else
+#endif
+		generator = ::lto_codegen_create();
 #if LTO_API_VERSION >= 7
 	lto_codegen_set_diagnostic_handler(generator, ltoDiagnosticHandler, NULL);
 #endif
@@ -526,14 +588,20 @@ bool Parser::optimize(  const std::vector<const ld::Atom*>&	allAtoms,
 	// <rdar://problem/12379604> The order that files are merged must match command line order
 	std::sort(_s_files.begin(), _s_files.end(), CommandLineOrderFileSorter());
 	ld::File::Ordinal lastOrdinal;
+
+	// When flto_codegen_only is on and we have a single .bc file, use lto_codegen_set_module instead of
+	// lto_codegen_add_module, to make sure the the destination module will be the same as the input .bc file.
+	bool useSetModule = false;
+#if LTO_API_VERSION >= 13
+	useSetModule = (_s_files.size() == 1) && options.ltoCodegenOnly && (::lto_api_version() >= 13);
+#endif
 	for (std::vector<File*>::iterator it=_s_files.begin(); it != _s_files.end(); ++it) {
 		File* f = *it;
 		assert(f->ordinal() > lastOrdinal);
-		if ( logBitcodeFiles ) fprintf(stderr, "lto_codegen_add_module(%s)\n", f->path());
-		if ( ::lto_codegen_add_module(generator, f->module()) )
+		if ( logBitcodeFiles && !useSetModule) fprintf(stderr, "lto_codegen_add_module(%s)\n", f->path());
+		if ( logBitcodeFiles && useSetModule) fprintf(stderr, "lto_codegen_set_module(%s)\n", f->path());
+		if ( f->mergeIntoGenerator(generator, useSetModule) )
 			throwf("lto: could not merge in %s because '%s', using libLTO version '%s'", f->path(), ::lto_get_error_message(), ::lto_get_version());
-		// <rdar://problem/15471128> linker should release module as soon as possible
-		f->release();
 		lastOrdinal = f->ordinal();
 	}
 
@@ -653,6 +721,9 @@ bool Parser::optimize(  const std::vector<const ld::Atom*>&	allAtoms,
 
     // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o)
     if ( options.relocatable && !hasNonllvmAtoms ) {
+#if LTO_API_VERSION >= 15
+		::lto_codegen_set_should_embed_uselists(generator, false);
+#endif
 		if ( ! ::lto_codegen_write_merged_modules(generator, options.outputFilePath) ) {
 			// HACK, no good way to tell linker we are all done, so just quit
 			exit(0);
@@ -691,6 +762,9 @@ bool Parser::optimize(  const std::vector<const ld::Atom*>&	allAtoms,
         char tempBitcodePath[MAXPATHLEN];
         strcpy(tempBitcodePath, options.outputFilePath);
         strcat(tempBitcodePath, ".lto.bc");
+#if LTO_API_VERSION >= 15
+        ::lto_codegen_set_should_embed_uselists(generator, true);
+#endif
         ::lto_codegen_write_merged_modules(generator, tempBitcodePath);
     }
 
@@ -708,11 +782,62 @@ bool Parser::optimize(  const std::vector<const ld::Atom*>&	allAtoms,
 		}
 	}
 #endif
-	// run code generator
-	size_t machOFileLen;
-	const uint8_t* machOFile = (uint8_t*)::lto_codegen_compile(generator, &machOFileLen);
-	if ( machOFile == NULL ) 
-		throwf("could not do LTO codegen: '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version());
+
+	// When lto API version is greater than or equal to 12, we use lto_codegen_optimize and lto_codegen_compile_optimized
+	// instead of lto_codegen_compile, and we save the merged bitcode file in between.
+	bool useSplitAPI = false;
+#if LTO_API_VERSION >= 12
+	if ( ::lto_api_version() >= 12)
+		useSplitAPI = true;
+#endif
+
+	size_t machOFileLen = 0;
+	const uint8_t* machOFile = NULL;
+	if ( useSplitAPI) {
+#if LTO_API_VERSION >= 12
+#if LTO_API_VERSION >= 14
+	if ( ::lto_api_version() >= 14 && options.ltoCodegenOnly)
+          lto_codegen_set_should_internalize(generator, false);
+#endif
+		// run optimizer
+		if ( !options.ltoCodegenOnly && ::lto_codegen_optimize(generator) )
+			throwf("could not do LTO optimization: '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version());
+
+		if ( options.saveTemps || options.bitcodeBundle ) {
+			// save off merged bitcode file
+			char tempOptBitcodePath[MAXPATHLEN];
+			strcpy(tempOptBitcodePath, options.outputFilePath);
+			strcat(tempOptBitcodePath, ".lto.opt.bc");
+#if LTO_API_VERSION >= 15
+			::lto_codegen_set_should_embed_uselists(generator, true);
+#endif
+			::lto_codegen_write_merged_modules(generator, tempOptBitcodePath);
+			if ( options.bitcodeBundle )
+				state.ltoBitcodePath = tempOptBitcodePath;
+		}
+
+		// run code generator
+		machOFile = (uint8_t*)::lto_codegen_compile_optimized(generator, &machOFileLen);
+#endif
+		if ( machOFile == NULL )
+			throwf("could not do LTO codegen: '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version());
+	}
+	else {
+		// run optimizer and code generator
+		machOFile = (uint8_t*)::lto_codegen_compile(generator, &machOFileLen);
+		if ( machOFile == NULL )
+			throwf("could not do LTO codegen: '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version());
+		if ( options.saveTemps ) {
+			// save off merged bitcode file
+			char tempOptBitcodePath[MAXPATHLEN];
+			strcpy(tempOptBitcodePath, options.outputFilePath);
+			strcat(tempOptBitcodePath, ".lto.opt.bc");
+#if LTO_API_VERSION >= 15
+			::lto_codegen_set_should_embed_uselists(generator, true);
+#endif
+			::lto_codegen_write_merged_modules(generator, tempOptBitcodePath);
+		}
+	}
 	
     // if requested, save off temp mach-o file
     if ( options.saveTemps ) {
@@ -724,11 +849,6 @@ bool Parser::optimize(  const std::vector<const ld::Atom*>&	allAtoms,
 			::write(fd, machOFile, machOFileLen);
 			::close(fd);
 		}
-		//	save off merged bitcode file
-		char tempOptBitcodePath[MAXPATHLEN];
-        strcpy(tempOptBitcodePath, options.outputFilePath);
-        strcat(tempOptBitcodePath, ".lto.opt.bc");
-        ::lto_codegen_write_merged_modules(generator, tempOptBitcodePath);
 	}
 
 	// if needed, save temp mach-o file to specific location
@@ -860,7 +980,7 @@ void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom)
 					}
 					else {
 						// <rdar://problem/12859831> Don't unbind follow-on reference into by-name reference 
-						if ( (_deadllvmAtoms.find(targetName) != _deadllvmAtoms.end()) && (fit->kind != ld::Fixup::kindNoneFollowOn) ) {
+						if ( (_deadllvmAtoms.find(targetName) != _deadllvmAtoms.end()) && (fit->kind != ld::Fixup::kindNoneFollowOn) && (fit->u.target->scope() != ld::Atom::scopeTranslationUnit) ) {
 							// target was coalesed away and replace by mach-o atom from a non llvm .o file
 							fit->binding = ld::Fixup::bindingByNameUnbound;
 							fit->u.name = targetName;
@@ -888,6 +1008,8 @@ public:
 	~Mutex() { pthread_mutex_unlock(&lto_lock); }
 };
 pthread_mutex_t Mutex::lto_lock = PTHREAD_MUTEX_INITIALIZER;
+bool File::sSupportsLocalContext = false;
+bool File::sHasTriedLocalContext = false;
 
 //
 // Used by archive reader to see if member is an llvm bitcode file
@@ -899,6 +1021,18 @@ bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t ar
 }
 
 
+static ld::relocatable::File *parseImpl(
+          const uint8_t *fileContent, uint64_t fileLength, const char *path,
+          time_t modTime, ld::File::Ordinal ordinal, cpu_type_t architecture,
+          cpu_subtype_t subarch, bool logAllFiles,
+          bool verboseOptimizationHints)
+{
+	if ( Parser::validFile(fileContent, fileLength, architecture, subarch) )
+		return Parser::parse(fileContent, fileLength, path, modTime, ordinal, architecture, subarch, logAllFiles, verboseOptimizationHints);
+	else
+		return NULL;
+}
+
 //
 // main function used by linker to instantiate ld::Files
 //
@@ -907,11 +1041,12 @@ ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength,
 								cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles,
 								bool verboseOptimizationHints)
 {
+	// Note: Once lto_module_create_in_local_context() and friends are thread safe
+	// this lock can be removed.
 	Mutex lock;
-	if ( Parser::validFile(fileContent, fileLength, architecture, subarch) )
-		return Parser::parse(fileContent, fileLength, path, modTime, ordinal, architecture, subarch, logAllFiles, verboseOptimizationHints);
-	else
-		return NULL;
+	return parseImpl(fileContent, fileLength, path, modTime, ordinal,
+					architecture, subarch, logAllFiles,
+					verboseOptimizationHints);
 }
 
 //
diff --git a/src/ld/parsers/lto_file.h b/src/ld/parsers/lto_file.h
index dcd6e36..6568232 100644
--- a/src/ld/parsers/lto_file.h
+++ b/src/ld/parsers/lto_file.h
@@ -48,6 +48,7 @@ struct OptimizeOptions {
 	bool								preserveAllGlobals;
 	bool								verbose; 
 	bool								saveTemps; 
+	bool								ltoCodegenOnly;
 	bool								pie; 
 	bool								mainExecutable; 
 	bool								staticExecutable; 
@@ -58,8 +59,12 @@ struct OptimizeOptions {
 	bool								keepDwarfUnwind; 
 	bool								verboseOptimizationHints;
 	bool								armUsesZeroCostExceptions;
+	bool								simulator;
+	bool								ignoreMismatchPlatform;
+	bool								bitcodeBundle;
 	cpu_type_t							arch;
 	const char*							mcpu;
+	Options::Platform					platform;
 	const std::vector<const char*>*		llvmOptions;
 	const std::vector<const char*>*		initialUndefines;
 };
diff --git a/src/ld/parsers/macho_dylib_file.cpp b/src/ld/parsers/macho_dylib_file.cpp
index a3c1456..0ba962c 100644
--- a/src/ld/parsers/macho_dylib_file.cpp
+++ b/src/ld/parsers/macho_dylib_file.cpp
@@ -1,4 +1,3 @@
-
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
  * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
@@ -33,11 +32,13 @@
 
 #include <vector>
 #include <set>
+#include <map>
 #include <algorithm>
 #include <unordered_map>
 #include <unordered_set>
 
 #include "Architectures.hpp"
+#include "Bitcode.hpp"
 #include "MachOFileAbstraction.hpp"
 #include "MachOTrie.hpp"
 #include "macho_dylib_file.h"
@@ -143,8 +144,10 @@ public:
 											File(const uint8_t* fileContent, uint64_t fileLength, const char* path,   
 													time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace, 
 													bool linkingMainExecutable, bool hoistImplicitPublicDylibs, 
-													ld::MacVersionMin macMin, ld::IOSVersionMin iPhoneMin, bool allowSimToMacOSX, bool addVers, 
-													bool logAllFiles, const char* installPath, bool indirectDylib);
+													Options::Platform platform, uint32_t linkMinOSVersion, bool allowSimToMacOSX,
+													bool addVers,  bool buildingForSimulator,
+													bool logAllFiles, const char* installPath,
+													bool indirectDylib, bool ignoreMismatchPlatform);
 	virtual									~File() {}
 
 	// overrides of ld::File
@@ -152,7 +155,9 @@ public:
 	virtual bool							justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const;
 	virtual ld::File::ObjcConstraint		objCConstraint() const		{ return _objcContraint; }
 	virtual uint8_t							swiftVersion() const		{ return _swiftVersion; }
-	
+	virtual uint32_t						minOSVersion() const		{ return _minVersionInDylib; }
+	virtual uint32_t						platformLoadCommand() const	{ return _platformInDylib; }
+
 	// overrides of ld::dylib::File
 	virtual void							processIndirectLibraries(ld::dylib::File::DylibHandler*, bool);
 	virtual bool							providedExportAtom() const	{ return _providedAtom; }
@@ -163,18 +168,12 @@ public:
 	virtual bool							hasPublicInstallName() const{ return _hasPublicInstallName; }
 	virtual bool							hasWeakDefinition(const char* name) const;
 	virtual bool							allSymbolsAreWeakImported() const;
-	virtual const void*						codeSignatureDR() const		{ return _codeSignatureDR; }
 	virtual bool							installPathVersionSpecific() const { return _installPathOverride; }
 	virtual bool							appExtensionSafe() const	{ return _appExtensionSafe; };
-	virtual ld::MacVersionMin				macMinVersion() const		{ return _macMinVersionInDylib; }
-	virtual ld::IOSVersionMin				iOSMinVersion() const		{ return _iOSMinVersionInDylib; }
-
+	virtual ld::Bitcode*					getBitcode() const			{ return _bitcode.get(); }
 
 protected:
-
-	struct ReExportChain { ReExportChain* prev; File<A>* file; };
-
-	void											assertNoReExportCycles(ReExportChain*);
+	virtual void							assertNoReExportCycles(ReExportChain*) const;
 
 private:
 	typedef typename A::P					P;
@@ -192,13 +191,14 @@ private:
 			return size_t(__h);
 		};
 	};
-	struct AtomAndWeak { ld::Atom* atom; bool weakDef; bool tlv; pint_t address; };
+	struct AtomAndWeak { ld::Atom* atom; bool weakDef; bool tlv; uint64_t address; };
 	typedef std::unordered_map<const char*, AtomAndWeak, ld::CStringHash, ld::CStringEquals> NameToAtomMap;
 	typedef std::unordered_set<const char*, CStringHash, ld::CStringEquals>  NameSet;
 
 	struct Dependent { const char* path; File<A>* dylib; bool reExport; };
 
-	bool										containsOrReExports(const char* name, bool* weakDef, bool* tlv, pint_t* defAddress) const;
+	virtual std::pair<bool, bool>				hasWeakDefinitionImpl(const char* name) const;
+	virtual bool								containsOrReExports(const char* name, bool& weakDef, bool& tlv, uint64_t& defAddress) const;
 	bool										isPublicLocation(const char* pth);
 	bool										wrongOS() { return _wrongOS; }
 	void										addSymbol(const char* name, bool weak, bool tlv, pint_t address);
@@ -211,9 +211,9 @@ private:
 	static uint32_t								parseVersionNumber32(const char* versionString);
 	static const char*							objCInfoSegmentName();
 	static const char*							objCInfoSectionName();
-	
-	const ld::MacVersionMin						_macVersionMin;
-	const ld::IOSVersionMin						_iOSVersionMin;
+
+	const Options::Platform						_platform;
+	const uint32_t								_linkMinOSVersion;
 	const bool									_allowSimToMacOSXLinking;
 	const bool									_addVersionLoadCommand;
 	bool										_linkingFlat;
@@ -228,7 +228,6 @@ private:
 	NameSet										_ignoreExports;
 	const char*									_parentUmbrella;
 	ImportAtom<A>*								_importAtom;
-	const void*									_codeSignatureDR;
 	bool										_noRexports;
 	bool										_hasWeakExports;
 	bool										_deadStrippable;
@@ -239,8 +238,9 @@ private:
 	bool										_installPathOverride;
 	bool										_indirectDylibsProcessed;
 	bool										_appExtensionSafe;
-	ld::MacVersionMin							_macMinVersionInDylib;
-	ld::IOSVersionMin							_iOSMinVersionInDylib;
+	uint32_t									_minVersionInDylib;
+	uint32_t									_platformInDylib;
+	std::unique_ptr<ld::Bitcode>				_bitcode;
 	
 	static bool									_s_logHashtable;
 };
@@ -259,20 +259,20 @@ template <typename A> const char* File<A>::objCInfoSectionName() { return "__ima
 template <typename A>
 File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth, time_t mTime, ld::File::Ordinal ord,
 				bool linkingFlatNamespace, bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
-				ld::MacVersionMin macMin, ld::IOSVersionMin iOSMin, bool allowSimToMacOSX, bool addVers,
-				bool logAllFiles, const char* targetInstallPath, bool indirectDylib)
+				Options::Platform platform, uint32_t linkMinOSVersion, bool allowSimToMacOSX, bool addVers, bool buildingForSimulator,
+				bool logAllFiles, const char* targetInstallPath, bool indirectDylib, bool ignoreMismatchPlatform)
 	: ld::dylib::File(strdup(pth), mTime, ord), 
-	_macVersionMin(macMin), _iOSVersionMin(iOSMin), _allowSimToMacOSXLinking(allowSimToMacOSX), _addVersionLoadCommand(addVers), 
+	_platform(platform), _linkMinOSVersion(linkMinOSVersion), _allowSimToMacOSXLinking(allowSimToMacOSX), _addVersionLoadCommand(addVers), 
 	_linkingFlat(linkingFlatNamespace), _implicitlyLinkPublicDylibs(hoistImplicitPublicDylibs),
 	_objcContraint(ld::File::objcConstraintNone), _swiftVersion(0),
 	_importProxySection("__TEXT", "__import", ld::Section::typeImportProxies, true),
 	_flatDummySection("__LINKEDIT", "__flat_dummy", ld::Section::typeLinkEdit, true),
-	_parentUmbrella(NULL), _importAtom(NULL), _codeSignatureDR(NULL), 
+	_parentUmbrella(NULL), _importAtom(NULL),
 	_noRexports(false), _hasWeakExports(false), 
 	_deadStrippable(false), _hasPublicInstallName(false), 
 	 _providedAtom(false), _explictReExportFound(false), _wrongOS(false), _installPathOverride(false), 
 	_indirectDylibsProcessed(false), _appExtensionSafe(false),
-	_macMinVersionInDylib(ld::macVersionUnset), _iOSMinVersionInDylib(ld::iOSVersionUnset)
+	_minVersionInDylib(0), _platformInDylib(Options::kPlatformUnknown)
 {
 	const macho_header<P>* header = (const macho_header<P>*)fileContent;
 	const uint32_t cmd_count = header->ncmds();
@@ -302,11 +302,11 @@ File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth,
 	// pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format
 	const macho_dysymtab_command<P>* dynamicInfo = NULL;
 	const macho_dyld_info_command<P>* dyldInfo = NULL;
-	const macho_linkedit_data_command<P>* codeSignature = NULL;
 	const macho_nlist<P>* symbolTable = NULL;
 	const char*	strings = NULL;
 	bool compressedLinkEdit = false;
 	uint32_t dependentLibCount = 0;
+	Options::Platform lcPlatform = Options::kPlatformUnknown;
 	const macho_load_command<P>* cmd = cmds;
 	for (uint32_t i = 0; i < cmd_count; ++i) {
 		macho_dylib_command<P>* dylibID;
@@ -348,29 +348,24 @@ File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth,
 				break;
 			case LC_SUB_CLIENT:
 				_allowableClients.push_back(strdup(((macho_sub_client_command<P>*)cmd)->client()));
+				// <rdar://problem/20627554> Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked
+				_hasPublicInstallName = false;
 				break;
 			case LC_VERSION_MIN_MACOSX:
-				if ( (_iOSVersionMin != ld::iOSVersionUnset) && !_allowSimToMacOSXLinking ) { 
-					_wrongOS = true;
-					if ( _addVersionLoadCommand && !indirectDylib )
-						throw "building for iOS Simulator, but linking against dylib built for MacOSX";
-				}
-				_macMinVersionInDylib = (ld::MacVersionMin)((macho_version_min_command<P>*)cmd)->version();
-				break;
 			case LC_VERSION_MIN_IPHONEOS:
-				if ( _macVersionMin != ld::macVersionUnset ) {
-					_wrongOS = true;
-					if ( _addVersionLoadCommand && !indirectDylib )
-						throw "building for MacOSX, but linking against dylib built for iOS Simulator";
-				}
-				_iOSMinVersionInDylib = (ld::IOSVersionMin)((macho_version_min_command<P>*)cmd)->version();
+			case LC_VERSION_MIN_WATCHOS:
+	#if SUPPORT_APPLE_TV
+			case LC_VERSION_MIN_TVOS:
+	#endif
+				_minVersionInDylib = (ld::MacVersionMin)((macho_version_min_command<P>*)cmd)->version();
+				_platformInDylib = cmd->cmd();
+				lcPlatform = Options::platformForLoadCommand(_platformInDylib);
 				break;
 			case LC_CODE_SIGNATURE:
-				codeSignature = (macho_linkedit_data_command<P>* )cmd;
 				break;
 			case macho_segment_command<P>::CMD:
 				// check for Objective-C info
-				if ( strcmp(((macho_segment_command<P>*)cmd)->segname(), objCInfoSegmentName()) == 0 ) {
+				if ( strncmp(((macho_segment_command<P>*)cmd)->segname(), objCInfoSegmentName(), 6) == 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()];
@@ -403,11 +398,88 @@ File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth,
 						}
 					}
 				}
+				// Construct bitcode if there is a bitcode bundle section in the dylib
+				// Record the size of the section because the content is not checked
+				else if ( strcmp(((macho_segment_command<P>*)cmd)->segname(), "__LLVM") == 0 ) {
+					const macho_section<P>* const sect = (macho_section<P>*)((char*)cmd + sizeof(macho_segment_command<P>));
+					if ( strncmp(sect->sectname(), "__bundle", 8) == 0 )
+						_bitcode = std::unique_ptr<ld::Bitcode>(new ld::Bitcode(NULL, sect->size()));
+				}
 		}
 		cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
 		if ( cmd > cmdsEnd )
 			throwf("malformed dylb, load command #%d is outside size of load commands in %s", i, pth);
 	}
+	// arm/arm64 objects are default to ios platform if not set.
+	// rdar://problem/21746314
+	if (lcPlatform == Options::kPlatformUnknown &&
+		(std::is_same<A, arm>::value || std::is_same<A, arm64>::value))
+		lcPlatform = Options::kPlatformiOS;
+
+	// check cross-linking
+	if ( lcPlatform != platform ) {
+		_wrongOS = true;
+		if ( _addVersionLoadCommand && !indirectDylib && !ignoreMismatchPlatform ) {
+			if ( buildingForSimulator ) {
+				if ( !_allowSimToMacOSXLinking ) {
+					switch (platform) {
+						case Options::kPlatformOSX:
+						case Options::kPlatformiOS:
+							if ( lcPlatform == Options::kPlatformUnknown )
+								break;
+							// fall through if the Platform is not Unknown
+						case Options::kPlatformWatchOS:
+							// WatchOS errors on cross-linking all the time.
+							throwf("building for %s simulator, but linking against dylib built for %s,",
+								   Options::platformName(platform),
+								   Options::platformName(lcPlatform));
+							break;
+	#if SUPPORT_APPLE_TV
+						case Options::kPlatform_tvOS:
+							// tvOS is a warning temporarily. rdar://problem/21746965
+							if (platform == Options::kPlatform_tvOS)
+								warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. "
+										"Note: This will be an error in the future.",
+										Options::platformName(platform), path(),
+										Options::platformName(lcPlatform));
+							break;
+	#endif
+						case Options::kPlatformUnknown:
+							// skip if the target platform is unknown
+							break;
+					}
+				}
+			}
+			else {
+				switch (platform) {
+					case Options::kPlatformOSX:
+					case Options::kPlatformiOS:
+						if ( lcPlatform == Options::kPlatformUnknown )
+							break;
+						// fall through if the Platform is not Unknown
+					case Options::kPlatformWatchOS:
+						// WatchOS errors on cross-linking all the time.
+						throwf("building for %s, but linking against dylib built for %s,",
+							   Options::platformName(platform),
+							   Options::platformName(lcPlatform));
+						break;
+	#if SUPPORT_APPLE_TV
+					case Options::kPlatform_tvOS:
+						// tvOS is a warning temporarily. rdar://problem/21746965
+						if (platform == Options::kPlatform_tvOS)
+							warning("URGENT: building for %s, but linking against dylib (%s) built for %s. "
+									"Note: This will be an error in the future.",
+									Options::platformName(platform), path(),
+									Options::platformName(lcPlatform));
+						break;
+	#endif
+					case Options::kPlatformUnknown:
+						// skip if the target platform is unknown
+						break;
+				}
+			}
+		}
+	}
 
 	// figure out if we need to examine dependent dylibs
 	// with compressed LINKEDIT format, MH_NO_REEXPORTED_DYLIBS can be trusted
@@ -441,7 +513,8 @@ File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth,
 		}
 		// verify MH_NO_REEXPORTED_DYLIBS bit was correct
 		if ( compressedLinkEdit && !linkingFlatNamespace ) {
-			assert(reExportDylibCount != 0);
+			if ( reExportDylibCount == 0 )
+				throwf("malformed dylib has MH_NO_REEXPORTED_DYLIBS flag but no LC_REEXPORT_DYLIB load commands: %s", pth);
 		}
 		// pass 3 add re-export info
 		cmd = cmds;
@@ -500,26 +573,7 @@ File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth,
 		}
 		_importAtom = new ImportAtom<A>(*this, importNames);
 	}
-	
-	// if the dylib is code signed, look for its Designated Requirement
-	if ( codeSignature != NULL ) {
-		const Security::BlobCore* overallSignature = (Security::BlobCore*)((char*)header + codeSignature->dataoff());
-		typedef Security::SuperBlob<Security::kSecCodeMagicEmbeddedSignature> EmbeddedSignatureBlob;
-		typedef Security::SuperBlob<Security::kSecCodeMagicRequirementSet> InternalRequirementsBlob;
-		const EmbeddedSignatureBlob* signature = EmbeddedSignatureBlob::specific(overallSignature);
-		if ( signature->validateBlob(codeSignature->datasize()) ) {
-			const InternalRequirementsBlob* ireq = signature->find<InternalRequirementsBlob>(Security::cdRequirementsSlot);
-			if ( (ireq != NULL) && ireq->validateBlob() ) {
-				const Security::BlobCore* dr = ireq->find(Security::kSecDesignatedRequirementType);
-				if ( (dr != NULL) && dr->validateBlob(Security::kSecCodeMagicRequirement) ) {
-					// <rdar://problem/10968461> make copy because mapped file is about to be unmapped
-					_codeSignatureDR = ::malloc(dr->length());
-					::memcpy((void*)_codeSignatureDR, dr, dr->length());
-				}
-			}
-		}
-	}
-	
+
 	// build hash table
 	if ( dyldInfo != NULL ) 
 		buildExportHashTableFromExportInfo(dyldInfo, fileContent);
@@ -530,6 +584,7 @@ File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth,
 	munmap((caddr_t)fileContent, fileLength);
 }
 
+
 //
 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
 //
@@ -634,15 +689,7 @@ void File<A>::addSymbol(const char* name, bool weakDef, bool tlv, pint_t address
 		const char* symCond = strchr(symAction, '$');
 		if ( symCond != NULL ) {
 			char curOSVers[16];
-			if ( _macVersionMin != ld::macVersionUnset ) {
-				sprintf(curOSVers, "$os%d.%d$", (_macVersionMin >> 16), ((_macVersionMin >> 8) & 0xFF));
-			}
-			else if ( _iOSVersionMin != ld::iOSVersionUnset ) {
-				sprintf(curOSVers, "$os%d.%d$", (_iOSVersionMin >> 16), ((_iOSVersionMin >> 8) & 0xFF));
-			}
-			else {
-				assert(0 && "targeting neither macosx nor iphoneos");
-			}
+			sprintf(curOSVers, "$os%d.%d$", (_linkMinOSVersion >> 16), ((_linkMinOSVersion >> 8) & 0xFF));
 			if ( strncmp(symCond, curOSVers, strlen(curOSVers)) == 0 ) {
 				const char* symName = strchr(&symCond[1], '$');
 				if ( symName != NULL ) {
@@ -705,29 +752,34 @@ bool File<A>::forEachAtom(ld::File::AtomHandler& handler) const
 	return false;
 }
 
+
+template <typename A>
+std::pair<bool, bool> File<A>::hasWeakDefinitionImpl(const char* name) const
+{
+	const auto pos = _atoms.find(name);
+	if ( pos != _atoms.end() )
+		return std::make_pair(true, pos->second.weakDef);
+
+	// look in children that I re-export
+	for (const auto &dep : _dependentDylibs) {
+		if ( dep.reExport ) {
+			auto ret = dep.dylib->hasWeakDefinitionImpl(name);
+			if ( ret.first )
+				return ret;
+		}
+	}
+	return std::make_pair(false, false);
+}
+
+
 template <typename A>
 bool File<A>::hasWeakDefinition(const char* name) const
 {
 	// if supposed to ignore this export, then pretend I don't have it
 	if ( _ignoreExports.count(name) != 0 )
 		return false;
-		
-	typename NameToAtomMap::const_iterator pos = _atoms.find(name);
-	if ( pos != _atoms.end() ) {
-		return pos->second.weakDef;
-	}
-	else {
-		// look in children that I re-export
-		for (typename std::vector<Dependent>::const_iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
-			if ( it->reExport ) {
-				//fprintf(stderr, "getJustInTimeAtomsFor: %s NOT found in %s, looking in child %s\n", name, this->path(), (*it)->getInstallPath());
-				typename NameToAtomMap::iterator cpos = it->dylib->_atoms.find(name);
-				if ( cpos != it->dylib->_atoms.end() ) 
-					return cpos->second.weakDef;
-			}
-		}
-	}
-	return false;
+
+	return hasWeakDefinitionImpl(name).second;
 }
 
 
@@ -756,24 +808,24 @@ bool File<A>::allSymbolsAreWeakImported() const
 
 
 template <typename A>
-bool File<A>::containsOrReExports(const char* name, bool* weakDef, bool* tlv, pint_t* defAddress) const
+bool File<A>::containsOrReExports(const char* name, bool& weakDef, bool& tlv, uint64_t& defAddress) const
 {
 	if ( _ignoreExports.count(name) != 0 )
 		return false;
 
 	// check myself
-	typename NameToAtomMap::iterator pos = _atoms.find(name);
+	const auto pos = _atoms.find(name);
 	if ( pos != _atoms.end() ) {
-		*weakDef = pos->second.weakDef;
-		*tlv = pos->second.tlv;
-		*defAddress = pos->second.address;
+		weakDef = pos->second.weakDef;
+		tlv = pos->second.tlv;
+		defAddress = pos->second.address;
 		return true;
 	}
 	
 	// check dylibs I re-export
-	for (typename std::vector<Dependent>::const_iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
-		if ( it->reExport && !it->dylib->implicitlyLinked() ) {
-			if ( it->dylib->containsOrReExports(name, weakDef, tlv, defAddress) )
+	for (const auto &dep : _dependentDylibs) {
+		if ( dep.reExport && !dep.dylib->implicitlyLinked() ) {
+			if ( dep.dylib->containsOrReExports(name, weakDef, tlv, defAddress) )
 				return true;
 		}
 	}
@@ -791,7 +843,7 @@ bool File<A>::justInTimeforEachAtom(const char* name, ld::File::AtomHandler& han
 	
 	
 	AtomAndWeak bucket;
-	if ( this->containsOrReExports(name, &bucket.weakDef, &bucket.tlv, &bucket.address) ) {
+	if ( this->containsOrReExports(name, bucket.weakDef, bucket.tlv, bucket.address) ) {
 		bucket.atom = new ExportAtom<A>(*this, name, bucket.weakDef, bucket.tlv, bucket.address);
 		_atoms[name] = bucket;
 		_providedAtom = true;
@@ -903,23 +955,23 @@ void File<A>::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, b
 }
 
 template <typename A>
-void File<A>::assertNoReExportCycles(ReExportChain* prev)
+void File<A>::assertNoReExportCycles(ReExportChain* prev) const
 {
 	// recursively check my re-exported dylibs
 	ReExportChain chain;
 	chain.prev = prev;
 	chain.file = this;
-	for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); it++) {
-		if ( it->reExport ) {
-			ld::File* child = it->dylib;
+	for (const auto &dep : _dependentDylibs) {
+		if ( dep.reExport ) {
+			ld::File* child = dep.dylib;
 			// check child is not already in chain 
-			for (ReExportChain* p = prev; p != NULL; p = p->prev) {
+			for (ReExportChain* p = prev; p != nullptr; p = p->prev) {
 				if ( p->file == child ) {
 					throwf("cycle in dylib re-exports with %s and %s", child->path(), this->path());
 				}
 			}
-			if ( it->dylib != NULL )
-				it->dylib->assertNoReExportCycles(&chain);
+			if ( dep.dylib != nullptr )
+				dep.dylib->assertNoReExportCycles(&chain);
 		}
 	}
 }
@@ -940,13 +992,15 @@ public:
 																			ordinal, opts.flatNamespace(), 
 																			opts.linkingMainExecutable(),
 																			opts.implicitlyLinkIndirectPublicDylibs(), 
-																			opts.macosxVersionMin(), 
-																			opts.iOSVersionMin(),
+																			opts.platform(), 
+																			opts.minOSversion(),
 																			opts.allowSimulatorToLinkWithMacOSX(),
 																			opts.addVersionLoadCommand(),
-																			opts.logAllFiles(), 
+																			opts.targetIOSSimulator(),
+																			opts.logAllFiles(),
 																			opts.installPath(),
-																			indirectDylib);
+																			indirectDylib,
+																			opts.outputKind() == Options::kPreload);
 														}
 
 };
diff --git a/src/ld/parsers/macho_relocatable_file.cpp b/src/ld/parsers/macho_relocatable_file.cpp
index 49d333e..c023f37 100644
--- a/src/ld/parsers/macho_relocatable_file.cpp
+++ b/src/ld/parsers/macho_relocatable_file.cpp
@@ -42,11 +42,13 @@
 #include <set>
 #include <map>
 #include <algorithm>
+#include <type_traits>
 
 #include "dwarf2.h"
 #include "debugline.h"
 
 #include "Architectures.hpp"
+#include "Bitcode.hpp"
 #include "ld.hpp"
 #include "macho_relocatable_file.h"
 
@@ -73,7 +75,7 @@ public:
 											File(const char* p, time_t mTime, const uint8_t* content, ld::File::Ordinal ord) :
 												ld::relocatable::File(p,mTime,ord), _fileContent(content),
 												_sectionsArray(NULL), _atomsArray(NULL),
-												_sectionsArrayCount(0), _atomsArrayCount(0),
+												_sectionsArrayCount(0), _atomsArrayCount(0), _aliasAtomsArrayCount(0),
 												_debugInfoKind(ld::relocatable::File::kDebugInfoNone),
 												_dwarfTranslationUnitPath(NULL), 
 												_dwarfDebugInfoSect(NULL), _dwarfDebugAbbrevSect(NULL), 
@@ -81,14 +83,19 @@ public:
 												_objConstraint(ld::File::objcConstraintNone),
 												_swiftVersion(0),
 												_cpuSubType(0),
-												_canScatterAtoms(false) {}
+												_minOSVersion(0),
+												_platform(0),
+												_canScatterAtoms(false),
+												_srcKind(kSourceUnknown) {}
 	virtual									~File();
 
 	// overrides of ld::File
 	virtual bool										forEachAtom(ld::File::AtomHandler&) const;
 	virtual bool										justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const
 																					{ return false; }
-	
+	virtual uint32_t									minOSVersion() const		{ return _minOSVersion; }
+	virtual uint32_t									platformLoadCommand() const	{ return _platform; }
+
 	// overrides of ld::relocatable::File 
 	virtual ObjcConstraint								objCConstraint() const			{ return _objConstraint; }
 	virtual uint32_t									cpuSubType() const				{ return _cpuSubType; }
@@ -98,6 +105,9 @@ public:
 	virtual const char*									translationUnitSource() const;
 	virtual LinkerOptionsList*							linkerOptions() const			{ return &_linkerOptions; }
 	virtual uint8_t										swiftVersion() const			{ return _swiftVersion; }
+	virtual ld::Bitcode*								getBitcode() const				{ return _bitcode.get(); }
+	virtual SourceKind									sourceKind() const				{ return _srcKind; }
+	virtual void										setSourceKind(SourceKind src)	{ _srcKind = src; }
 	
 	const uint8_t*										fileContent()					{ return _fileContent; }
 private:
@@ -128,8 +138,12 @@ private:
 	ld::File::ObjcConstraint				_objConstraint;
 	uint8_t									_swiftVersion;
 	uint32_t								_cpuSubType;
+	uint32_t								_minOSVersion;
+	uint32_t								_platform;
 	bool									_canScatterAtoms;
 	std::vector<std::vector<const char*> >	_linkerOptions;
+	std::unique_ptr<ld::Bitcode>			_bitcode;
+	SourceKind								_srcKind;
 };
 
 
@@ -148,6 +162,7 @@ public:
 	virtual ld::Atom::Alignment		alignmentForAddress(pint_t addr);
 	virtual ld::Atom::ContentType	contentType()				{ return ld::Atom::typeUnclassified; }
 	virtual bool					dontDeadStrip()				{ return (this->_machOSection->flags() & S_ATTR_NO_DEAD_STRIP); }
+	virtual bool					dontDeadStripIfReferencesLive() { return ( (this->_machOSection != NULL) && (this->_machOSection->flags() & S_ATTR_LIVE_SUPPORT) );  }
 	virtual	Atom<A>*				findAtomByAddress(pint_t addr) { return this->findContentAtomByAddress(addr, this->_beginAtoms, this->_endAtoms); }
 	virtual bool					addFollowOnFixups() const	{ return ! _file.canScatterAtoms(); }
 	virtual uint32_t				appendAtoms(class Parser<A>& parser, uint8_t* buffer, 
@@ -506,6 +521,30 @@ private:
 	static ld::Fixup::Kind			fixupKind();
 };
 
+template <typename A>
+class TLVPointerSection : public FixedSizeSection<A>
+{
+public:
+						TLVPointerSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
+							: FixedSizeSection<A>(parser, f, s) {}
+protected:
+	typedef typename A::P::uint_t	pint_t;
+	typedef typename A::P			P;
+
+	virtual ld::Atom::ContentType	contentType()							{ return ld::Atom::typeTLVPointer; }
+	virtual ld::Atom::Alignment		alignmentForAddress(pint_t addr)		{ return ld::Atom::Alignment(log2(sizeof(pint_t))); }
+	virtual const char*				unlabeledAtomName(Parser<A>&, pint_t)	{ return "tlv_lazy_ptr"; }
+	virtual	pint_t					elementSizeAtAddress(pint_t addr)		{ return sizeof(pint_t); }
+	virtual ld::Atom::Combine		combine(Parser<A>&, pint_t);
+	virtual	bool					ignoreLabel(const char* label) const 	{ return true; }
+	virtual unsigned long			contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
+	virtual bool					canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs, 
+													const ld::IndirectBindingTable& ind) const;
+
+private:
+	static const char*				targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind, bool* isStatic);
+};
+
 
 template <typename A>
 class CFStringSection : public FixedSizeSection<A>
@@ -752,7 +791,7 @@ public:
 																parser.combineFromSymbol(sym), parser.scopeFromSymbol(sym),
 																parser.resolverFromSymbol(sym) ? ld::Atom::typeResolver : sct.contentType(), 
 																parser.inclusionFromSymbol(sym), 
-																parser.dontDeadStripFromSymbol(sym) || sct.dontDeadStrip(),
+																(parser.dontDeadStripFromSymbol(sym) && !sct.dontDeadStripIfReferencesLive()) || sct.dontDeadStrip(),
 																parser.isThumbFromSymbol(sym), alias, 
 																sct.alignmentForAddress(sym.n_value())),
 															_size(sz), _objAddress(sym.n_value()), 
@@ -764,7 +803,9 @@ public:
 																if ( _scope == ld::Atom::scopeGlobal && 
 																		(sym.n_desc() & (N_WEAK_DEF|N_WEAK_REF)) == (N_WEAK_DEF|N_WEAK_REF) )
 																	this->setAutoHide();
-																	this->verifyAlignment(*sct.machoSection());
+																this->verifyAlignment(*sct.machoSection());
+																if ( sct.dontDeadStripIfReferencesLive() )
+																	this->setDontDeadStripIfReferencesLive();
 															}
 
 private:
@@ -936,15 +977,18 @@ public:
 	static bool										validFile(const uint8_t* fileContent, bool subtypeMustMatch=false, 
 																cpu_subtype_t subtype=0);
 	static const char*								fileKind(const uint8_t* fileContent);
+	static Options::Platform						findPlatform(const macho_header<typename A::P>* header);
 	static bool										hasObjC2Categories(const uint8_t* fileContent);
 	static bool										hasObjC1Categories(const uint8_t* fileContent);
+	static bool										getNonLocalSymbols(const uint8_t* fileContnet, std::vector<const char*> &syms);
 	static ld::relocatable::File*					parse(const uint8_t* fileContent, uint64_t fileLength, 
 															const char* path, time_t modTime, ld::File::Ordinal ordinal,
 															 const ParserOptions& opts) {
 																Parser p(fileContent, fileLength, path, modTime, 
 																		ordinal, opts.warnUnwindConversionProblems,
 																		opts.keepDwarfUnwind, opts.forceDwarfConversion,
-																		opts.neverConvertDwarf, opts.verboseOptimizationHints);
+																		opts.neverConvertDwarf, opts.verboseOptimizationHints,
+																		opts.ignoreMismatchPlatform);
 																return p.parse(opts);
 														}
 
@@ -1114,7 +1158,7 @@ private:
 						sectionTypeUTF16Strings, sectionTypeCFString, sectionTypeObjC2ClassRefs, typeObjC2CategoryList,
 						sectionTypeObjC1Classes, sectionTypeSymboled, sectionTypeObjC1ClassRefs,
 						sectionTypeTentativeDefinitions, sectionTypeAbsoluteSymbols, sectionTypeTLVDefs,
-						sectionTypeCompactUnwind };
+						sectionTypeCompactUnwind, sectionTypeTLVPointers};
 
 	template <typename P>
 	struct MachOSectionAndSectionClass
@@ -1141,10 +1185,11 @@ private:
 													Parser(const uint8_t* fileContent, uint64_t fileLength, 
 															const char* path, time_t modTime, ld::File::Ordinal ordinal, 
 															bool warnUnwindConversionProblems, bool keepDwarfUnwind,
-															bool forceDwarfConversion, bool neverConvertDwarf, bool verboseOptimizationHints);
+															bool forceDwarfConversion, bool neverConvertDwarf,
+															bool verboseOptimizationHints, bool ignoreMismatchPlatform);
 	ld::relocatable::File*							parse(const ParserOptions& opts);
-	uint8_t											loadCommandSizeMask();
-	bool											parseLoadCommands();
+	static uint8_t									loadCommandSizeMask();
+	bool											parseLoadCommands(Options::Platform platform, uint32_t minOSVersion, bool simulator, bool ignoreMismatchPlatform);
 	void											makeSections();
 	void											prescanSymbolTable();
 	void											makeSortedSymbolsArray(uint32_t symArray[], const uint32_t sectionArray[]);
@@ -1209,6 +1254,7 @@ private:
 	bool										_neverConvertDwarf;
 	bool										_verboseOptimizationHints;
 	bool										_armUsesZeroCostExceptions;
+	bool										_ignoreMismatchPlatform;
 	unsigned int								_stubsSectionNum;
 	const macho_section<P>*						_stubsMachOSection;
 	std::vector<const char*>					_dtraceProviderInfo;
@@ -1220,7 +1266,7 @@ private:
 template <typename A>
 Parser<A>::Parser(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, 
 					ld::File::Ordinal ordinal, bool convertDUI, bool keepDwarfUnwind, bool forceDwarfConversion, 
-					bool neverConvertDwarf, bool verboseOptimizationHints)
+					bool neverConvertDwarf, bool verboseOptimizationHints, bool ignoreMismatchPlatform)
 		: _fileContent(fileContent), _fileLength(fileLength), _path(path), _modTime(modTime),
 			_ordinal(ordinal), _file(NULL),
 			_symbols(NULL), _symbolCount(0), _indirectSymbolCount(0), _strings(NULL), _stringsSize(0),
@@ -1236,6 +1282,7 @@ Parser<A>::Parser(const uint8_t* fileContent, uint64_t fileLength, const char* p
 			_keepDwarfUnwind(keepDwarfUnwind), _forceDwarfConversion(forceDwarfConversion),
 			_neverConvertDwarf(neverConvertDwarf),
 			_verboseOptimizationHints(verboseOptimizationHints),
+			_ignoreMismatchPlatform(ignoreMismatchPlatform),
 			_stubsSectionNum(0), _stubsMachOSection(NULL)
 {
 }
@@ -1318,7 +1365,7 @@ template <>
 const char* Parser<x86_64>::fileKind(const uint8_t* fileContent)
 {
 	const macho_header<P>* header = (const macho_header<P>*)fileContent;
-	if ( header->magic() != MH_MAGIC )
+	if ( header->magic() != MH_MAGIC_64 )
 		return NULL;
 	if ( header->cputype() != CPU_TYPE_X86_64 )
 		return NULL;
@@ -1346,7 +1393,7 @@ template <>
 const char* Parser<arm64>::fileKind(const uint8_t* fileContent)
 {
 	const macho_header<P>* header = (const macho_header<P>*)fileContent;
-	if ( header->magic() != MH_MAGIC )
+	if ( header->magic() != MH_MAGIC_64 )
 		return NULL;
 	if ( header->cputype() != CPU_TYPE_ARM64 )
 		return NULL;
@@ -1411,6 +1458,39 @@ bool Parser<A>::hasObjC1Categories(const uint8_t* fileContent)
 	return false;
 }
 
+
+template <typename A>
+bool Parser<A>::getNonLocalSymbols(const uint8_t* fileContent, std::vector<const char*> &syms)
+{
+	const macho_header<P>* header = (const macho_header<P>*)fileContent;
+	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>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
+	const macho_load_command<P>* cmd = cmds;
+	for (uint32_t i = 0; i < cmd_count; ++i) {
+		if ( cmd->cmd() == LC_SYMTAB ) {
+			const macho_symtab_command<P>* symtab = (macho_symtab_command<P>*)cmd;
+			uint32_t symbolCount = symtab->nsyms();
+			const macho_nlist<P>* symbols = (const macho_nlist<P>*)(fileContent + symtab->symoff());
+			const char* strings = (char*)fileContent + symtab->stroff();
+			for (uint32_t i = 0; i < symbolCount; ++i) {
+				// ignore stabs and count only ext symbols
+				if ( (symbols[i].n_type() & N_STAB) == 0 &&
+					 (symbols[i].n_type() & N_EXT) != 0 ) {
+					const char* symName = &strings[symbols[i].n_strx()];
+					syms.push_back(symName);
+				}
+			}
+			return true;
+		}
+		cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
+		if ( cmd > cmdsEnd )
+			throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
+	}
+	return false;
+}
+
+
 template <typename A>
 int Parser<A>::pointerSorter(const void* l, const void* r)
 {
@@ -1634,6 +1714,9 @@ ld::relocatable::File* Parser<A>::parse(const ParserOptions& opts)
 	// create file object
 	_file = new File<A>(_path, _modTime, _fileContent, _ordinal);
 
+	// set input source
+	_file->setSourceKind(opts.srcKind);
+
 	// respond to -t option
 	if ( opts.logAllFiles )
 		printf("%s\n", _path);
@@ -1641,7 +1724,7 @@ ld::relocatable::File* Parser<A>::parse(const ParserOptions& opts)
 	_armUsesZeroCostExceptions = opts.armUsesZeroCostExceptions;
 
 	// parse start of mach-o file
-	if ( ! parseLoadCommands() )
+	if ( ! parseLoadCommands(opts.platform, opts.minOSVersion, opts.simulator, opts.ignoreMismatchPlatform) )
 		return _file;
 	
 	// make array of
@@ -1797,7 +1880,7 @@ ld::relocatable::File* Parser<A>::parse(const ParserOptions& opts)
 		p += sizeof(Atom<A>);
 	}
 	assert(fixupOffset == _allFixups.size());
-	_file->_fixups.reserve(fixupOffset);
+	_file->_fixups.resize(fixupOffset);
 	
 	// copy each fixup for each atom 
 	for(typename std::vector<FixupInAtom>::iterator it=_allFixups.begin(); it != _allFixups.end(); ++it) {
@@ -1871,6 +1954,13 @@ ld::relocatable::File* Parser<A>::parse(const ParserOptions& opts)
 	return _file;
 }
 
+static void versionToString(uint32_t value, char buffer[32])
+{
+	if ( value & 0xFF )
+		sprintf(buffer, "%d.%d.%d", value >> 16, (value >> 8) & 0xFF, value & 0xFF);
+	else
+		sprintf(buffer, "%d.%d", value >> 16, (value >> 8) & 0xFF);
+}
 
 template <> uint8_t Parser<x86>::loadCommandSizeMask()		{ return 0x03; }
 template <> uint8_t Parser<x86_64>::loadCommandSizeMask()	{ return 0x07; }
@@ -1878,7 +1968,7 @@ template <> uint8_t Parser<arm>::loadCommandSizeMask()		{ return 0x03; }
 template <> uint8_t Parser<arm64>::loadCommandSizeMask()	{ return 0x07; }
 
 template <typename A>
-bool Parser<A>::parseLoadCommands()
+bool Parser<A>::parseLoadCommands(Options::Platform platform, uint32_t linkMinOSVersion, bool simulator, bool ignoreMismatchPlatform)
 {
 	const macho_header<P>* header = (const macho_header<P>*)_fileContent;
 
@@ -1892,6 +1982,7 @@ bool Parser<A>::parseLoadCommands()
 	// <rdar://problem/5394172> an empty .o file with zero load commands will crash linker
 	if ( cmd_count == 0 )
 		return false;
+	Options::Platform lcPlatform = Options::kPlatformUnknown;
 	const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
 	const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
 	const macho_load_command<P>* cmd = cmds;
@@ -1970,6 +2061,18 @@ bool Parser<A>::parseLoadCommands()
 						throw "LC_LINKER_OPTIMIZATION_HINTS table extends beyond end of file";
 				}
 				break;
+			case LC_VERSION_MIN_MACOSX:
+			case LC_VERSION_MIN_IPHONEOS:
+			case LC_VERSION_MIN_WATCHOS:
+	#if SUPPORT_APPLE_TV
+			case LC_VERSION_MIN_TVOS:
+	#endif
+				if ( ignoreMismatchPlatform )
+					break;
+				_file->_platform = cmd->cmd();
+				lcPlatform = Options::platformForLoadCommand(cmd->cmd());
+				_file->_minOSVersion = ((macho_version_min_command<P>*)cmd)->version();
+				break;
 			default:
 				if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
 					if ( segment != NULL )
@@ -1982,6 +2085,52 @@ bool Parser<A>::parseLoadCommands()
 		if ( cmd > cmdsEnd )
 			throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
 	}
+	// arm/arm64 objects are default to ios platform if not set.
+	// rdar://problem/21746314
+	if (lcPlatform == Options::kPlatformUnknown &&
+		(std::is_same<A, arm>::value || std::is_same<A, arm64>::value))
+		lcPlatform = Options::kPlatformiOS;
+
+	// Check platform cross-linking.
+	if ( !ignoreMismatchPlatform ) {
+		if ( lcPlatform != platform ) {
+			switch (platform) {
+				case Options::kPlatformOSX:
+				case Options::kPlatformiOS:
+					if ( lcPlatform == Options::kPlatformUnknown )
+						break;
+					// fall through if the Platform is not Unknown
+				case Options::kPlatformWatchOS:
+					// WatchOS errors on cross-linking all the time.
+					throwf("building for %s%s, but linking in object file built for %s,",
+						   Options::platformName(platform), (simulator ? " simulator" : ""),
+						   Options::platformName(lcPlatform));
+					break;
+	#if SUPPORT_APPLE_TV
+				case Options::kPlatform_tvOS:
+					// tvOS is a warning temporarily. rdar://problem/21746965
+					if (platform == Options::kPlatform_tvOS)
+						warning("URGENT: building for %s%s, but linking in object file (%s) built for %s. "
+								"Note: This will be an error in the future.",
+								Options::platformName(platform), (simulator ? " simulator" : ""), path(),
+								Options::platformName(lcPlatform));
+					break;
+	#endif
+				case Options::kPlatformUnknown:
+					// skip if the target platform is unknown
+					break;
+			}
+		}
+		if ( linkMinOSVersion && (_file->_minOSVersion > linkMinOSVersion) ) {
+			char t1[32];
+			char t2[32];
+			versionToString(_file->_minOSVersion, t1);
+			versionToString(linkMinOSVersion, t2);
+			warning("object file (%s) was built for newer %s version (%s) than being linked (%s)",
+					_path, Options::platformName(lcPlatform), t1, t2);
+		}
+	}
+
 
 	// record range of sections
 	if ( segment == NULL ) 
@@ -1992,6 +2141,35 @@ bool Parser<A>::parseLoadCommands()
 	return true;
 }
 
+template <typename A>
+Options::Platform Parser<A>::findPlatform(const macho_header<P>* header)
+{
+	const uint32_t cmd_count = header->ncmds();
+	if ( cmd_count == 0 )
+		return Options::kPlatformUnknown;
+	const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
+	const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
+	const macho_load_command<P>* cmd = cmds;
+	for (uint32_t i = 0; i < cmd_count; ++i) {
+		uint32_t size = cmd->cmdsize();
+		if ( (size & loadCommandSizeMask()) != 0 )
+			throwf("load command #%d has a unaligned size", i);
+		const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize();
+		if ( endOfCmd > (uint8_t*)cmdsEnd )
+			throwf("load command #%d extends beyond the end of the load commands", i);
+		switch (cmd->cmd()) {
+			case LC_VERSION_MIN_MACOSX:
+				return Options::kPlatformOSX;
+			case LC_VERSION_MIN_IPHONEOS:
+				return Options::kPlatformiOS;
+		}
+		cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
+		if ( cmd > cmdsEnd )
+			throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
+	}
+	return Options::kPlatformUnknown;
+}
+
 
 template <typename A>
 void Parser<A>::prescanSymbolTable()
@@ -2258,6 +2436,13 @@ void Parser<A>::makeSections()
 	// allocate raw storage for all section objects on stack
 	MachOSectionAndSectionClass<P>* machOSects = (MachOSectionAndSectionClass<P>*)machOSectsStorage;
 	unsigned int count = 0;
+	// local variable for bitcode parsing
+	const macho_section<P>* bitcodeSect = NULL;
+	const macho_section<P>*	cmdlineSect = NULL;
+	const macho_section<P>*	swiftCmdlineSect = NULL;
+	const macho_section<P>*	bundleSect = NULL;
+	bool bitcodeAsm = false;
+
 	for (uint32_t i=0; i < _machOSectionsCount; ++i) {
 		const macho_section<P>* sect = &_sectionsStart[i];
 		if ( (sect->flags() & S_ATTR_DEBUG) != 0 ) {
@@ -2285,6 +2470,23 @@ void Parser<A>::makeSections()
 				}
 			}
 		}
+		if ( strcmp(sect->segname(), "__LLVM") == 0 ) {
+			if ( strncmp(sect->sectname(), "__bitcode", 9) == 0 ) {
+				bitcodeSect = sect;
+			} else if ( strncmp(sect->sectname(), "__cmdline", 9) == 0 ) {
+				cmdlineSect = sect;
+			} else if ( strncmp(sect->sectname(), "__swift_cmdline", 15) == 0 ) {
+				swiftCmdlineSect = sect;
+			} else if ( strncmp(sect->sectname(), "__bundle", 8) == 0 ) {
+				bundleSect = sect;
+			} else if ( strncmp(sect->sectname(), "__asm", 5) == 0 ) {
+				bitcodeAsm = true;
+			}
+			// If it is not single input for ld -r, don't count the section
+			// otherwise, fall through and add it to the sections.
+			if (_file->sourceKind() != ld::relocatable::File::kSourceSingle)
+				continue;
+		}
 		// ignore empty __OBJC sections
 		if ( (sect->size() == 0) && (strcmp(sect->segname(), "__OBJC") == 0) )
 			continue;
@@ -2348,6 +2550,10 @@ void Parser<A>::makeSections()
 				totalSectionsSize += sizeof(NonLazyPointerSection<A>);
 				machOSects[count++].type = sectionTypeNonLazy;
 				break;
+			case S_THREAD_LOCAL_VARIABLE_POINTERS:
+				totalSectionsSize += sizeof(TLVPointerSection<A>);
+				machOSects[count++].type = sectionTypeTLVPointers;
+				break;
 			case S_LITERAL_POINTERS:
 				if ( (strcmp(sect->segname(), "__OBJC") == 0) && (strcmp(sect->sectname(), "__cls_refs") == 0) ) {
 					totalSectionsSize += sizeof(Objc1ClassReferences<A>);
@@ -2404,11 +2610,26 @@ void Parser<A>::makeSections()
 				totalSectionsSize += sizeof(TLVDefsSection<A>);
 				machOSects[count++].type = sectionTypeTLVDefs;
 				break;
-			case S_THREAD_LOCAL_VARIABLE_POINTERS:
 			default:
 				throwf("unknown section type %d", sect->flags() & SECTION_TYPE);
 		}
 	}
+
+	// Create bitcode
+	if ( bitcodeSect != NULL ) {
+		if ( cmdlineSect != NULL )
+			_file->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::ClangBitcode(&_fileContent[bitcodeSect->offset()], bitcodeSect->size(),
+																				&_fileContent[cmdlineSect->offset()], cmdlineSect->size()));
+		else if ( swiftCmdlineSect != NULL )
+			_file->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::SwiftBitcode(&_fileContent[bitcodeSect->offset()], bitcodeSect->size(),
+																				&_fileContent[swiftCmdlineSect->offset()], swiftCmdlineSect->size()));
+		else
+			throwf("Object file with bitcode missing cmdline options: %s", _file->path());
+	}
+	else if ( bundleSect != NULL )
+		_file->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::BundleBitcode(&_fileContent[bundleSect->offset()], bundleSect->size()));
+	else if ( bitcodeAsm )
+		_file->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::AsmBitcode(_fileContent, _fileLength));
 	
 	// sort by address (mach-o object files don't aways have sections sorted)
 	::qsort(machOSects, count, sizeof(MachOSectionAndSectionClass<P>), MachOSectionAndSectionClass<P>::sorter);
@@ -2451,6 +2672,10 @@ void Parser<A>::makeSections()
 				*objects++ = new (space) NonLazyPointerSection<A>(*this, *_file, machOSects[i].sect);
 				space += sizeof(NonLazyPointerSection<A>);
 				break;
+			case sectionTypeTLVPointers:
+				*objects++ = new (space) TLVPointerSection<A>(*this, *_file, machOSects[i].sect);
+				space += sizeof(TLVPointerSection<A>);
+				break;
 			case sectionTypeCFI:
 				_EHFrameSection = new (space) CFISection<A>(*this, *_file, machOSects[i].sect);
 				*objects++ = _EHFrameSection;
@@ -3481,7 +3706,7 @@ void Parser<A>::parseDebugInfo()
 		p += sizeof(Atom<A>);
 	}
 	assert(liOffset == entries.size());
-	_file->_lineInfos.reserve(liOffset);
+	_file->_lineInfos.resize(liOffset);
 
 	// copy each line info for each atom 
 	for (typename std::vector<AtomAndLineInfo<A> >::iterator it = entries.begin(); it != entries.end(); ++it) {
@@ -3853,8 +4078,6 @@ const char* File<A>::translationUnitSource() const
 	return _dwarfTranslationUnitPath;
 }
 
-
-
 template <typename A>
 bool File<A>::forEachAtom(ld::File::AtomHandler& handler) const
 {
@@ -4014,6 +4237,8 @@ ld::Section::Type Section<A>::sectionType(const macho_section<typename A::P>* se
 			return ld::Section::typeTLVZeroFill;
 		case S_THREAD_LOCAL_VARIABLES:
 			return ld::Section::typeTLVDefs;
+		case S_THREAD_LOCAL_VARIABLE_POINTERS:
+			return ld::Section::typeTLVPointers;
 		case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS:
 			return ld::Section::typeTLVInitializerPointers;
 	}
@@ -4728,6 +4953,7 @@ const char* CUSection<arm64>::personalityName(class Parser<arm64>& parser, const
 		const pint_t* content = (pint_t*)(this->file().fileContent() + this->_machOSection->offset() + reloc->r_address());
 		pint_t personalityAddr = *content;
 		Section<arm64>* personalitySection = parser.sectionForAddress(personalityAddr);
+		(void)personalitySection;
 		assert((personalitySection->type() == ld::Section::typeCode) && "personality column in __compact_unwind section is not pointer to function");
 		// atoms may not be constructed yet, so scan symbol table for labels
 		const char* name = parser.scanSymbolTableForAddress(personalityAddr);
@@ -5468,6 +5694,73 @@ ld::Atom::Scope NonLazyPointerSection<A>::scopeAtAddress(Parser<A>& parser, pint
 		return ld::Atom::scopeLinkageUnit; 
 }
 
+
+
+template <typename A>
+ld::Atom::Combine TLVPointerSection<A>::combine(Parser<A>& parser, pint_t addr)
+{
+	return ld::Atom::combineByNameAndReferences;
+}
+
+
+template <typename A>
+const char* TLVPointerSection<A>::targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind, bool* isStatic)
+{
+	assert(atom->combine() == ld::Atom::combineByNameAndReferences);
+	assert(atom->fixupCount() == 1);
+	*isStatic = false;
+	ld::Fixup::iterator fit = atom->fixupsBegin();
+	const char* name = NULL;
+	switch ( fit->binding ) {
+		case ld::Fixup::bindingByNameUnbound:
+			name = fit->u.name;
+			break;
+		case ld::Fixup::bindingByContentBound:
+			name = fit->u.target->name();
+			break;
+		case ld::Fixup::bindingsIndirectlyBound:
+			name = ind.indirectName(fit->u.bindingIndex);
+			break;
+		case ld::Fixup::bindingDirectlyBound:
+			name = fit->u.target->name();
+			*isStatic = (fit->u.target->scope() == ld::Atom::scopeTranslationUnit);
+			break;
+		default:
+			assert(0);
+	}
+	assert(name != NULL);
+	return name;
+}
+
+template <typename A>
+unsigned long TLVPointerSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
+{
+	assert(atom->combine() == ld::Atom::combineByNameAndReferences);
+	unsigned long hash = 9508;
+	bool isStatic;
+	for (const char* s = this->targetName(atom, ind, &isStatic); *s != '\0'; ++s) {
+		hash = hash * 33 + *s;
+	}
+	return hash;
+}
+
+template <typename A>
+bool TLVPointerSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
+													const ld::IndirectBindingTable& indirectBindingTable) const
+{
+	if ( rhs.section().type() != ld::Section::typeTLVPointers )
+		return false;
+	assert(this->type() == rhs.section().type());
+	const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
+	assert(rhsAtom !=  NULL);
+	bool thisIsStatic;
+	bool rhsIsStatic;
+	const char* thisName = this->targetName(atom, indirectBindingTable, &thisIsStatic);
+	const char* rhsName = this->targetName(rhsAtom, indirectBindingTable, &rhsIsStatic);
+	return !thisIsStatic && !rhsIsStatic && (strcmp(thisName, rhsName) == 0);
+}
+
+
 template <typename A>
 const uint8_t* CFStringSection<A>::targetContent(const class Atom<A>* atom, const ld::IndirectBindingTable& ind,
 													ContentType* ct, unsigned int* count)
@@ -6826,7 +7119,8 @@ bool Section<arm64>::addRelocFixup(class Parser<arm64>& parser, const macho_relo
 		case ARM64_RELOC_UNSIGNED:
 			if ( reloc->r_pcrel() )
 				throw "pcrel and ARM64_RELOC_UNSIGNED not supported";
-			target.addend = contentValue;
+			if ( reloc->r_extern() )
+				target.addend = contentValue;
 			switch ( reloc->r_length() ) {
 				case 0:
 				case 1:
@@ -7451,28 +7745,34 @@ bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, const ParserO
 //
 // used by linker to infer architecture when no -arch is on command line
 //
-bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult)
+bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult, Options::Platform* platform)
 {
 	if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
 		*result = CPU_TYPE_X86_64;
 		const macho_header<Pointer64<LittleEndian> >* header = (const macho_header<Pointer64<LittleEndian> >*)fileContent;
 		*subResult = header->cpusubtype();
+		*platform = Parser<x86_64>::findPlatform(header);
 		return true;
 	}
 	if ( mach_o::relocatable::Parser<x86>::validFile(fileContent) ) {
+		const macho_header<Pointer32<LittleEndian> >* header = (const macho_header<Pointer32<LittleEndian> >*)fileContent;
 		*result = CPU_TYPE_I386;
 		*subResult = CPU_SUBTYPE_X86_ALL;
+		*platform = Parser<x86>::findPlatform(header);
 		return true;
 	}
 	if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
-		*result = CPU_TYPE_ARM;
 		const macho_header<Pointer32<LittleEndian> >* header = (const macho_header<Pointer32<LittleEndian> >*)fileContent;
+		*result = CPU_TYPE_ARM;
 		*subResult = header->cpusubtype();
+		*platform = Parser<arm>::findPlatform(header);
 		return true;
 	}
 	if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, false, 0) ) {
+		const macho_header<Pointer64<LittleEndian> >* header = (const macho_header<Pointer64<LittleEndian> >*)fileContent;
 		*result = CPU_TYPE_ARM64;
 		*subResult = CPU_SUBTYPE_ARM64_ALL;
+		*platform = Parser<arm64>::findPlatform(header);
 		return true;
 	}
 	return false;
@@ -7528,6 +7828,26 @@ bool hasObjC1Categories(const uint8_t* fileContent)
 	return false;
 }
 
+//
+// Used by bitcode obfuscator to get a list of non local symbols from object file
+//
+bool getNonLocalSymbols(const uint8_t* fileContent, std::vector<const char*> &syms)
+{
+	if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
+		return mach_o::relocatable::Parser<x86_64>::getNonLocalSymbols(fileContent, syms);
+	}
+	else if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
+		return mach_o::relocatable::Parser<arm>::getNonLocalSymbols(fileContent, syms);
+	}
+	else if ( mach_o::relocatable::Parser<x86>::validFile(fileContent, false, 0) ) {
+		return mach_o::relocatable::Parser<x86>::getNonLocalSymbols(fileContent, syms);
+	}
+	else if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, false, 0) ) {
+		return mach_o::relocatable::Parser<arm64>::getNonLocalSymbols(fileContent, syms);
+	}
+	return false;
+}
+
 
 
 } // namespace relocatable
diff --git a/src/ld/parsers/macho_relocatable_file.h b/src/ld/parsers/macho_relocatable_file.h
index 92e9042..40f02d6 100644
--- a/src/ld/parsers/macho_relocatable_file.h
+++ b/src/ld/parsers/macho_relocatable_file.h
@@ -41,7 +41,12 @@ struct ParserOptions {
 	bool			neverConvertDwarf;
 	bool			verboseOptimizationHints;
 	bool			armUsesZeroCostExceptions;
+	bool			simulator;
+	bool			ignoreMismatchPlatform;
 	uint32_t		subType;
+	Options::Platform platform;
+	uint32_t		minOSVersion;
+	ld::relocatable::File::SourceKind	srcKind;
 };
 
 extern ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength, 
@@ -50,13 +55,15 @@ extern ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLen
 									
 extern bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, const ParserOptions& opts);
 
-extern bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult);					
+extern bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult, Options::Platform* platform);
 
 extern bool hasObjC2Categories(const uint8_t* fileContent);					
 
 extern bool hasObjC1Categories(const uint8_t* fileContent);
 
-extern const char* archName(const uint8_t* fileContent);					
+extern const char* archName(const uint8_t* fileContent);
+
+bool getNonLocalSymbols(const uint8_t* fileContent, std::vector<const char*> &syms);
 
 } // namespace relocatable
 } // namespace mach_o
diff --git a/src/ld/parsers/opaque_section_file.cpp b/src/ld/parsers/opaque_section_file.cpp
index e60332b..081e957 100644
--- a/src/ld/parsers/opaque_section_file.cpp
+++ b/src/ld/parsers/opaque_section_file.cpp
@@ -24,6 +24,7 @@
 
 
 #include <vector>
+#include <map>
 
 #include "ld.hpp"
 #include "opaque_section_file.h"
@@ -63,7 +64,7 @@ public:
 									const char* symbolName="sect_create")
 									: ld::File(pth, 0, ld::File::Ordinal::NullOrdinal(), Other),
 									  _atom(*this, symbolName, fileContent, fileLength), 
-									  _section(segmentName, sectionName, ld::Section::typeUnclassified) { }
+									  _section(segmentName, sectionName, ld::Section::typeSectCreate) { }
 	virtual						~File() { }
 	
 	virtual bool				forEachAtom(ld::File::AtomHandler& h) const { h.doAtom(_atom); return true; }
diff --git a/src/ld/parsers/textstub_dylib_file.cpp b/src/ld/parsers/textstub_dylib_file.cpp
new file mode 100644
index 0000000..cde3344
--- /dev/null
+++ b/src/ld/parsers/textstub_dylib_file.cpp
@@ -0,0 +1,1072 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015 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 <sys/param.h>
+#include <sys/mman.h>
+
+#include <vector>
+
+#include "Architectures.hpp"
+#include "bitcode.hpp"
+#include "MachOFileAbstraction.hpp"
+#include "MachOTrie.hpp"
+#include "textstub_dylib_file.hpp"
+
+namespace {
+
+///
+/// A token is a light-weight reference to the content of an nmap'ed file. It
+/// doesn't own the data and it doesn't make a copy of it. The referenced data
+/// is only valid as long as the file is mapped in.
+///
+class Token {
+	const char* _p;
+	size_t _size;
+
+	int compareMemory(const char* lhs, const char* rhs, size_t size) const {
+		if (size == 0)
+			return 0;
+		return ::memcmp(lhs, rhs, size);
+	}
+
+public:
+	Token() : _p(nullptr), _size(0) {}
+
+	Token(const char* p) : _p(p), _size(0) {
+		if (p)
+			_size = ::strlen(p);
+	}
+
+	Token(const char* p, size_t s) : _p(p), _size(s) {}
+
+	const char* data() const { return _p; }
+
+	size_t size() const { return _size; }
+
+	std::string str() const { return std::move(std::string(_p, _size)); }
+
+	bool empty() const { return _size == 0; }
+
+	bool operator==(Token other) const {
+		if (_size != other._size)
+			return false;
+		return compareMemory(_p, other._p, _size) == 0;
+	}
+
+	bool operator!=(Token other) const {
+		return !(*this == other);
+	}
+};
+
+///
+/// Simple text-based dynamic library file tokenizer.
+///
+class Tokenizer {
+	const char* _start;
+	const char* _current;
+	const char* _end;
+	Token _currentToken;
+
+	void fetchNextToken();
+	void scanToNextToken();
+	void skip(unsigned distance) {
+		_current += distance;
+		assert(_current <= _end && "Skipped past the end");
+	}
+
+	const char* skipLineBreak(const char* pos) const;
+	bool isDelimiter(const char* pos) const;
+
+public:
+	Tokenizer(const char* data, uint64_t size) : _start(data), _current(data), _end(data + size) {}
+
+	void reset() {
+		_current = _start;
+		fetchNextToken();
+	}
+
+	Token peek() { return _currentToken; }
+	Token next() {
+		Token token = peek();
+		fetchNextToken();
+		return token;
+	}
+};
+
+const char* Tokenizer::skipLineBreak(const char* pos) const
+{
+	if ( pos == _end )
+		return pos;
+
+	// Carriage return.
+	if ( *pos == 0x0D ) {
+		// line feed.
+		if ( pos + 1 != _end && *(pos + 1) == 0x0A)
+			return pos + 2;
+		return pos + 1;
+	}
+
+	// line feed.
+	if ( *pos == 0x0A )
+		return pos + 1;
+
+	return pos;
+}
+
+void Tokenizer::scanToNextToken() {
+	while (true) {
+		while ( isDelimiter(_current) )
+			skip(1);
+
+		const char* i = skipLineBreak(_current);
+		if ( i == _current )
+			break;
+
+		_current = i;
+	}
+}
+
+
+bool Tokenizer::isDelimiter(const char* pos) const {
+	if ( pos == _end )
+		return false;
+	if ( *pos == ' ' || *pos == '\t' || *pos == '\r' || *pos == '\n' || *pos == ',' || *pos == ':' || *pos == '\'' || *pos == '\"' )
+		return true;
+	return false;
+}
+
+void Tokenizer::fetchNextToken() {
+	scanToNextToken();
+
+	if (_current == _end) {
+		_currentToken = Token();
+		return;
+	}
+
+	auto start = _current;
+	while ( !isDelimiter(_current) ) {
+		++_current;
+	}
+
+	_currentToken = Token(start, _current - start);
+}
+
+///
+/// Representation of a parsed text-based dynamic library file.
+///
+struct DynamicLibrary {
+	Token _installName;
+	uint32_t _currentVersion;
+	uint32_t _compatibilityVersion;
+	uint8_t _swiftVersion;
+	ld::File::ObjcConstraint _objcConstraint;
+	Options::Platform _platform;
+	std::vector<Token> _allowedClients;
+	std::vector<Token> _reexportedLibraries;
+	std::vector<Token> _symbols;
+	std::vector<Token> _classes;
+	std::vector<Token> _ivars;
+	std::vector<Token> _weakDefSymbols;
+	std::vector<Token> _tlvSymbols;
+
+	DynamicLibrary() : _currentVersion(0x10000), _compatibilityVersion(0x10000), _swiftVersion(0),
+		_objcConstraint(ld::File::objcConstraintNone)  {}
+};
+
+static uint32_t parseVersionNumber32(Token token) {
+	if ( token.size() >= 128 )
+		throwf("malformed version number");
+
+	char buffer[128];
+	uint32_t x = 0;
+	uint32_t y = 0;
+	uint32_t z = 0;
+	char* end;
+
+	// Make a null-terminated string.
+	::memcpy(buffer, token.data(), token.size());
+	buffer[token.size()] = '\0';
+
+	x = strtoul(buffer, &end, 10);
+	if ( *end == '.' ) {
+		y = strtoul(&end[1], &end, 10);
+		if ( *end == '.' ) {
+			z = strtoul(&end[1], &end, 10);
+		}
+	}
+	if ( (x > 0xffff) || (y > 0xff) || (z > 0xff) )
+		throwf("malformed 32-bit x.y.z version number: %s", buffer);
+
+	return (x << 16) | ( y << 8 ) | z;
+}
+
+///
+/// A simple text-based dynamic library file parser.
+///
+class TBDFile {
+	Tokenizer _tokenizer;
+
+	Token peek() { return _tokenizer.peek(); }
+	Token next() { return _tokenizer.next(); }
+
+	void expectToken(Token str) {
+		Token token = next();
+		if (token != str)
+			throwf("unexpected token: %s", token.str().c_str());
+	}
+
+	bool hasOptionalToken(Token str) {
+		auto token = peek();
+		if ( token == str ) {
+			next();
+			return true;
+		}
+		return false;
+	}
+
+
+	void parseFlowSequence(std::function<void (Token)> func) {
+		expectToken("[");
+
+		while ( true ) {
+			auto token = peek();
+			if ( token == "]" )
+				break;
+
+			token = next();
+			func(token);
+		}
+
+		expectToken("]");
+	}
+
+	void parseAllowedClients(DynamicLibrary& lib) {
+		if ( !hasOptionalToken("allowed-clients") )
+			return;
+		parseFlowSequence([&](Token name) {
+			lib._allowedClients.emplace_back(name);
+		});
+	}
+
+	void parseReexportedDylibs(DynamicLibrary& lib) {
+		if ( !hasOptionalToken("re-exports") )
+			return;
+		parseFlowSequence([&](Token name) {
+			lib._reexportedLibraries.emplace_back(name);
+		});
+	}
+
+	void parseSymbols(DynamicLibrary& lib) {
+		if ( hasOptionalToken("symbols") ) {
+			parseFlowSequence([&](Token name) {
+				lib._symbols.emplace_back(name);
+			});
+		}
+
+		if ( hasOptionalToken("objc-classes") ) {
+			parseFlowSequence([&](Token name) {
+				lib._classes.emplace_back(name);
+			});
+		}
+
+		if ( hasOptionalToken("objc-ivars") ) {
+			parseFlowSequence([&](Token name) {
+				lib._ivars.emplace_back(name);
+			});
+		}
+
+		if ( hasOptionalToken("weak-def-symbols") ) {
+			parseFlowSequence([&](Token name) {
+				lib._weakDefSymbols.emplace_back(name);
+			});
+		}
+
+		if ( hasOptionalToken("thread-local-symbols") ) {
+			parseFlowSequence([&](Token name) {
+				lib._tlvSymbols.emplace_back(name);
+			});
+		}
+	}
+
+	bool parseArchFlowSequence(Token archName) {
+		expectToken("archs");
+
+		bool foundArch = false;
+		parseFlowSequence([&](Token name) {
+			if ( name == archName )
+				foundArch = true;
+			});
+
+		return foundArch;
+	}
+
+	void parsePlatform(DynamicLibrary& lib) {
+		expectToken("platform");
+
+		auto token =  next();
+		if (token == "macosx")
+			lib._platform = Options::kPlatformOSX;
+		else if (token == "ios")
+			lib._platform = Options::kPlatformiOS;
+		else if (token == "watchos")
+			lib._platform = Options::kPlatformWatchOS;
+#if SUPPORT_APPLE_TV
+		else if (token == "tvos")
+			lib._platform = Options::kPlatform_tvOS;
+#endif
+		else
+			lib._platform = Options::kPlatformUnknown;
+	}
+
+	void parseInstallName(DynamicLibrary& lib) {
+		expectToken("install-name");
+
+		lib._installName = next();
+		if ( lib._installName.empty() )
+			throwf("no install name specified");
+	}
+
+	void parseCurrentVersion(DynamicLibrary& lib) {
+		if ( !hasOptionalToken("current-version") )
+			return;
+		lib._currentVersion = parseVersionNumber32(next());
+	}
+
+	void parseCompatibilityVersion(DynamicLibrary& lib) {
+		if ( !hasOptionalToken("compatibility-version") )
+			return;
+		lib._compatibilityVersion = parseVersionNumber32(next());
+	}
+
+	void parseSwiftVersion(DynamicLibrary& lib) {
+		if ( !hasOptionalToken("swift-version") )
+			return;
+		auto token = next();
+		if ( token == "1.0" )
+			lib._swiftVersion = 1;
+		else if ( token == "1.1" )
+			lib._swiftVersion = 2;
+		else if ( token == "2.0" )
+			lib._swiftVersion = 3;
+		else
+			throwf("unsupported Swift ABI version: %s", token.str().c_str());
+	}
+
+	void parseObjCConstraint(DynamicLibrary& lib) {
+		if ( !hasOptionalToken("objc-constraint") )
+			return;
+		auto token = next();
+		if ( token == "none" )
+			lib._objcConstraint = ld::File::objcConstraintNone;
+		else if ( token == "retain_release" )
+			lib._objcConstraint = ld::File::objcConstraintRetainRelease;
+		else if ( token == "retain_release_for_simulator" )
+			lib._objcConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
+		else if ( token == "retain_release_or_gc" )
+			lib._objcConstraint = ld::File::objcConstraintRetainReleaseOrGC;
+		else if ( token == "gc" )
+			lib._objcConstraint = ld::File::objcConstraintGC;
+		else
+			throwf("unexpected token: %s", token.str().c_str());
+	}
+	void parseExportsBlock(DynamicLibrary& lib, Token archName) {
+		if ( !hasOptionalToken("exports") )
+			return;
+
+		if ( !hasOptionalToken("-") )
+			return;
+
+		while ( true ) {
+			if ( !parseArchFlowSequence(archName) ) {
+				Token token;
+				while ( true ) {
+					token = peek();
+					if ( token == "archs" || token == "..." || token.empty() )
+						break;
+					next();
+				}
+				if (token == "..." || token.empty() )
+					break;
+
+				continue;
+			}
+
+			parseAllowedClients(lib);
+			parseReexportedDylibs(lib);
+			parseSymbols(lib);
+			if ( !hasOptionalToken("-") )
+				break;
+		}
+	}
+
+	void parseDocument(DynamicLibrary& lib, Token archName) {
+		if ( !parseArchFlowSequence(archName) )
+			throwf("invalid arch");
+
+		parsePlatform(lib);
+		parseInstallName(lib);
+		parseCurrentVersion(lib);
+		parseCompatibilityVersion(lib);
+		parseSwiftVersion(lib);
+		parseObjCConstraint(lib);
+		parseExportsBlock(lib, archName);
+	}
+
+public:
+	TBDFile(const char* data, uint64_t size) : _tokenizer(data, size) {}
+
+	DynamicLibrary parseFileForArch(Token archName) {
+		_tokenizer.reset();
+		DynamicLibrary lib;
+		expectToken("---");
+		parseDocument(lib, archName);
+		expectToken("...");
+		return std::move(lib);
+	}
+
+	bool validForArch(Token archName) {
+		_tokenizer.reset();
+		auto token = next();
+		if ( token != "---" )
+			return false;
+		return parseArchFlowSequence(archName);
+	}
+
+	void dumpTokens() {
+		_tokenizer.reset();
+		Token token;
+		do {
+			token = next();
+			printf("token: %s\n", token.str().c_str());
+		} while ( !token.empty() );
+	}
+};
+
+} // end anonymous namespace
+
+namespace textstub {
+namespace dylib {
+
+// forward reference
+template <typename A> class File;
+
+
+//
+// An ExportAtom has no content.  It exists so that the linker can track which imported
+// symbols came from which dynamic libraries.
+//
+template <typename A>
+class ExportAtom : public ld::Atom
+{
+public:
+	ExportAtom(const File<A>& f, const char* nm, bool weakDef, bool tlv)
+		: ld::Atom(f._importProxySection, ld::Atom::definitionProxy,
+				   (weakDef? ld::Atom::combineByName : ld::Atom::combineNever),
+				   ld::Atom::scopeLinkageUnit,
+				   (tlv ? ld::Atom::typeTLV : ld::Atom::typeUnclassified),
+				   symbolTableNotIn, false, false, false, ld::Atom::Alignment(0)),
+				   _file(f), _name(nm) {}
+	// overrides of ld::Atom
+	virtual const ld::File*			file() const		{ return &_file; }
+	virtual const char*				name() const		{ return _name; }
+	virtual uint64_t				size() const		{ return 0; }
+	virtual uint64_t				objectAddress() const { return 0; }
+	virtual void					copyRawContent(uint8_t buffer[]) const { }
+	virtual void					setScope(Scope)		{ }
+
+protected:
+	typedef typename A::P			P;
+	typedef typename A::P::uint_t	pint_t;
+
+	virtual							~ExportAtom() {}
+
+	const File<A>&					_file;
+	const char*						_name;
+};
+
+
+//
+// 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
+// savings for large dylibs.
+//
+template <typename A>
+class File : public ld::dylib::File
+{
+public:
+	static bool		validFile(const uint8_t* fileContent, bool executableOrDylib);
+					File(const uint8_t* fileContent, uint64_t fileLength, const char* path,
+						 time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace,
+						 bool hoistImplicitPublicDylibs, Options::Platform platform,
+						 cpu_type_t cpuType, const char* archName, uint32_t linkMinOSVersion,
+						 bool allowSimToMacOSX, bool addVers, bool buildingForSimulator,
+						 bool logAllFiles, const char* installPath, bool indirectDylib);
+	virtual			~File() {}
+
+	// overrides of ld::File
+	virtual bool							forEachAtom(ld::File::AtomHandler&) const;
+	virtual bool							justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const;
+	virtual ld::File::ObjcConstraint		objCConstraint() const		{ return _objcConstraint; }
+	virtual uint8_t							swiftVersion() const		{ return _swiftVersion; }
+
+	// overrides of ld::dylib::File
+	virtual void							processIndirectLibraries(ld::dylib::File::DylibHandler*, bool);
+	virtual bool							providedExportAtom() const	{ return _providedAtom; }
+	virtual const char*						parentUmbrella() const { return nullptr; }
+	virtual const std::vector<const char*>*	allowableClients() const	{ return _allowableClients.size() != 0 ? &_allowableClients : nullptr; }
+	virtual bool							hasWeakExternals() const	{ return _hasWeakExports; }
+	virtual bool							deadStrippable() const		{ return false; }
+	virtual bool							hasPublicInstallName() const{ return _hasPublicInstallName; }
+	virtual bool							hasWeakDefinition(const char* name) const;
+	virtual bool							allSymbolsAreWeakImported() const;
+	virtual bool							installPathVersionSpecific() const { return _installPathOverride; }
+	// All text-based stubs are per definition AppExtensionSafe.
+	virtual bool							appExtensionSafe() const	{ return true; };
+	virtual ld::Bitcode*					getBitcode() const			{ return _bitcode.get(); }
+
+
+protected:
+	virtual void							assertNoReExportCycles(ReExportChain*) const;
+
+private:
+	typedef typename A::P					P;
+	typedef typename A::P::E				E;
+	typedef typename A::P::uint_t			pint_t;
+
+	friend class ExportAtom<A>;
+
+	struct CStringHash {
+		std::size_t operator()(const char* __s) const {
+			unsigned long __h = 0;
+			for ( ; *__s; ++__s)
+				__h = 5 * __h + *__s;
+			return size_t(__h);
+		};
+	};
+	struct AtomAndWeak { ld::Atom* atom; bool weakDef; bool tlv; };
+	typedef std::unordered_map<const char*, AtomAndWeak, ld::CStringHash, ld::CStringEquals> NameToAtomMap;
+	typedef std::unordered_set<const char*, CStringHash, ld::CStringEquals>  NameSet;
+
+	struct Dependent { const char* path; File<A>* dylib; };
+
+	virtual std::pair<bool, bool>			hasWeakDefinitionImpl(const char* name) const;
+	virtual bool							containsOrReExports(const char* name, bool& weakDef, bool& tlv, uint64_t& address) const;
+
+	void									buildExportHashTable(const DynamicLibrary &lib);
+	bool									isPublicLocation(const char* pth);
+	bool									wrongOS() { return _wrongOS; }
+	void									addSymbol(const char* name, bool weak, bool tlv);
+
+	const Options::Platform					_platform;
+	cpu_type_t								_cpuType;
+	const uint32_t							_linkMinOSVersion;
+	const bool								_allowSimToMacOSXLinking;
+	const bool								_addVersionLoadCommand;
+	bool									_linkingFlat;
+	bool									_implicitlyLinkPublicDylibs;
+	ld::File::ObjcConstraint				_objcConstraint;
+	uint8_t									_swiftVersion;
+	ld::Section								_importProxySection;
+	ld::Section								_flatDummySection;
+	std::vector<Dependent>					_dependentDylibs;
+	std::vector<const char*>				_allowableClients;
+	mutable NameToAtomMap					_atoms;
+	NameSet									_ignoreExports;
+	bool									_noRexports;
+	bool									_hasWeakExports;
+	bool									_hasPublicInstallName;
+	mutable bool							_providedAtom;
+	bool									_wrongOS;
+	bool									_installPathOverride;
+	bool									_indirectDylibsProcessed;
+	std::unique_ptr<ld::Bitcode>			_bitcode;
+	static bool								_s_logHashtable;
+};
+
+template <typename A>
+bool File<A>::_s_logHashtable = false;
+
+
+template <typename A>
+File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t mTime,
+			  ld::File::Ordinal ord, bool linkingFlatNamespace, bool hoistImplicitPublicDylibs,
+			  Options::Platform platform, cpu_type_t cpuType, const char* archName,
+			  uint32_t linkMinOSVersion, bool allowSimToMacOSX, bool addVers,
+			  bool buildingForSimulator, bool logAllFiles, const char* targetInstallPath,
+			  bool indirectDylib)
+	: ld::dylib::File(strdup(path), mTime, ord), _platform(platform), _cpuType(cpuType),
+	  _linkMinOSVersion(linkMinOSVersion), _allowSimToMacOSXLinking(allowSimToMacOSX),
+	  _addVersionLoadCommand(addVers), _linkingFlat(linkingFlatNamespace),
+	  _implicitlyLinkPublicDylibs(hoistImplicitPublicDylibs),
+	  _objcConstraint(ld::File::objcConstraintNone), _swiftVersion(0),
+	  _importProxySection("__TEXT", "__import", ld::Section::typeImportProxies, true),
+	  _flatDummySection("__LINKEDIT", "__flat_dummy", ld::Section::typeLinkEdit, true),
+	  _noRexports(false), _hasWeakExports(false),
+	  _hasPublicInstallName(false), _providedAtom(false), _wrongOS(false),
+	  _installPathOverride(false), _indirectDylibsProcessed(false),
+	  _bitcode(new ld::Bitcode(nullptr, 0))
+{
+	// write out path for -t option
+	if ( logAllFiles )
+		printf("%s\n", path);
+
+	TBDFile stub((const char*)fileContent, fileLength);
+	auto lib = stub.parseFileForArch(archName);
+
+	_noRexports = lib._reexportedLibraries.empty();
+	_hasWeakExports = !lib._weakDefSymbols.empty();
+	_dylibInstallPath = strdup(lib._installName.str().c_str());
+	_dylibCurrentVersion = lib._currentVersion;
+	_dylibCompatibilityVersion = lib._compatibilityVersion;
+	_swiftVersion = lib._swiftVersion;
+	_objcConstraint = lib._objcConstraint;
+	_hasPublicInstallName = isPublicLocation(_dylibInstallPath);
+
+	for (auto &client : lib._allowedClients)
+		_allowableClients.push_back(strdup(client.str().c_str()));
+
+	// <rdar://problem/20659505> [TAPI] Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked
+	if ( !_allowableClients.empty() )
+		_hasPublicInstallName = false;
+
+	if ( (lib._platform != platform) && (platform != Options::kPlatformUnknown) ) {
+		_wrongOS = true;
+		if ( _addVersionLoadCommand && !indirectDylib ) {
+			if ( buildingForSimulator ) {
+				if ( !_allowSimToMacOSXLinking )
+					throwf("building for %s simulator, but linking against dylib built for %s (%s).",
+							Options::platformName(platform), Options::platformName(lib._platform), path);
+			} else {
+				throwf("building for %s, but linking against dylib built for %s (%s).",
+						Options::platformName(platform), Options::platformName(lib._platform), path);
+			}
+		}
+	}
+
+	_dependentDylibs.reserve(lib._reexportedLibraries.size());
+	for ( auto& reexport : lib._reexportedLibraries ) {
+		Dependent entry;
+		entry.path = strdup(reexport.str().c_str());
+		entry.dylib = nullptr;
+		if ( (targetInstallPath == nullptr) || (strcmp(targetInstallPath, entry.path) != 0) )
+			_dependentDylibs.push_back(entry);
+	}
+
+	// build hash table
+	buildExportHashTable(lib);
+
+	munmap((caddr_t)fileContent, fileLength);
+}
+
+template <typename A>
+void File<A>::buildExportHashTable(const DynamicLibrary& lib) {
+	if ( _s_logHashtable )
+		fprintf(stderr, "ld: building hashtable from text-stub info in %s\n", this->path());
+
+	for (auto &sym : lib._symbols)
+		addSymbol(sym.str().c_str(), /*weak=*/false, /*tlv=*/false);
+
+#if SUPPORT_ARCH_i386
+	if (_platform == Options::kPlatformOSX && _cpuType == CPU_TYPE_I386) {
+		for (auto &sym : lib._classes)
+			addSymbol((".objc_class_name" + sym.str()).c_str(), /*weak=*/false, /*tlv=*/false);
+	} else {
+		for (auto &sym : lib._classes) {
+			addSymbol(("_OBJC_CLASS_$" + sym.str()).c_str(), /*weak=*/false, /*tlv=*/false);
+			addSymbol(("_OBJC_METACLASS_$" + sym.str()).c_str(), /*weak=*/false, /*tlv=*/false);
+		}
+	}
+#else
+	for (auto &sym : lib._classes) {
+		addSymbol(("_OBJC_CLASS_$" + sym.str()).c_str(), /*weak=*/false, /*tlv=*/false);
+		addSymbol(("_OBJC_METACLASS_$" + sym.str()).c_str(), /*weak=*/false, /*tlv=*/false);
+	}
+#endif
+
+	for (auto &sym : lib._ivars)
+		addSymbol(("_OBJC_IVAR_$" + sym.str()).c_str(), /*weak=*/false, /*tlv=*/false);
+
+	for (auto &sym : lib._weakDefSymbols)
+		addSymbol(sym.str().c_str(), /*weak=*/true, /*tlv=*/false);
+
+	for (auto &sym : lib._tlvSymbols)
+		addSymbol(sym.str().c_str(), /*weak=*/false, /*tlv=*/true);
+}
+
+
+template <typename A>
+void File<A>::addSymbol(const char* name, bool weakDef, bool tlv)
+{
+	// 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 != nullptr ) {
+			char curOSVers[16];
+			sprintf(curOSVers, "$os%d.%d$", (_linkMinOSVersion >> 16), ((_linkMinOSVersion >> 8) & 0xFF));
+			if ( strncmp(symCond, curOSVers, strlen(curOSVers)) == 0 ) {
+				const char* symName = strchr(&symCond[1], '$');
+				if ( symName != nullptr ) {
+					++symName;
+					if ( strncmp(symAction, "hide$", 5) == 0 ) {
+						if ( _s_logHashtable )
+							fprintf(stderr, "  adding %s to ignore set for %s\n", symName, this->path());
+						_ignoreExports.insert(strdup(symName));
+						return;
+					}
+					else if ( strncmp(symAction, "add$", 4) == 0 ) {
+						this->addSymbol(symName, weakDef, false);
+						return;
+					}
+					else if ( strncmp(symAction, "install_name$", 13) == 0 ) {
+						_dylibInstallPath = strdup(symName);
+						_installPathOverride = true;
+						return;
+					}
+					else if ( strncmp(symAction, "compatibility_version$", 22) == 0 ) {
+						_dylibCompatibilityVersion = parseVersionNumber32(symName);
+						return;
+					}
+					else {
+						warning("bad symbol action: %s in dylib %s", name, this->path());
+					}
+				}
+			}
+		}
+		else {
+			warning("bad symbol condition: %s in dylib %s", name, this->path());
+		}
+	}
+
+	// add symbol as possible export if we are not supposed to ignore it
+	if ( _ignoreExports.count(name) == 0 ) {
+		AtomAndWeak bucket;
+		bucket.atom = nullptr;
+		bucket.weakDef = weakDef;
+		bucket.tlv = tlv;
+		if ( _s_logHashtable )
+			fprintf(stderr, "  adding %s to hash table for %s\n", name, this->path());
+		_atoms[strdup(name)] = bucket;
+	}
+}
+
+
+template <typename A>
+bool File<A>::forEachAtom(ld::File::AtomHandler& handler) const
+{
+	handler.doFile(*this);
+	return false;
+}
+
+
+template <typename A>
+std::pair<bool, bool> File<A>::hasWeakDefinitionImpl(const char* name) const
+{
+	const auto pos = _atoms.find(name);
+	if ( pos != _atoms.end() )
+		return std::make_pair(true, pos->second.weakDef);
+
+	// look in children that I re-export
+	for (const auto &dep : _dependentDylibs) {
+		auto ret = dep.dylib->hasWeakDefinitionImpl(name);
+		if ( ret.first )
+			return ret;
+	}
+	return std::make_pair(false, false);
+}
+
+
+template <typename A>
+bool File<A>::hasWeakDefinition(const char* name) const
+{
+	// if supposed to ignore this export, then pretend I don't have it
+	if ( _ignoreExports.count(name) != 0 )
+		return false;
+
+	return hasWeakDefinitionImpl(name).second;
+}
+
+
+// <rdar://problem/5529626> If only weak_import symbols are used, linker should use LD_LOAD_WEAK_DYLIB
+template <typename A>
+bool File<A>::allSymbolsAreWeakImported() const
+{
+	bool foundNonWeakImport = false;
+	bool foundWeakImport = false;
+	for (const auto &it : _atoms) {
+		const ld::Atom* atom = it.second.atom;
+		if ( atom != nullptr ) {
+			if ( atom->weakImported() )
+				foundWeakImport = true;
+			else
+				foundNonWeakImport = true;
+		}
+	}
+
+	// don't automatically weak link dylib with no imports
+	// so at least one weak import symbol and no non-weak-imported symbols must be found
+	return foundWeakImport && !foundNonWeakImport;
+}
+
+
+template <typename A>
+bool File<A>::containsOrReExports(const char* name, bool& weakDef, bool& tlv, uint64_t& addr) const
+{
+	if ( _ignoreExports.count(name) != 0 )
+		return false;
+
+	// check myself
+	const auto pos = _atoms.find(name);
+	if ( pos != _atoms.end() ) {
+		weakDef = pos->second.weakDef;
+		tlv = pos->second.tlv;
+		addr = 0;
+		return true;
+	}
+
+	// check dylibs I re-export
+	for (const auto& lib : _dependentDylibs) {
+		if ( !lib.dylib->implicitlyLinked() ) {
+			if ( lib.dylib->containsOrReExports(name, weakDef, tlv, addr) )
+				return true;
+		}
+	}
+
+	return false;
+}
+
+
+template <typename A>
+bool File<A>::justInTimeforEachAtom(const char* name, ld::File::AtomHandler& handler) const
+{
+	// if supposed to ignore this export, then pretend I don't have it
+	if ( _ignoreExports.count(name) != 0 )
+		return false;
+
+
+	AtomAndWeak bucket;
+	uint64_t addr;
+	if ( this->containsOrReExports(name, bucket.weakDef, bucket.tlv, addr) ) {
+		bucket.atom = new ExportAtom<A>(*this, name, bucket.weakDef, bucket.tlv);
+		_atoms[name] = bucket;
+		_providedAtom = true;
+		if ( _s_logHashtable )
+			fprintf(stderr, "getJustInTimeAtomsFor: %s found in %s\n", name, this->path());
+		// call handler with new export atom
+		handler.doAtom(*bucket.atom);
+		return true;
+	}
+
+	return false;
+}
+
+
+
+template <typename A>
+bool File<A>::isPublicLocation(const char* path)
+{
+	// -no_implicit_dylibs disables this optimization
+	if ( ! _implicitlyLinkPublicDylibs )
+		return false;
+
+	// /usr/lib is a public location
+	if ( (strncmp(path, "/usr/lib/", 9) == 0) && (strchr(&path[9], '/') == nullptr) )
+		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 != nullptr ) {
+			int frameworkNameLen = frameworkDot - &path[27];
+			if ( strncmp(&path[strlen(path)-frameworkNameLen-1], &path[26], frameworkNameLen+1) == 0 )
+				return true;
+		}
+	}
+
+	return false;
+}
+
+template <typename A>
+void File<A>::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, bool addImplicitDylibs)
+{
+	// only do this once
+	if ( _indirectDylibsProcessed )
+		return;
+
+	const static bool log = false;
+	if ( log ) fprintf(stderr, "processIndirectLibraries(%s)\n", this->installPath());
+	if ( _linkingFlat ) {
+		for (auto& lib : _dependentDylibs) {
+			lib.dylib = (File<A>*)handler->findDylib(lib.path, this->path());
+		}
+	}
+	else if ( _noRexports ) {
+		// MH_NO_REEXPORTED_DYLIBS bit set, then nothing to do
+	}
+	else {
+		// two-level, might have re-exports
+		for (auto& lib : _dependentDylibs) {
+			if ( log )
+				fprintf(stderr, "processIndirectLibraries() parent=%s, child=%s\n", this->installPath(), lib.path);
+			// a LC_REEXPORT_DYLIB, LC_SUB_UMBRELLA or LC_SUB_LIBRARY says we re-export this child
+			lib.dylib = (File<A>*)handler->findDylib(lib.path, this->path());
+			if ( lib.dylib->hasPublicInstallName() && !lib.dylib->wrongOS() ) {
+				// promote this child to be automatically added as a direct dependent if this already is
+				if ( (this->explicitlyLinked() || this->implicitlyLinked()) && (strcmp(lib.path, lib.dylib->installPath()) == 0) ) {
+					if ( log )
+						fprintf(stderr, "processIndirectLibraries() implicitly linking %s\n", lib.dylib->installPath());
+					lib.dylib->setImplicitlyLinked();
+				}
+				else if ( lib.dylib->explicitlyLinked() || lib.dylib->implicitlyLinked() ) {
+					if ( log )
+						fprintf(stderr, "processIndirectLibraries() parent is not directly linked, but child is, so no need to re-export child\n");
+				} else {
+					if ( log )
+						fprintf(stderr, "processIndirectLibraries() parent is not directly linked, so parent=%s will re-export child=%s\n", this->installPath(), lib.path);
+				}
+			} else {
+				// add all child's symbols to me
+				if ( log )
+					fprintf(stderr, "processIndirectLibraries() child is not public, so parent=%s will re-export child=%s\n", this->installPath(), lib.path);
+			}
+		}
+	}
+
+	// check for re-export cycles
+	ReExportChain chain;
+	chain.prev = nullptr;
+	chain.file = this;
+	this->assertNoReExportCycles(&chain);
+
+	_indirectDylibsProcessed = true;
+}
+
+template <typename A>
+void File<A>::assertNoReExportCycles(ReExportChain* prev) const
+{
+	// recursively check my re-exported dylibs
+	ReExportChain chain;
+	chain.prev = prev;
+	chain.file = this;
+	for (const auto& dep : _dependentDylibs) {
+		ld::File* child = dep.dylib;
+		// check child is not already in chain
+		for (ReExportChain* p = prev; p != nullptr; p = p->prev) {
+			if ( p->file == child )
+				throwf("cycle in dylib re-exports with %s and %s", child->path(), this->path());
+		}
+		if ( dep.dylib != nullptr )
+			dep.dylib->assertNoReExportCycles(&chain);
+	}
+}
+
+
+template <typename A>
+class Parser
+{
+public:
+	typedef typename A::P	P;
+
+	static bool				validFile(const uint8_t* fileContent, uint64_t fileLength, const std::string &path, const char* archName);
+	static ld::dylib::File*	parse(const uint8_t* fileContent, uint64_t fileLength, const char* path,
+								  time_t mTime, ld::File::Ordinal ordinal, const Options& opts,
+								  bool indirectDylib) {
+		return new File<A>(fileContent, fileLength, path, mTime, ordinal,
+						   opts.flatNamespace(),
+						   opts.implicitlyLinkIndirectPublicDylibs(),
+						   opts.platform(),
+						   opts.architecture(),
+						   opts.architectureName(),
+						   opts.minOSversion(),
+						   opts.allowSimulatorToLinkWithMacOSX(),
+						   opts.addVersionLoadCommand(),
+						   opts.targetIOSSimulator(),
+						   opts.logAllFiles(),
+						   opts.installPath(),
+						   indirectDylib);
+	}
+};
+
+template <typename A>
+bool Parser<A>::validFile(const uint8_t* fileContent, uint64_t fileLength, const std::string &path, const char* archName)
+{
+	if ( path.find(".tbd", path.size()-4) == std::string::npos )
+		return false;
+
+	TBDFile stub((const char*)fileContent, fileLength);
+	if ( !stub.validForArch(archName) )
+		throwf("missing required architecture %s in file %s", archName, path.c_str());
+
+	return true;
+}
+
+//
+// main function used by linker to instantiate ld::Files
+//
+ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path,
+					   time_t modTime, const Options& opts, ld::File::Ordinal ordinal,
+					   bool bundleLoader, bool indirectDylib)
+{
+	switch ( opts.architecture() ) {
+#if SUPPORT_ARCH_x86_64
+		case CPU_TYPE_X86_64:
+			if ( Parser<x86_64>::validFile(fileContent, fileLength, path, opts.architectureName()) )
+				return Parser<x86_64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
+			break;
+#endif
+#if SUPPORT_ARCH_i386
+		case CPU_TYPE_I386:
+			if ( Parser<x86>::validFile(fileContent, fileLength, path, opts.architectureName()) )
+				return Parser<x86>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
+			break;
+#endif
+#if SUPPORT_ARCH_arm_any
+		case CPU_TYPE_ARM:
+			if ( Parser<arm>::validFile(fileContent, fileLength, path, opts.architectureName()) )
+				return Parser<arm>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
+			break;
+#endif
+#if SUPPORT_ARCH_arm64
+		case CPU_TYPE_ARM64:
+			if ( Parser<arm64>::validFile(fileContent, fileLength, path, opts.architectureName()) )
+				return Parser<arm64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
+			break;
+#endif
+	}
+	return nullptr;
+}
+	
+	
+} // namespace dylib
+} // namespace textstub
+
+
diff --git a/src/ld/parsers/textstub_dylib_file.hpp b/src/ld/parsers/textstub_dylib_file.hpp
new file mode 100644
index 0000000..e0a75f6
--- /dev/null
+++ b/src/ld/parsers/textstub_dylib_file.hpp
@@ -0,0 +1,43 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015 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 __TEXTSTUB_DYLIB_FILE_H__
+#define __TEXTSTUB_DYLIB_FILE_H__
+
+#include "ld.hpp"
+#include "Options.h"
+
+namespace textstub {
+namespace dylib {
+
+
+extern ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path,
+							  time_t modTime, const Options& opts, ld::File::Ordinal ordinal,
+							  bool bundleLoader, bool indirectDylib);
+
+} // namespace dylib
+} // namespace textstub
+
+
+#endif // __TEXTSTUB_DYLIB_FILE_H__
diff --git a/src/ld/passes/bitcode_bundle.cpp b/src/ld/passes/bitcode_bundle.cpp
new file mode 100644
index 0000000..bafad0b
--- /dev/null
+++ b/src/ld/passes/bitcode_bundle.cpp
@@ -0,0 +1,809 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <vector>
+#include <dlfcn.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <unordered_map>
+
+#include "llvm-c/lto.h"
+// c header
+extern "C" {
+#include <xar/xar.h>
+}
+
+#include "bitcode_bundle.h"
+
+#include "Options.h"
+#include "ld.hpp"
+#include "Bitcode.hpp"
+#include "macho_relocatable_file.h"
+
+
+namespace ld {
+namespace passes {
+namespace bitcode_bundle {
+
+class BitcodeTempFile;
+
+class BitcodeAtom : public ld::Atom {
+    static ld::Section                      bitcodeBundleSection;
+public:
+                                            BitcodeAtom();
+                                            BitcodeAtom(BitcodeTempFile& tempfile);
+                                            ~BitcodeAtom()                  { free(_content); }
+    virtual ld::File*						file() const					{ return NULL; }
+    virtual const char*						name() const					{ return "bitcode bundle"; }
+    virtual uint64_t						size() const					{ return _size; }
+    virtual uint64_t						objectAddress() const			{ return 0; }
+    virtual void							copyRawContent(uint8_t buffer[]) const
+                                                                            { memcpy(buffer, _content, _size); }
+    virtual void							setScope(Scope)					{ }
+
+private:
+    uint8_t*                                _content;
+    uint64_t								_size;
+};
+
+ld::Section BitcodeAtom::bitcodeBundleSection("__LLVM", "__bundle", ld::Section::typeSectCreate);
+
+class BitcodeTempFile {
+public:
+                                            BitcodeTempFile(const char* path, bool deleteAfterRead);
+                                            ~BitcodeTempFile();
+    uint8_t*                                getContent() const              { return _content; }
+    uint64_t                                getSize() const                 { return _size; }
+private:
+    friend class BitcodeAtom;
+    const char* _path;
+    uint8_t* _content;
+    uint64_t _size;
+    bool _deleteAfterRead;
+};
+
+class BitcodeObfuscator {
+public:
+    BitcodeObfuscator();
+    ~BitcodeObfuscator();
+
+    void addMustPreserveSymbols(const char* name);
+    void bitcodeHideSymbols(ld::Bitcode* bc, const char* filePath, const char* outputPath);
+    void writeSymbolMap(const char* outputPath);
+private:
+    typedef void (*lto_codegen_func_t) (lto_code_gen_t);
+    typedef void (*lto_codegen_output_t) (lto_code_gen_t, const char*);
+
+    lto_code_gen_t                          _obfuscator;
+    lto_codegen_func_t                      _lto_hide_symbols;
+    lto_codegen_func_t                      _lto_reset_context;
+    lto_codegen_output_t                    _lto_write_reverse_map;
+};
+
+class FileHandler {
+    // generic handler for files in a bundle
+public:
+    virtual void populateMustPreserveSymbols(BitcodeObfuscator* _obfuscator)    { }
+    virtual void obfuscateAndWriteToPath(BitcodeObfuscator* _obfuscator, const char* path) { };
+    xar_file_t getXARFile()                 { return _xar_file; }
+
+    FileHandler(char* content, size_t size) :
+        _parent(NULL), _xar_file(NULL), _file_buffer(content), _file_size(size) {   }           // eager construct
+    FileHandler(xar_t parent, xar_file_t xar_file) :
+        _parent(parent), _xar_file(xar_file), _file_buffer(NULL), _file_size(0) {   }           // lazy construct
+    virtual ~FileHandler()                                                      {   }
+
+protected:
+    void initFile() {
+        if (!_file_buffer) {
+            if (xar_extract_tobuffersz(_parent, _xar_file, &_file_buffer, &_file_size) != 0)
+                throwf("could not extract files from bitcode bundle");
+        }
+    }
+    void destroyFile() {
+        if (_parent)
+            free(_file_buffer);
+    }
+
+    xar_t                               _parent;
+    xar_file_t                          _xar_file;
+    char*                               _file_buffer;
+    size_t                              _file_size;
+};
+
+class BundleHandler : public FileHandler {
+public:
+    BundleHandler(char* bundleContent, size_t bundleSize, const Options& options) :
+        FileHandler(bundleContent, bundleSize), _xar(NULL), _temp_dir(NULL), _options(options) { }
+    BundleHandler(xar_t parent, xar_file_t xar_file, const Options& options) :
+        FileHandler(parent, xar_file), _xar(NULL), _temp_dir(NULL), _options(options) { }
+
+    ~BundleHandler();
+
+    virtual void populateMustPreserveSymbols(BitcodeObfuscator* obfuscator) override;
+    virtual void obfuscateAndWriteToPath(BitcodeObfuscator* obfuscator, const char* path) override;
+
+private:
+    void init();
+    void copyXARProp(xar_file_t src, xar_file_t dst);
+
+    xar_t                                   _xar;
+    char*                                   _temp_dir;
+    const Options&                          _options;
+    std::vector<FileHandler*>               _handlers;
+};
+
+class BitcodeHandler : public FileHandler {
+public:
+    BitcodeHandler(char* content, size_t size) : FileHandler(content, size)      { }
+    BitcodeHandler(xar_t parent, xar_file_t xar_file) : FileHandler(parent, xar_file)   { }
+
+    ~BitcodeHandler();
+
+    virtual void populateMustPreserveSymbols(BitcodeObfuscator* obfuscator) override { } // Don't need to preserve symbols
+    virtual void obfuscateAndWriteToPath(BitcodeObfuscator* obfuscator, const char* path) override;
+};
+
+class ObjectHandler : public FileHandler {
+public:
+    ObjectHandler(char* content, size_t size) :
+        FileHandler(content, size)                      { }
+    ObjectHandler(xar_t parent, xar_file_t xar_file) :
+        FileHandler(parent, xar_file)                   { }
+
+    ~ObjectHandler();
+
+    void populateMustPreserveSymbols(BitcodeObfuscator* obfuscator) override;
+    void obfuscateAndWriteToPath(BitcodeObfuscator* obfuscator, const char* path) override;
+
+};
+
+
+class BitcodeBundle {
+public:
+    BitcodeBundle(const Options& opts, ld::Internal& internal) :
+        _options(opts), _state(internal)    { }
+    ~BitcodeBundle()                        { }
+    void                                    doPass();
+
+private:
+    const Options&                          _options;
+    ld::Internal&                           _state;
+};
+
+BitcodeAtom::BitcodeAtom()
+: ld::Atom(bitcodeBundleSection,
+           ld::Atom::definitionRegular, ld::Atom::combineNever,
+           ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified,
+           ld::Atom::symbolTableNotIn, true, false, false, ld::Atom::Alignment(0)),
+    _size(1)
+{
+    // initialize a marker of 1 byte
+    _content = (uint8_t*)calloc(1,1);
+}
+
+BitcodeAtom::BitcodeAtom(BitcodeTempFile& tempfile)
+    : ld::Atom(bitcodeBundleSection,
+               ld::Atom::definitionRegular, ld::Atom::combineNever,
+               ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified,
+               ld::Atom::symbolTableNotIn, true, false, false, ld::Atom::Alignment(0)),
+    _content(tempfile._content), _size(tempfile._size)
+{
+    // Creating the Atom will transfer the ownership of the buffer from Tempfile to Atom
+    tempfile._content = NULL;
+}
+
+BitcodeTempFile::BitcodeTempFile(const char* path, bool deleteAfterRead = true)
+    : _path(path), _deleteAfterRead(deleteAfterRead)
+{
+    int fd = ::open(path, O_RDONLY, 0);
+    if ( fd == -1 )
+        throwf("could not open bitcode temp file: %s", path);
+    struct stat stat_buf;
+    ::fstat(fd, &stat_buf);
+    _content = (uint8_t*)malloc(stat_buf.st_size);
+    if ( _content == NULL )
+        throwf("could not process bitcode temp file: %s", path);
+    if ( read(fd, _content, stat_buf.st_size) != stat_buf.st_size )
+        throwf("could not read bitcode temp file: %s", path);
+    ::close(fd);
+    _size = stat_buf.st_size;
+}
+
+BitcodeTempFile::~BitcodeTempFile()
+{
+    free(_content);
+    if ( _deleteAfterRead ) {
+        if ( ::unlink(_path) != 0 )
+            throwf("could not remove temp file: %s", _path);
+    }
+}
+
+BitcodeObfuscator::BitcodeObfuscator()
+{
+    // check if apple internal libLTO is used
+    if ( ::lto_get_version() == NULL )
+        throwf("libLTO is not loaded");
+    _lto_hide_symbols = (lto_codegen_func_t) dlsym(RTLD_DEFAULT, "lto_codegen_hide_symbols");
+    _lto_write_reverse_map = (lto_codegen_output_t) dlsym(RTLD_DEFAULT, "lto_codegen_write_symbol_reverse_map");
+    _lto_reset_context = (lto_codegen_func_t) dlsym(RTLD_DEFAULT, "lto_codegen_reset_context");
+    if ( _lto_hide_symbols == NULL || _lto_write_reverse_map == NULL ||
+        _lto_reset_context == NULL || ::lto_api_version() < 14 )
+        throwf("loaded libLTO doesn't support -bitcode_hide_symbols: %s", ::lto_get_version());
+    _obfuscator = ::lto_codegen_create_in_local_context();
+#if LTO_API_VERSION >= 14
+    lto_codegen_set_should_internalize(_obfuscator, false);
+#endif
+}
+
+BitcodeObfuscator::~BitcodeObfuscator()
+{
+    ::lto_codegen_dispose(_obfuscator);
+}
+
+void BitcodeObfuscator::addMustPreserveSymbols(const char* name)
+{
+    ::lto_codegen_add_must_preserve_symbol(_obfuscator, name);
+}
+
+void BitcodeObfuscator::bitcodeHideSymbols(ld::Bitcode* bc, const char* filePath, const char* outputPath)
+{
+#if LTO_API_VERSION >= 13 && LTO_APPLE_INTERNAL
+    lto_module_t module = ::lto_module_create_in_codegen_context(bc->getContent(), bc->getSize(), filePath, _obfuscator);
+    if ( module == NULL )
+        throwf("object contains invalid bitcode: %s", filePath);
+    ::lto_codegen_set_module(_obfuscator, module);
+    (*_lto_hide_symbols)(_obfuscator);
+#if LTO_API_VERSION >= 15
+    ::lto_codegen_set_should_embed_uselists(_obfuscator, true);
+#endif
+    ::lto_codegen_write_merged_modules(_obfuscator, outputPath);
+    (*_lto_reset_context)(_obfuscator);
+#endif
+    return;
+}
+
+void BitcodeObfuscator::writeSymbolMap(const char *outputPath)
+{
+    (*_lto_write_reverse_map)(_obfuscator, outputPath);
+}
+
+BundleHandler::~BundleHandler()
+{
+    // free buffers
+    destroyFile();
+    // free handlers
+    for (auto handler : _handlers)
+        delete handler;
+
+    // delete temp file if not -save-temps
+    if ( _xar ) {
+        xar_close(_xar);
+        std::string oldXARPath = std::string(_temp_dir) + std::string("/bundle.xar");
+        if ( !_options.saveTempFiles() && ::unlink(oldXARPath.c_str()) != 0)
+            warning("could not delete temp file: %s", oldXARPath.c_str());
+    }
+
+    if ( _temp_dir ) {
+        if ( !_options.saveTempFiles() && ::rmdir(_temp_dir) != 0 )
+            warning("could not delete temp directory: %s", _temp_dir);
+        free(_temp_dir);
+    }
+}
+
+BitcodeHandler::~BitcodeHandler()
+{
+    destroyFile();
+}
+
+ObjectHandler::~ObjectHandler()
+{
+    destroyFile();
+}
+
+void BundleHandler::init()
+{
+    if ( _xar != NULL )
+        return;
+
+    // make temp directory
+    const char* finalOutput = _options.outputFilePath();
+    _temp_dir = (char*)malloc(PATH_MAX * sizeof(char));
+    // Check outputFilePath.bundle-XXXXXX/YYYYYYYYYY.bc will not over flow PATH_MAX
+    // If so, fall back to /tmp
+    if ( strlen(finalOutput) + 30 >= PATH_MAX )
+        sprintf(_temp_dir, "/tmp/ld.bundle.XXXXXX");
+    else
+        sprintf(_temp_dir, "%s.bundle.XXXXXX", finalOutput);
+    ::mkdtemp(_temp_dir);
+
+    // write the bundle to the temp_directory
+    initFile();
+    std::string oldXARPath = std::string(_temp_dir) + std::string("/bundle.xar");
+    int f = ::open(oldXARPath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+    if ( f == -1 )
+        throwf("could not write file to temp directory: %s", _temp_dir);
+    if ( ::write(f, _file_buffer, _file_size) != (int)_file_size )
+        throwf("failed to write content to temp file: %s", oldXARPath.c_str());
+    ::close(f);
+
+    // read the xar file
+    _xar = xar_open(oldXARPath.c_str(), READ);
+
+    // Init the vector of handler
+    xar_iter_t iter = xar_iter_new();
+    if ( !iter )
+        throwf("could not aquire iterator for the bitcode bundle");
+    for ( xar_file_t f = xar_file_first(_xar, iter); f; f = xar_file_next(iter) ) {
+        const char* filetype = NULL;
+        if ( xar_prop_get(f, "file-type", &filetype) != 0 )
+            throwf("could not get the file type for the bitcode bundle");
+        if ( strcmp(filetype, "Bundle") == 0 )
+            _handlers.push_back(new BundleHandler(_xar, f, _options));
+        else if ( strcmp(filetype, "Object") == 0 )
+            _handlers.push_back(new ObjectHandler(_xar, f));
+        else if ( strcmp(filetype, "Bitcode") == 0 || strcmp(filetype, "LTO") == 0 )
+            _handlers.push_back(new BitcodeHandler(_xar, f));
+        else
+            assert(0 && "Unknown file type");
+    }
+    xar_iter_free(iter);
+}
+
+void BundleHandler::copyXARProp(xar_file_t src, xar_file_t dst)
+{
+    // copy the property in the XAR.
+    // Since XAR API can only get the first value from the key,
+    // Deleting the value after read.
+    int i = 0;
+    while (1) {
+        xar_iter_t p = xar_iter_new();
+        const char* key = xar_prop_first(src, p);
+        for (int x = 0; x < i; x++)
+            key = xar_prop_next(p);
+        if ( !key )
+            break;
+        const char* val = NULL;
+        xar_prop_get(src, key, &val);
+        if ( // Info from bitcode files
+             strcmp(key, "file-type") == 0 ||
+             strcmp(key, "clang/cmd") == 0 ||
+             strcmp(key, "swift/cmd") == 0 ||
+             // Info from linker subdoc
+             strcmp(key, "version") == 0 ||
+             strcmp(key, "architecture") == 0 ||
+             strcmp(key, "hide-symbols") == 0 ||
+             strcmp(key, "platform") == 0 ||
+             strcmp(key, "sdkversion") == 0 ||
+             strcmp(key, "dylibs/lib") == 0 ||
+             strcmp(key, "link-options/option") == 0 ) {
+            xar_prop_create(dst, key, val);
+            xar_prop_unset(src, key);
+        } else
+            ++ i;
+        xar_iter_free(p);
+    }
+}
+
+void BundleHandler::populateMustPreserveSymbols(BitcodeObfuscator* obfuscator)
+{
+    // init the handler
+    if ( _xar == NULL )
+        init();
+
+    // iterate through the XAR file and add symbols
+    for ( auto handler : _handlers )
+        handler->populateMustPreserveSymbols(obfuscator);
+}
+
+void ObjectHandler::populateMustPreserveSymbols(BitcodeObfuscator* obfuscator)
+{
+    initFile();
+    // Parse the object file and add the symbols
+    std::vector<const char*> symbols;
+    if ( mach_o::relocatable::getNonLocalSymbols((uint8_t*)_file_buffer, symbols) ) {
+        for ( auto sym : symbols )
+            obfuscator->addMustPreserveSymbols(sym);
+    }
+}
+
+void BundleHandler::obfuscateAndWriteToPath(BitcodeObfuscator *obfuscator, const char *path)
+{
+    // init the handler
+    if ( _xar == NULL )
+        init();
+
+    // creating the new xar
+    xar_t x = xar_open(path, WRITE);
+    if (x == NULL)
+        throwf("could not open output bundle to write %s", path);
+    // Disable compression
+    if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE) != 0)
+        throwf("could not disable compression for bitcode bundle");
+
+    // iterate through the XAR file and obfuscate
+    for ( auto handler : _handlers ) {
+        const char* name = NULL;
+        xar_file_t f = handler->getXARFile();
+        if ( xar_prop_get(f, "name", &name) != 0 )
+            throwf("could not get the name of the file from bitcode bundle");
+        char outputPath[PATH_MAX];
+        sprintf(outputPath, "%s/%s", _temp_dir, name);
+        handler->obfuscateAndWriteToPath(obfuscator, outputPath);
+        BitcodeTempFile* bcOut = new BitcodeTempFile(outputPath, !_options.saveTempFiles());
+        xar_file_t bcEntry = xar_add_frombuffer(x, NULL, name, (char*)bcOut->getContent(), bcOut->getSize());
+        copyXARProp(f, bcEntry);
+        delete bcOut;
+    }
+
+    // copy the subdoc as well
+    for ( xar_subdoc_t sub = xar_subdoc_first(_xar); sub; sub = xar_subdoc_next(sub) ) {
+        const char *name = xar_subdoc_name(sub);
+        xar_subdoc_t newDoc = xar_subdoc_new(x, name);
+        copyXARProp((xar_file_t) sub, (xar_file_t) newDoc);
+    }
+    xar_close(x);
+}
+
+void BitcodeHandler::obfuscateAndWriteToPath(BitcodeObfuscator *obfuscator, const char *path)
+{
+    initFile();
+    ld::Bitcode bc((uint8_t*)_file_buffer, _file_size);
+    obfuscator->bitcodeHideSymbols(&bc, path, path);
+}
+
+void ObjectHandler::obfuscateAndWriteToPath(BitcodeObfuscator *obfuscator, const char *path)
+{
+    initFile();
+    int f = ::open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+    if ( f == -1 || ::write(f, _file_buffer, _file_size) != (int)_file_size )
+        throwf("failed to write content to temp file: %s", path);
+    ::close(f);
+}
+
+void BitcodeBundle::doPass()
+{
+    if ( _state.embedMarkerOnly ) {
+        assert( _options.outputKind() != Options::kDynamicExecutable &&
+                _options.outputKind() != Options::kStaticExecutable &&
+                "Don't emit marker for executables");
+        BitcodeAtom* marker = new BitcodeAtom();
+        _state.addAtom(*marker);
+        return;
+    }
+
+    if ( _state.filesWithBitcode.empty() && _state.ltoBitcodePath.empty() )
+        return;
+    // Create tempdir, the temp directory should be OUTPUT/main.exe.bundle-XXXXXX
+    char tempdir[PATH_MAX];
+    const char* finalOutput = _options.outputFilePath();
+    // Check outputFilePath.bundle-XXXXXX/YYYYYYYYYY.bc will not over flow PATH_MAX
+    // If so, fall back to /tmp
+    if ( strlen(finalOutput) + 30 >= PATH_MAX )
+        sprintf(tempdir, "/tmp/ld.bundle.XXXXXX");
+    else
+        sprintf(tempdir, "%s.bundle.XXXXXX", finalOutput);
+    ::mkdtemp(tempdir);
+    // A lookup map to look for BundlerHandler base on filename
+    std::unordered_map<std::string, BundleHandler*> handlerMap;
+
+    BitcodeObfuscator* obfuscator = _options.hideSymbols() ? new BitcodeObfuscator() : NULL;
+    // Build must keep symbols if we need to hide all the symbols
+    if ( _options.hideSymbols() ) {
+        // Go through all the atoms and decide if it should be obfuscated.
+        // The following symbols are kept:
+        // 1. entry point
+        // 2. undefined symbols
+        // 3. symbols must not be stripped
+        // 4. all the globals if the globals are dead_strip root (ex. dylibs)
+        // 5. there is an exported symbol list suggests the symbol should be exported
+        // 6. the special symbols supplied by linker
+        for ( auto &sect : _state.sections ) {
+            for ( auto &atom : sect->atoms ) {
+                if ( atom == _state.entryPoint ||
+                     atom->definition() == ld::Atom::definitionProxy ||
+                     atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip ||
+                     ( _options.allGlobalsAreDeadStripRoots() && atom->scope() == ld::Atom::scopeGlobal ) ||
+                     ( _options.hasExportRestrictList() && _options.shouldExport(atom->name())) )
+                    obfuscator->addMustPreserveSymbols(atom->name());
+            }
+        }
+        // If there are assembly sources, add globals and undefined symbols from them as well
+        for ( auto &f : _state.filesWithBitcode ) {
+            if ( ld::AsmBitcode* ab = dynamic_cast<ld::AsmBitcode*>(f->getBitcode()) ) {
+                ObjectHandler objHandler((char*)ab->getContent(), ab->getSize());
+                objHandler.populateMustPreserveSymbols(obfuscator);
+            } else if ( ld::BundleBitcode* bb = dynamic_cast<ld::BundleBitcode*>(f->getBitcode()) ) {
+                BundleHandler* bh = new BundleHandler((char*)bb->getContent(), bb->getSize(), _options);
+                bh->populateMustPreserveSymbols(obfuscator);
+                handlerMap.emplace(std::string(f->path()), bh);
+            }
+        }
+        // special symbols supplied by linker
+        obfuscator->addMustPreserveSymbols("___dso_handle");
+        obfuscator->addMustPreserveSymbols("__mh_execute_header");
+        obfuscator->addMustPreserveSymbols("__mh_dylib_header");
+        obfuscator->addMustPreserveSymbols("__mh_bundle_header");
+        obfuscator->addMustPreserveSymbols("__mh_dylinker_header");
+        obfuscator->addMustPreserveSymbols("__mh_object_header");
+        obfuscator->addMustPreserveSymbols("__mh_preload_header");
+    }
+
+    // Open XAR output
+    xar_t x;
+    char outFile[PATH_MAX];
+    sprintf(outFile, "%s/bundle.xar", tempdir);
+
+    // By default, it uses gzip to compress and SHA1 as checksum
+    x = xar_open(outFile, WRITE);
+    if (x == NULL)
+        throwf("could not open output bundle to write %s", outFile);
+    // Disable compression
+    if (xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE) != 0)
+        throwf("could not disable compression for bitcode bundle");
+
+    // Sort all the object file according to oridnal order
+    std::sort(_state.filesWithBitcode.begin(), _state.filesWithBitcode.end(),
+              [](const ld::relocatable::File* a, const ld::relocatable::File* b) {
+                  return a->ordinal() < b->ordinal();
+              });
+
+    // Copy each bitcode file into archive
+    int index = 1;
+    char formatString[10];
+    sprintf(formatString, "%%0%ud", (unsigned int)log10(_state.filesWithBitcode.size()) + 1);
+    for ( auto &obj : _state.filesWithBitcode ) {
+        assert(obj->getBitcode() != NULL && "File should contain bitcode");
+        char outFilePath[16];
+        sprintf(outFilePath, formatString, index++);
+        if ( ld::LLVMBitcode* llvmbc = dynamic_cast<ld::LLVMBitcode*>(obj->getBitcode()) ) {
+            // Handle clang and swift bitcode
+            xar_file_t bcFile = NULL;
+            if ( _options.hideSymbols() && !llvmbc->isMarker() ) { // dont strip if it is just a marker
+                char tempfile[PATH_MAX];
+                sprintf(tempfile, "%s/%s.bc", tempdir, outFilePath);
+                obfuscator->bitcodeHideSymbols(llvmbc, obj->path(), tempfile);
+                BitcodeTempFile* bcTemp = new BitcodeTempFile(tempfile, !_options.saveTempFiles());
+                bcFile = xar_add_frombuffer(x, NULL, outFilePath, (char*)bcTemp->getContent(), bcTemp->getSize());
+                delete bcTemp;
+            } else {
+                bcFile = xar_add_frombuffer(x, NULL, outFilePath, (char*)const_cast<uint8_t*>(llvmbc->getContent()), llvmbc->getSize());
+            }
+            if ( bcFile == NULL )
+                throwf("could not add bitcode from %s to bitcode bundle", obj->path());
+            if ( xar_prop_set(bcFile, "file-type", "Bitcode") != 0 )
+                throwf("could not set bitcode property for %s in bitcode bundle", obj->path());
+            // Write commandline options
+            std::string tagName = std::string(llvmbc->getBitcodeName()) + std::string("/cmd");
+            for ( uint32_t i = 0; i < llvmbc->getCmdSize(); ++i ) {
+                if ( i == 0 || llvmbc->getCmdline()[i-1] == '\0' ) {
+                    if ( xar_prop_create(bcFile, tagName.c_str(), (const char *)llvmbc->getCmdline() + i) )
+                        throwf("could not set cmdline to XAR file");
+                }
+            }
+        }
+        else if ( ld::BundleBitcode* bundlebc = dynamic_cast<ld::BundleBitcode*>(obj->getBitcode()) ) {
+            xar_file_t bundleFile = NULL;
+            if ( _options.hideSymbols() && !bundlebc->isMarker() ) { // dont strip if it is just a marker
+                char tempfile[PATH_MAX];
+                sprintf(tempfile, "%s/%s.xar", tempdir, outFilePath);
+                auto search = handlerMap.find(std::string(obj->path()));
+                assert( search != handlerMap.end() && "Cannot find handler");
+                search->second->obfuscateAndWriteToPath(obfuscator, tempfile);
+                BitcodeTempFile* bundleTemp = new BitcodeTempFile(tempfile, !_options.saveTempFiles());
+                bundleFile = xar_add_frombuffer(x, NULL, outFilePath, (char*)bundleTemp->getContent(), bundleTemp->getSize());
+                delete bundleTemp;
+            } else {
+                bundleFile = xar_add_frombuffer(x, NULL, outFilePath,
+                                                (char*)const_cast<uint8_t*>(bundlebc->getContent()),
+                                                bundlebc->getSize());
+            }
+            if ( bundleFile == NULL )
+                throwf("could not add bitcode from the bundle %s to bitcode bundle", obj->path());
+            if ( xar_prop_set(bundleFile, "file-type", "Bundle") != 0 )
+                throwf("could not set bundle property for %s in bitcode bundle", obj->path());
+        }
+        else if ( ld::AsmBitcode* asmbc = dynamic_cast<ld::AsmBitcode*>(obj->getBitcode()) ) {
+            xar_file_t objFile = xar_add_frombuffer(x, NULL, outFilePath, (char*)asmbc->getContent(), asmbc->getSize());
+            if ( objFile == NULL )
+                throwf("could not add obj file %s to bitcode bundle", obj->path());
+            if ( xar_prop_set(objFile, "file-type", "Object") != 0 )
+                throwf("could not set object property for %s in bitcode bundle", obj->path());
+        }
+        else {
+            assert(false && "Unknown bitcode");
+        }
+    }
+
+    // Write merged LTO bitcode
+    if ( !_state.ltoBitcodePath.empty() ) {
+        xar_file_t ltoFile = NULL;
+        BitcodeTempFile* ltoTemp = new BitcodeTempFile(_state.ltoBitcodePath.c_str(), !_options.saveTempFiles());
+        if ( _options.hideSymbols() ) {
+            ld::Bitcode ltoBitcode(ltoTemp->getContent(), ltoTemp->getSize());
+            char ltoTempFile[PATH_MAX];
+            sprintf(ltoTempFile, "%s/lto.bc", tempdir);
+            obfuscator->bitcodeHideSymbols(&ltoBitcode, _state.ltoBitcodePath.c_str(), ltoTempFile);
+            BitcodeTempFile* ltoStrip = new BitcodeTempFile(ltoTempFile, !_options.saveTempFiles());
+            ltoFile = xar_add_frombuffer(x, NULL, "lto.o", (char*)ltoStrip->getContent(), ltoStrip->getSize());
+            delete ltoStrip;
+        } else {
+            ltoFile = xar_add_frombuffer(x, NULL, "lto.o", (char*)ltoTemp->getContent(), ltoTemp->getSize());
+        }
+        if ( ltoFile == NULL )
+            throwf("could not add lto file %s to bitcode bundle", _state.ltoBitcodePath.c_str());
+        if ( xar_prop_set(ltoFile, "file-type", "LTO") != 0 )
+            throwf("could not set bitcode property for %s in bitcode bundle", _state.ltoBitcodePath.c_str());
+        delete ltoTemp;
+    }
+
+    // Common LinkOptions
+    std::vector<std::string> linkCmd = _options.writeBitcodeLinkOptions();
+
+    // support -sectcreate option
+    for ( auto extraSect = _options.extraSectionsBegin(); extraSect != _options.extraSectionsEnd(); ++ extraSect ) {
+        std::string sectName = std::string(extraSect->segmentName) + std::string(",") + std::string(extraSect->sectionName);
+        BitcodeTempFile* sectFile = new BitcodeTempFile(extraSect->path, false);
+        xar_file_t sectXar = xar_add_frombuffer(x, NULL, sectName.c_str(), (char*)sectFile->getContent(), sectFile->getSize());
+        if ( sectXar == NULL )
+            throwf("could not encode sectcreate file %s into bitcode bundle", extraSect->path);
+        if ( xar_prop_set(sectXar, "file-type", "Section") != 0 )
+            throwf("could not set bitcode property for %s", sectName.c_str());
+        delete sectFile;
+        linkCmd.push_back("-sectcreate");
+        linkCmd.push_back(extraSect->segmentName);
+        linkCmd.push_back(extraSect->sectionName);
+        linkCmd.push_back(sectName);
+    }
+
+    // Write exports file
+    if ( _options.hasExportMaskList() ) {
+        linkCmd.push_back("-exported_symbols_list");
+        linkCmd.push_back("exports.exp");
+        const char* exportsPath = "exports.exp";
+        std::vector<const char*> exports = _options.exportsData();
+        std::string exps;
+        for (std::vector<const char*>::iterator it = exports.begin();
+             it != exports.end(); ++ it) {
+            exps += *it;
+            exps += "\n";
+        }
+        // always append an empty line so exps cannot be empty. rdar://problem/22404253
+        exps += "\n";
+        xar_file_t exportsFile = xar_add_frombuffer(x, NULL, exportsPath, const_cast<char*>(exps.data()), exps.size());
+        if (exportsFile == NULL)
+            throwf("could not add exports list to bitcode bundle");
+        if (xar_prop_set(exportsFile, "file-type", "Exports") != 0)
+            throwf("could not set exports property in bitcode bundle");
+    }
+
+    // Create subdoc to write link information
+    xar_subdoc_t linkXML = xar_subdoc_new(x, "Ld");
+    if ( linkXML == NULL )
+        throwf("could not create XML in bitcode bundle");
+
+    // Write version number
+    if ( xar_prop_create((xar_file_t)linkXML, "version", BITCODE_XAR_VERSION) != 0 )
+        throwf("could not add version number to bitcode bundle");
+
+    // Arch
+    if ( xar_prop_create((xar_file_t)linkXML, "architecture", _options.architectureName()) != 0 )
+        throwf("could not add achitecture name to bitcode bundle");
+
+    // Opt-out symbols
+    if ( _options.hideSymbols() ) {
+        if ( xar_prop_create((xar_file_t)linkXML, "hide-symbols", "1") != 0 )
+            throwf("could not add property to bitcode bundle");
+    }
+
+    // Write SDK version
+    if ( _options.sdkPaths().size() > 1 )
+        throwf("only one -syslibroot is accepted for bitcode bundle");
+    if ( xar_prop_create((xar_file_t)linkXML, "platform", _options.getPlatformStr().c_str()) != 0 )
+        throwf("could not add platform name to bitcode bundle");
+    if ( xar_prop_create((xar_file_t)linkXML, "sdkversion", _options.getSDKVersionStr().c_str()) != 0 )
+        throwf("could not add SDK version to bitcode bundle");
+
+    // Write dylibs
+    const char* sdkRoot = NULL;
+    if ( !_options.sdkPaths().empty() )
+        sdkRoot = _options.sdkPaths().front();
+    if ( !_state.dylibs.empty() ) {
+        std::vector<const char*> SDKPaths = _options.sdkPaths();
+        char dylibPath[PATH_MAX];
+        for ( auto &dylib : _state.dylibs ) {
+            // For every dylib/framework, figure out if it is coming from a SDK
+            // if it is coming from some SDK, we parse the path to figure out which SDK
+            // If -syslibroot is pointing to a SDK, it should end with PlatformX.Y.sdk/
+            if (sdkRoot && strncmp(dylib->path(), sdkRoot, strlen(sdkRoot)) == 0) {
+                // dylib/framework from one of the -syslibroot
+                // The path start with a string template
+                strcpy(dylibPath, "{SDKPATH}/");
+                // append the path of dylib/frameowrk in the SDK
+                strcat(dylibPath, dylib->path() + strlen(sdkRoot));
+            } else {
+                // Not in any SDKs, then assume it is a user dylib/framework
+                // strip off all the path in the front
+                const char* dylib_name = strrchr(dylib->path(), '/');
+                dylib_name = (dylib_name == NULL) ? dylib->path() : dylib_name + 1;
+                strcpy(dylibPath, dylib_name);
+            }
+            if ( dylib->forcedWeakLinked() ) {
+                if ( xar_prop_create((xar_file_t)linkXML, "dylibs/weak", dylibPath) != 0)
+                    throwf("could not add dylib options to bitcode bundle");
+            } else {
+                if ( xar_prop_create((xar_file_t)linkXML, "dylibs/lib", dylibPath) != 0)
+                    throwf("could not add dylib options to bitcode bundle");
+            }
+        }
+    }
+
+    // Write link-line into archive
+    for ( auto &it : linkCmd ) {
+        if (xar_prop_create((xar_file_t)linkXML, "link-options/option", it.c_str()) != 0)
+            throwf("could not add link options to bitcode bundle");
+    }
+    // Finish writing
+    xar_close(x);
+
+    // Read the file back
+    BitcodeTempFile* xarTemp = new BitcodeTempFile(outFile, !_options.saveTempFiles());
+
+    // Create an Atom and add to the list
+    BitcodeAtom* bundleAtom = new BitcodeAtom(*xarTemp);
+    _state.addAtom(*bundleAtom);
+
+    // write the reverse mapping file if required
+    if ( _options.hideSymbols() && !_options.reverseMapTempPath().empty() )
+        obfuscator->writeSymbolMap(_options.reverseMapTempPath().c_str());
+
+    // Clean up local variables
+    delete xarTemp;
+    delete obfuscator;
+    for ( auto &entry: handlerMap )
+        delete entry.second;
+    // delete temp directory if not using -save-temps
+    // only do so after all the BitcodeTempFiles are deleted.
+    if ( !_options.saveTempFiles() ) {
+        if ( ::rmdir(tempdir) != 0 )
+            warning("temp directory cannot be removed: %s", tempdir);
+    }
+}
+
+
+
+// called by linker to write bitcode bundle into a mach-o section
+void doPass(const Options& opts, ld::Internal& internal) {
+    BitcodeBundle BB(opts, internal);
+    BB.doPass();
+}
+
+
+} // namespace bitcode_bundle
+} // namespace passes
+} // namespace ld
diff --git a/src/ld/passes/bitcode_bundle.h b/src/ld/passes/bitcode_bundle.h
new file mode 100644
index 0000000..c87a59e
--- /dev/null
+++ b/src/ld/passes/bitcode_bundle.h
@@ -0,0 +1,43 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _BITCODE_BUNDLE_H_
+#define _BITCODE_BUNDLE_H_
+
+#include "Options.h"
+#include "ld.hpp"
+
+namespace ld {
+namespace passes {
+namespace bitcode_bundle {
+
+// called by linker to write bitcode bundle into a mach-o section
+extern void doPass(const Options& opts, ld::Internal& internal);
+
+
+} // namespace bitcode_bundle
+} // namespace passes
+} // namespace ld
+
+#endif /* defined(_BITCODE_BUNDLE_H_) */
diff --git a/src/ld/passes/branch_island.cpp b/src/ld/passes/branch_island.cpp
index a8fb325..f7465d0 100644
--- a/src/ld/passes/branch_island.cpp
+++ b/src/ld/passes/branch_island.cpp
@@ -552,7 +552,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
 				if ( target->section().type() == ld::Section::typeStub )
 					dstAddr = totalTextSize;
 				int64_t displacement = dstAddr - srcAddr;
-				TargetAndOffset finalTargetAndOffset = { target, addend };
+				TargetAndOffset finalTargetAndOffset = { target, (uint32_t)addend };
 				const int64_t kBranchLimit = kBetweenRegions;
 				if ( crossSectionBranch && ((displacement > kBranchLimit) || (displacement < (-kBranchLimit))) ) {
 					const ld::Atom* island;
@@ -565,6 +565,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
 												island, island->name(), displacement);
 						++islandCount;
 						regionsIslands[0]->push_back(island);
+						state.atomToSection[island] = textSection;
 					}
 					else {
 						island = pos->second;
@@ -588,6 +589,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
 								(*region)[finalTargetAndOffset] = island;
 								if (_s_log) fprintf(stderr, "added forward branching island %p %s to region %d for %s\n", island, island->name(), i, atom->name());
 								regionsIslands[i]->push_back(island);
+								state.atomToSection[island] = textSection;
 								++islandCount;
 								nextTarget = island;
 							}
@@ -614,6 +616,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
 								(*region)[finalTargetAndOffset] = island;
 								if (_s_log) fprintf(stderr, "added back branching island %p %s to region %d for %s\n", island, island->name(), i, atom->name());
 								regionsIslands[i]->push_back(island);
+								state.atomToSection[island] = textSection;
 								++islandCount;
 								prevTarget = island;
 							}
diff --git a/src/ld/passes/branch_shim.cpp b/src/ld/passes/branch_shim.cpp
index 840a391..efc010c 100644
--- a/src/ld/passes/branch_shim.cpp
+++ b/src/ld/passes/branch_shim.cpp
@@ -328,6 +328,7 @@ void doPass(const Options& opts, ld::Internal& state)
 									}
 									shims.push_back(shim);
 									thumbToAtomMap[target] = shim;
+									state.atomToSection[shim] = sect;
 								}
 								else {
 									shim = pos->second;
@@ -361,6 +362,7 @@ void doPass(const Options& opts, ld::Internal& state)
 										shim = new ARMtoThumbShimAtom(target, *sect);
 									shims.push_back(shim);
 									atomToThumbMap[target] = shim;
+									state.atomToSection[shim] = sect;
 								}
 								else {
 									shim = pos->second;
diff --git a/src/ld/passes/dylibs.cpp b/src/ld/passes/dylibs.cpp
index af1ecf6..f77f5cd 100644
--- a/src/ld/passes/dylibs.cpp
+++ b/src/ld/passes/dylibs.cpp
@@ -30,6 +30,7 @@
 #include <mach/machine.h>
 
 #include <vector>
+#include <map>
 
 #include "ld.hpp"
 #include "dylibs.h"
diff --git a/src/ld/passes/got.cpp b/src/ld/passes/got.cpp
index 66caf34..01c2e30 100644
--- a/src/ld/passes/got.cpp
+++ b/src/ld/passes/got.cpp
@@ -44,8 +44,8 @@ class File; // forward reference
 
 class GOTEntryAtom : public ld::Atom {
 public:
-											GOTEntryAtom(ld::Internal& internal, const ld::Atom* target, bool weakImport, bool is64)
-				: ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
+											GOTEntryAtom(ld::Internal& internal, const ld::Atom* target, bool weakImport, bool weakDef, bool is64)
+				: ld::Atom(weakDef ? _s_sectionWeak : _s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
 							ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, 
 							symbolTableNotIn, false, false, false, (is64 ? ld::Atom::Alignment(3) : ld::Atom::Alignment(2))),
 				_fixup(0, ld::Fixup::k1of1, (is64 ? ld::Fixup::kindStoreTargetAddressLittleEndian64 : ld::Fixup::kindStoreTargetAddressLittleEndian32), target),
@@ -68,13 +68,16 @@ private:
 	bool									_is64;
 	
 	static ld::Section						_s_section;
+	static ld::Section						_s_sectionWeak;
 };
 
 ld::Section GOTEntryAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer);
+ld::Section GOTEntryAtom::_s_sectionWeak("__DATA", "__got_weak", ld::Section::typeNonLazyPointer);
 
 
-static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom* targetOfGOT, const ld::Fixup* fixup, bool* optimizable)
+static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom* targetOfGOT, const ld::Fixup* fixup, bool* optimizable, bool* targetIsExternalWeakDef)
 {
+	*targetIsExternalWeakDef = false;
 	switch (fixup->kind) {
 		case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
 #if SUPPORT_ARCH_arm64
@@ -92,14 +95,15 @@ static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom
 												|| (targetOfGOT->section().type() == ld::Section::typeTentativeDefs)) ) {
 				*optimizable = false;
 			}
-			if ( targetOfGOT->scope() == ld::Atom::scopeGlobal ) {	
+			if ( targetOfGOT->scope() == ld::Atom::scopeGlobal ) {
 				// cannot do LEA optimization if target is weak exported symbol
-				if ( (targetOfGOT->definition() == ld::Atom::definitionRegular) && (targetOfGOT->combine() == ld::Atom::combineByName) ) {
+				if ( ((targetOfGOT->definition() == ld::Atom::definitionRegular) || (targetOfGOT->definition() == ld::Atom::definitionProxy)) && (targetOfGOT->combine() == ld::Atom::combineByName) ) {
 					switch ( opts.outputKind() ) {
 						case Options::kDynamicExecutable:
 						case Options::kDynamicLibrary:
 						case Options::kDynamicBundle:
 						case Options::kKextBundle:
+							*targetIsExternalWeakDef = true;
 							*optimizable = false;
 							break;
 						case Options::kStaticExecutable:
@@ -199,6 +203,7 @@ void doPass(const Options& opts, ld::Internal& internal)
 	// don't create GOT atoms during this loop because that could invalidate the sections iterator
 	std::vector<const ld::Atom*> atomsReferencingGOT;
 	std::map<const ld::Atom*,bool>		weakImportMap;
+	std::map<const ld::Atom*,bool>		weakDefMap;
 	atomsReferencingGOT.reserve(128);
 	for (std::vector<ld::Internal::FinalSection*>::iterator sit=internal.sections.begin(); sit != internal.sections.end(); ++sit) {
 		ld::Internal::FinalSection* sect = *sit;
@@ -223,7 +228,8 @@ void doPass(const Options& opts, ld::Internal& internal)
                         break;   
 				}
 				bool optimizable;
-				if ( !gotFixup(opts, internal, targetOfGOT, fit, &optimizable) )
+				bool targetIsExternalWeakDef;
+				if ( !gotFixup(opts, internal, targetOfGOT, fit, &optimizable, &targetIsExternalWeakDef) )
 					continue;
 				if ( optimizable ) {
 					// change from load of GOT entry to lea of target
@@ -264,6 +270,8 @@ void doPass(const Options& opts, ld::Internal& internal)
 					}
 					if ( gotMap.count(targetOfGOT) == 0 )
 						gotMap[targetOfGOT] = NULL;
+					// record if target is weak def
+					weakDefMap[targetOfGOT] = targetIsExternalWeakDef;
 					// record weak_import attribute
 					std::map<const ld::Atom*,bool>::iterator pos = weakImportMap.find(targetOfGOT);
 					if ( pos == weakImportMap.end() ) {
@@ -319,7 +327,7 @@ void doPass(const Options& opts, ld::Internal& internal)
 	// make GOT entries
 	for (auto& entry : gotMap) {
 		if ( entry.second == NULL ) {
-			entry.second = new GOTEntryAtom(internal, entry.first, weakImportMap[entry.first], is64);
+			entry.second = new GOTEntryAtom(internal, entry.first, weakImportMap[entry.first], opts.useDataConstSegment() && weakDefMap[entry.first], is64);
 			if (log) fprintf(stderr, "making new GOT slot for %s, gotMap[%p] = %p\n", entry.first->name(), entry.first, entry.second);
 		}
 	}
@@ -348,7 +356,8 @@ void doPass(const Options& opts, ld::Internal& internal)
                     break;    
 			}
 			bool optimizable;
-			if ( (targetOfGOT == NULL) || !gotFixup(opts, internal, targetOfGOT, fit, &optimizable) )
+			bool targetIsExternalWeakDef;
+			if ( (targetOfGOT == NULL) || !gotFixup(opts, internal, targetOfGOT, fit, &optimizable, &targetIsExternalWeakDef) )
 				continue;
 			if ( !optimizable ) {
 				// GOT use not optimized away, update to bind to GOT entry
diff --git a/src/ld/passes/huge.cpp b/src/ld/passes/huge.cpp
index 51dda80..693976c 100644
--- a/src/ld/passes/huge.cpp
+++ b/src/ld/passes/huge.cpp
@@ -30,6 +30,7 @@
 #include <mach/machine.h>
 
 #include <vector>
+#include <map>
 
 #include "ld.hpp"
 #include "huge.h"
@@ -94,6 +95,7 @@ void doPass(const Options& opts, ld::Internal& state)
 				const ld::Atom* atom = *ait;
 				if ( atom->size() > 1024*1024 ) {
 					hugeSection->atoms.push_back(atom);
+					state.atomToSection[atom] = hugeSection;
 					if (log) fprintf(stderr, "moved to __huge: %s, size=%llu\n", atom->name(), atom->size());
 					*ait = NULL;  // change atom to NULL for later bulk removal
 					movedSome = true;
diff --git a/src/ld/passes/objc.cpp b/src/ld/passes/objc.cpp
index 2bbf54a..ad4673c 100644
--- a/src/ld/passes/objc.cpp
+++ b/src/ld/passes/objc.cpp
@@ -805,7 +805,7 @@ void OptimizeCategories<A>::doit(const Options& opts, ld::Internal& state)
 	std::set<const ld::Atom*> nlcatListAtoms;
 	for (std::vector<ld::Internal::FinalSection*>::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) {
 		ld::Internal::FinalSection* sect = *sit;
-		if ( (strcmp(sect->sectionName(), "__objc_nlcatlist") == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) ) {
+		if ( (strcmp(sect->sectionName(), "__objc_nlcatlist") == 0) && (strncmp(sect->segmentName(), "__DATA", 6) == 0) ) {
 			for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
 				const ld::Atom* categoryListElementAtom = *ait;
 				for (unsigned int offset=0; offset < categoryListElementAtom->size(); offset += sizeof(pint_t)) {
@@ -865,7 +865,7 @@ void OptimizeCategories<A>::doit(const Options& opts, ld::Internal& state)
 			}
 		}
 		// record method list section
-		if ( (strcmp(sect->sectionName(), "__objc_const") == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
+		if ( (strcmp(sect->sectionName(), "__objc_const") == 0) && (strncmp(sect->segmentName(), "__DATA", 6) == 0) )
 			methodListSection = sect;
 	}
 
@@ -885,9 +885,11 @@ void OptimizeCategories<A>::doit(const Options& opts, ld::Internal& state)
 				const ld::Atom* newClassRO = Class<A>::setInstanceMethodList(state, classAtom, newInstanceMethodListAtom, deadAtoms);
 				// add new method list to final sections
 				methodListSection->atoms.push_back(newInstanceMethodListAtom);
+				state.atomToSection[newInstanceMethodListAtom] = methodListSection;
 				if ( newClassRO != NULL ) {
 					assert(strcmp(newClassRO->section().sectionName(), "__objc_const") == 0);
 					methodListSection->atoms.push_back(newClassRO);
+					state.atomToSection[newClassRO] = methodListSection;
 				}
 			}
 			// if any category adds class methods, generate new merged method list, and replace
@@ -897,9 +899,11 @@ void OptimizeCategories<A>::doit(const Options& opts, ld::Internal& state)
 				const ld::Atom* newClassRO = Class<A>::setClassMethodList(state, classAtom, newClassMethodListAtom, deadAtoms);
 				// add new method list to final sections
 				methodListSection->atoms.push_back(newClassMethodListAtom);
+				state.atomToSection[newClassMethodListAtom] = methodListSection;
 				if ( newClassRO != NULL ) {
 					assert(strcmp(newClassRO->section().sectionName(), "__objc_const") == 0);
 					methodListSection->atoms.push_back(newClassRO);
+					state.atomToSection[newClassRO] = methodListSection;
 				}
 			}
 			// if any category adds protocols, generate new merged protocol list, and replace
@@ -910,13 +914,16 @@ void OptimizeCategories<A>::doit(const Options& opts, ld::Internal& state)
 				const ld::Atom* newMetaClassRO = Class<A>::setClassProtocolList(state, classAtom, newProtocolListAtom, deadAtoms);
 				// add new protocol list to final sections
 				methodListSection->atoms.push_back(newProtocolListAtom);
+				state.atomToSection[newProtocolListAtom] = methodListSection;
 				if ( newClassRO != NULL ) {
 					assert(strcmp(newClassRO->section().sectionName(), "__objc_const") == 0);
 					methodListSection->atoms.push_back(newClassRO);
+					state.atomToSection[newClassRO] = methodListSection;
 				}
 				if ( newMetaClassRO != NULL ) {
 					assert(strcmp(newMetaClassRO->section().sectionName(), "__objc_const") == 0);
 					methodListSection->atoms.push_back(newMetaClassRO);
+					state.atomToSection[newMetaClassRO] = methodListSection;
 				}
 			}
 			// if any category adds properties, generate new merged property list, and replace
@@ -926,9 +933,11 @@ void OptimizeCategories<A>::doit(const Options& opts, ld::Internal& state)
 				const ld::Atom* newClassRO = Class<A>::setInstancePropertyList(state, classAtom, newPropertyListAtom, deadAtoms);
 				// add new property list to final sections
 				methodListSection->atoms.push_back(newPropertyListAtom);
+				state.atomToSection[newPropertyListAtom] = methodListSection;
 				if ( newClassRO != NULL ) {
 					assert(strcmp(newClassRO->section().sectionName(), "__objc_const") == 0);
 					methodListSection->atoms.push_back(newClassRO);
+					state.atomToSection[newClassRO] = methodListSection;
 				}
 			}
 		 
diff --git a/src/ld/passes/order.cpp b/src/ld/passes/order.cpp
index 139e761..a7d31f3 100644
--- a/src/ld/passes/order.cpp
+++ b/src/ld/passes/order.cpp
@@ -510,8 +510,14 @@ void Layout::buildOrdinalOverrideMap()
 			switch ( atom->section().type() ) {
 				case ld::Section::typeZeroFill:
 				case ld::Section::typeTentativeDefs:
-					if ( atom->size() <= 512 ) 
-						moveToData.insert(atom);
+					if ( atom->size() <= 512 ) {
+						const char* dstSeg;
+						bool wildCardMatch;
+						const ld::File* f = atom->file();
+						const char* path = (f != NULL) ? f->path() : NULL;
+						if ( !_options.moveRwSymbol(atom->name(), path, dstSeg, wildCardMatch) )
+							moveToData.insert(atom);
+					}
 					break;
 				default:
 					break;
@@ -579,6 +585,10 @@ void Layout::buildOrdinalOverrideMap()
 						break;
 				}
 			}
+			// update atom-to-section map
+			for (std::set<const ld::Atom*>::iterator it=moveToData.begin(); it != moveToData.end(); ++it) {
+				_state.atomToSection[*it] = dataSect;
+			}
 		}
 	}
 
diff --git a/src/ld/passes/stubs/stub_arm.hpp b/src/ld/passes/stubs/stub_arm.hpp
index 5c8fc42..02ae454 100644
--- a/src/ld/passes/stubs/stub_arm.hpp
+++ b/src/ld/passes/stubs/stub_arm.hpp
@@ -234,8 +234,9 @@ class LazyPointerAtom : public ld::Atom {
 public:
 											LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
 															bool stubToGlobalWeakDef, bool stubToResolver, 
-															bool weakImport, bool close)
-				: ld::Atom(close ? _s_sectionClose : _s_section, ld::Atom::definitionRegular, 
+															bool weakImport, bool close, bool usingDataConst)
+				: ld::Atom(selectSection(close, stubToGlobalWeakDef, stubToResolver, usingDataConst),
+							ld::Atom::definitionRegular,
 							ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeLazyPointer, 
 							symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), 
 				_stubTo(stubTo),
@@ -243,7 +244,7 @@ public:
 				_resolverHelper(pass, stubTo, this),
 				_fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, 
 								stubToResolver ? &_resolverHelper : (stubToGlobalWeakDef ?  &stubTo : &_helper)),
-				_fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) { 
+				_fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) {
 						_fixup2.weakImport = weakImport; pass.addAtom(*this); 
 						if ( stubToResolver )
 							pass.addAtom(_resolverHelper);
@@ -261,6 +262,17 @@ public:
 	virtual ld::Fixup::iterator				fixupsEnd()	const 				{ return &((ld::Fixup*)&_fixup2)[1]; }
 
 private:
+	static ld::Section& selectSection(bool close, bool stubToGlobalWeakDef, bool stubToResolver, bool usingDataConst) {
+		if ( close )
+			return _s_sectionClose;
+		else if ( stubToGlobalWeakDef && usingDataConst )
+			return _s_sectionWeak;
+		else if ( stubToResolver && usingDataConst )
+			return _s_sectionResolver;
+		else
+			return _s_section;
+	}
+
 	const ld::Atom&							_stubTo;
 	StubHelperAtom							_helper;
 	ResolverHelperAtom						_resolverHelper;
@@ -269,10 +281,14 @@ private:
 	
 	static ld::Section						_s_section;
 	static ld::Section						_s_sectionClose;
+	static ld::Section						_s_sectionResolver;
+	static ld::Section						_s_sectionWeak;
 };
 
 ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer);
 ld::Section LazyPointerAtom::_s_sectionClose("__DATA", "__lazy_symbol", ld::Section::typeLazyPointerClose);
+ld::Section LazyPointerAtom::_s_sectionResolver("__DATA_DIRTY", "__la_resolver", ld::Section::typeLazyPointer);
+ld::Section LazyPointerAtom::_s_sectionWeak("__DATA", "__la_weak_ptr", ld::Section::typeLazyPointer);
 
 
 class NonLazyPointerAtom : public ld::Atom {
@@ -364,12 +380,12 @@ ld::Section StubPICKextAtom::_s_section("__TEXT", "__stub", ld::Section::typeCod
 class StubPICAtom : public ld::Atom {
 public:
 											StubPICAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
-														bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
+														bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool usingDataConst)
 				: ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
 							ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, 
 							symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), 
 				_stubTo(stubTo), 
-				_lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, false),
+				_lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, false, usingDataConst),
 				_fixup1(12, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, &_lazyPointer),
 				_fixup2(12, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this),
 				_fixup3(12, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 12),
@@ -413,7 +429,7 @@ public:
 							ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, 
 							symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), 
 				_stubTo(stubTo), 
-				_lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, false),
+				_lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, false, false),
 				_fixup(8, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, &_lazyPointer) 
 					{ pass.addAtom(*this); }
 
@@ -451,7 +467,7 @@ public:
 							ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, 
 							symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), 
 				_stubTo(stubTo), 
-				_lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, true),
+				_lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, true, false),
 				_fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARMLoad12, &_lazyPointer) 
 				{ pass.addAtom(*this); }
 
diff --git a/src/ld/passes/stubs/stub_arm64.hpp b/src/ld/passes/stubs/stub_arm64.hpp
index 63382e5..09de1fa 100644
--- a/src/ld/passes/stubs/stub_arm64.hpp
+++ b/src/ld/passes/stubs/stub_arm64.hpp
@@ -241,8 +241,9 @@ ld::Section						ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::S
 class LazyPointerAtom : public ld::Atom {
 public:
 											LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
-															bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
-				: ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
+															bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed)
+				: ld::Atom(selectSection(stubToGlobalWeakDef, stubToResolver, dataConstUsed),
+							ld::Atom::definitionRegular, ld::Atom::combineNever,
 							ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, 
 							symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), 
 				_stubTo(stubTo),
@@ -269,6 +270,15 @@ public:
 	virtual ld::Fixup::iterator				fixupsEnd()	const 				{ return &((ld::Fixup*)&_fixup2)[1]; }
 
 private:
+	static ld::Section& selectSection(bool stubToGlobalWeakDef, bool stubToResolver, bool dataConstUsed) {
+		if ( stubToGlobalWeakDef && dataConstUsed )
+			return _s_sectionWeak;
+		else if ( stubToResolver && dataConstUsed )
+			return _s_sectionResolver;
+		else
+			return _s_section;
+	}
+
 	const ld::Atom&							_stubTo;
 	StubHelperAtom							_helper;
 	ResolverHelperAtom						_resolverHelper;
@@ -276,20 +286,24 @@ private:
 	ld::Fixup								_fixup2;
 	
 	static ld::Section						_s_section;
+	static ld::Section						_s_sectionResolver;
+	static ld::Section						_s_sectionWeak;
 };
 
 ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer);
+ld::Section LazyPointerAtom::_s_sectionResolver("__DATA_DIRTY", "__la_resolver", ld::Section::typeLazyPointer);
+ld::Section LazyPointerAtom::_s_sectionWeak("__DATA", "__la_weak_ptr", ld::Section::typeLazyPointer);
 
 
 class StubAtom : public ld::Atom {
 public:
 											StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
-													bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
+													bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed)
 				: ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
 							ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, 
 							symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), 
 				_stubTo(stubTo), 
-				_lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport),
+				_lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, dataConstUsed),
 				_fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer),
 				_fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_lazyPointer),
 				_fixup3(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 0, 4) 
diff --git a/src/ld/passes/stubs/stubs.cpp b/src/ld/passes/stubs/stubs.cpp
index c01f3f9..bee5f2f 100644
--- a/src/ld/passes/stubs/stubs.cpp
+++ b/src/ld/passes/stubs/stubs.cpp
@@ -164,16 +164,17 @@ const ld::Atom* Pass::stubableFixup(const ld::Fixup* fixup, ld::Internal& state)
 
 ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport)
 {
-	//fprintf(stderr, "makeStub(target=%p %s in sect %s)\n", &target, target.name(), target.section().sectionName());
-	bool stubToGlobalWeakDef = ( (target.scope() == ld::Atom::scopeGlobal)
-								&& (target.definition() == ld::Atom::definitionRegular) 
-								&& (target.combine() == ld::Atom::combineByName) );
+	//fprintf(stderr, "makeStub(target=%p %s in sect %s, def=%d)\n", &target, target.name(), target.section().sectionName(), target.definition());
+	bool stubToGlobalWeakDef = ( (target.combine() == ld::Atom::combineByName) &&
+								 (((target.definition() == ld::Atom::definitionRegular) && (target.scope() == ld::Atom::scopeGlobal))
+								  || (target.definition() == ld::Atom::definitionProxy)) );
 
 	bool forLazyDylib = false;
 	const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target.file());
 	if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() ) 
 		forLazyDylib = true;
 	bool stubToResolver = (target.contentType() == ld::Atom::typeResolver);
+	bool usingDataConst =  _options.useDataConstSegment();
 	
 	if ( usingCompressedLINKEDIT() && !forLazyDylib ) {
 		if ( _internal->compressedFastBinderProxy == NULL )
@@ -209,7 +210,7 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport)
 				if ( (_stubCount < 900) && !_mightBeInSharedRegion && !_largeText )
 					return new ld::passes::stubs::arm::StubCloseAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport);
 				else if ( _pic )
-					return new ld::passes::stubs::arm::StubPICAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport);
+					return new ld::passes::stubs::arm::StubPICAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport, usingDataConst);
 				else
 					return new ld::passes::stubs::arm::StubNoPICAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport);
 			} 
@@ -226,7 +227,7 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport)
 			if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) 
 				return new ld::passes::stubs::arm64::KextStubAtom(*this, target);
 			else
-				return new ld::passes::stubs::arm64::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport);
+				return new ld::passes::stubs::arm64::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport, usingDataConst);
 			break;
 #endif
 	}
diff --git a/src/ld/passes/tlvp.cpp b/src/ld/passes/tlvp.cpp
index e84fc25..aec9562 100644
--- a/src/ld/passes/tlvp.cpp
+++ b/src/ld/passes/tlvp.cpp
@@ -48,7 +48,7 @@ public:
 							symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), 
 				_fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, target),
 				_target(target)
-					{ _fixup.weakImport = weakImport; internal.addAtom(*this); }
+					{	_fixup.weakImport = weakImport; internal.addAtom(*this); }
 
 	virtual const ld::File*					file() const					{ return NULL; }
 	virtual const char*						name() const					{ return _target->name(); }
@@ -236,7 +236,7 @@ void doPass(const Options& opts, ld::Internal& internal)
 					break;
 #if SUPPORT_ARCH_arm64
 				case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
-					it->fixupWithTLVStore->kind = ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21;
+					it->fixupWithTLVStore->kind = ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21;
 					break;
 				case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
 					it->fixupWithTLVStore->kind = ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12;
@@ -265,6 +265,9 @@ void doPass(const Options& opts, ld::Internal& internal)
 			continue;
 		for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin();  ait != sect->atoms.end(); ++ait) {
 			const ld::Atom* atom = *ait;
+			if ( ! opts.canUseThreadLocalVariables() ) {
+				throwf("targeted OS version does not support use of thread local variables in %s", atom->name());
+			}
 			for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
 				if ( fit->offsetInAtom != 0 ) {
 					assert(fit->binding == ld::Fixup::bindingDirectlyBound && "thread variable def contains pointer to global");
diff --git a/src/other/ObjectDump.cpp b/src/other/ObjectDump.cpp
index ceab63c..dfadf71 100644
--- a/src/other/ObjectDump.cpp
+++ b/src/other/ObjectDump.cpp
@@ -1244,11 +1244,13 @@ static ld::relocatable::File* createReader(const char* path)
 	objOpts.verboseOptimizationHints = true;
 	objOpts.armUsesZeroCostExceptions = true;
 	objOpts.subType				= sPreferredSubArch;
+	objOpts.srcKind				= ld::relocatable::File::kSourceObj;
 #if 1
 	if ( ! foundFatSlice ) {
 		cpu_type_t archOfObj;
 		cpu_subtype_t subArchOfObj;
-		if ( mach_o::relocatable::isObjectFile(p, &archOfObj, &subArchOfObj) ) {
+		Options::Platform platform;
+		if ( mach_o::relocatable::isObjectFile(p, &archOfObj, &subArchOfObj, &platform) ) {
 			objOpts.architecture = archOfObj;
 			objOpts.subType = subArchOfObj;
 		}
diff --git a/src/other/dyldinfo.cpp b/src/other/dyldinfo.cpp
index 6ac3311..f19538f 100644
--- a/src/other/dyldinfo.cpp
+++ b/src/other/dyldinfo.cpp
@@ -104,12 +104,19 @@ private:
 	void										printClassicLazyBindingInfo();
 	void										printClassicBindingInfo();
 	void										printSharedRegionInfo();
+	const char*									sharedRegionKindName(uint8_t kind);
 	void										printFunctionStartsInfo();
 	void										printDylibsInfo();
 	void										printDRInfo();
 	void										printDataInCode();
 	void										printFunctionStartLine(uint64_t addr);
-	const uint8_t*								printSharedRegionInfoForEachULEB128Address(const uint8_t* p, uint8_t kind);
+	const uint8_t*								printSharedRegionV1InfoForEachULEB128Address(const uint8_t* p, const uint8_t* end, uint8_t kind);
+	const uint8_t*								printSharedRegionV2InfoForEachULEB128Address(const uint8_t* p, const uint8_t* end);
+	const uint8_t*								printSharedRegionV2InfoForEachULEB128AddressAndAdj(const uint8_t* p, const uint8_t* end);
+	const uint8_t*								printSharedRegionV2SectionPair(const uint8_t* p, const uint8_t* end);
+	const uint8_t*								printSharedRegionV2ToSectionOffset(const uint8_t* p, const uint8_t* end);
+	const uint8_t*								printSharedRegionV2Kind(const uint8_t* p, const uint8_t* end);
+
 	pint_t										relocBase();
 	const char*									relocTypeName(uint8_t r_type);
 	uint8_t										segmentIndexForAddress(pint_t addr);
@@ -129,6 +136,7 @@ private:
 	const char*									classicOrdinalName(int libraryOrdinal);
 	pint_t*										mappedAddressForVMAddress(pint_t vmaddress);
 	const char*									symbolNameForAddress(uint64_t);
+	const char*									closestSymbolNameForAddress(uint64_t addr, uint64_t* offset, uint8_t sectIndex=0);
 
 		
 	const char*									fPath;
@@ -149,8 +157,10 @@ private:
 	const macho_segment_command<P>*				fFirstWritableSegment;
 	bool										fWriteableSegmentWithAddrOver4G;
 	std::vector<const macho_segment_command<P>*>fSegments;
+	std::vector<const macho_section<P>*>		fSections;
 	std::vector<const char*>					fDylibs;
 	std::vector<const macho_dylib_command<P>*>	fDylibLoadCommands;
+	macho_section<P>							fMachHeaderPseudoSection;
 };
 
 
@@ -286,7 +296,12 @@ DyldInfoPrinter<A>::DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLen
 
 	fPath = strdup(path);
 	fHeader = (const macho_header<P>*)fileContent;
-	
+
+	fMachHeaderPseudoSection.set_segname("__TEXT");
+	fMachHeaderPseudoSection.set_sectname("");
+	fMachHeaderPseudoSection.set_addr(0);
+	fSections.push_back(&fMachHeaderPseudoSection);
+
 	// get LC_DYLD_INFO
 	const uint8_t* const endOfFile = (uint8_t*)fHeader + fLength;
 	const uint8_t* const endOfLoadCommands = (uint8_t*)fHeader + sizeof(macho_header<P>) + fHeader->sizeofcmds();
@@ -318,6 +333,10 @@ DyldInfoPrinter<A>::DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLen
 					if ( segCmd->vmaddr() > 0x100000000ULL )
 						fWriteableSegmentWithAddrOver4G = true;
 				}
+				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()];
+				for(const macho_section<P>* sect = sectionsStart; sect < sectionsEnd; ++sect)
+					fSections.push_back(sect);
 				}
 				break;
 			case LC_LOAD_DYLIB:
@@ -704,9 +723,10 @@ void DyldInfoPrinter<A>::printRebaseInfoOpcodes()
 	}
 	else {
 		printf("rebase opcodes:\n");
-		const uint8_t* p = (uint8_t*)fHeader + fInfo->rebase_off();
-		const uint8_t* end = &p[fInfo->rebase_size()];
-		
+		const uint8_t* start = (uint8_t*)fHeader + fInfo->rebase_off();
+		const uint8_t* end = &start[fInfo->rebase_size()];
+		const uint8_t* p = start;
+
 		uint8_t type = 0;
 		uint64_t address = fBaseAddress;
 		uint32_t count;
@@ -716,44 +736,45 @@ void DyldInfoPrinter<A>::printRebaseInfoOpcodes()
 		while ( !done && (p < end) ) {
 			uint8_t immediate = *p & REBASE_IMMEDIATE_MASK;
 			uint8_t opcode = *p & REBASE_OPCODE_MASK;
+			uint32_t opcodeOffset = p-start;
 			++p;
 			switch (opcode) {
 				case REBASE_OPCODE_DONE:
 					done = true;
-					printf("REBASE_OPCODE_DONE()\n");
+					printf("0x%04X REBASE_OPCODE_DONE()\n", opcodeOffset);
 					break;
 				case REBASE_OPCODE_SET_TYPE_IMM:
 					type = immediate;
-					printf("REBASE_OPCODE_SET_TYPE_IMM(%d)\n", type);
+					printf("0x%04X REBASE_OPCODE_SET_TYPE_IMM(%d)\n", opcodeOffset, type);
 					break;
 				case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
 					segmentIndex = immediate;
 					address = read_uleb128(p, end);
-					printf("REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%d, 0x%08llX)\n", segmentIndex, address);
+					printf("0x%04X REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%d, 0x%08llX)\n", opcodeOffset, segmentIndex, address);
 					break;
 				case REBASE_OPCODE_ADD_ADDR_ULEB:
 					address = read_uleb128(p, end);
-					printf("REBASE_OPCODE_ADD_ADDR_ULEB(0x%0llX)\n", address);
+					printf("0x%04X REBASE_OPCODE_ADD_ADDR_ULEB(0x%0llX)\n", opcodeOffset, address);
 					break;
 				case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
 					address = immediate*sizeof(pint_t);
-					printf("REBASE_OPCODE_ADD_ADDR_IMM_SCALED(0x%0llX)\n", address);
+					printf("0x%04X REBASE_OPCODE_ADD_ADDR_IMM_SCALED(0x%0llX)\n", opcodeOffset, address);
 					break;
 				case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
-					printf("REBASE_OPCODE_DO_REBASE_IMM_TIMES(%d)\n", immediate);
+					printf("0x%04X REBASE_OPCODE_DO_REBASE_IMM_TIMES(%d)\n", opcodeOffset, immediate);
 					break;
 				case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
 					count = read_uleb128(p, end);
-					printf("REBASE_OPCODE_DO_REBASE_ULEB_TIMES(%d)\n", count);
+					printf("0x%04X REBASE_OPCODE_DO_REBASE_ULEB_TIMES(%d)\n", opcodeOffset, count);
 					break;
 				case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
 					skip = read_uleb128(p, end) + sizeof(pint_t);
-					printf("REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB(%d)\n", skip);
+					printf("0x%04X REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB(%d)\n", opcodeOffset, skip);
 					break;
 				case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
 					count = read_uleb128(p, end);
 					skip = read_uleb128(p, end);
-					printf("REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB(%d, %d)\n", count, skip);
+					printf("0x%04X REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB(%d, %d)\n", opcodeOffset, count, skip);
 					break;
 				default:
 					throwf("bad rebase opcode %d", *p);
@@ -1485,102 +1506,126 @@ void DyldInfoPrinter<A>::printExportInfoNodes()
 
 
 template <typename A>
-const uint8_t* DyldInfoPrinter<A>::printSharedRegionInfoForEachULEB128Address(const uint8_t* p, uint8_t kind)
+const uint8_t* DyldInfoPrinter<A>::printSharedRegionV1InfoForEachULEB128Address(const uint8_t* p, const uint8_t* end, uint8_t kind)
 {
 	const char* kindStr =  "??";
-	switch (kind) {
-		case 1:
+	switch (kind ) {
+		case DYLD_CACHE_ADJ_V1_POINTER_32:
 			kindStr = "32-bit pointer";
 			break;
-		case 2:
+		case DYLD_CACHE_ADJ_V1_POINTER_64:
 			kindStr = "64-bit pointer";
 			break;
-		case 3:
-#if SUPPORT_ARCH_arm64
-			if ( fHeader->cputype() == CPU_TYPE_ARM64 )
-				kindStr = "arm64 ADRP";
-			else
-#endif
-				kindStr = "ppc hi16";
-			break;
-		case 4:
-			kindStr = "32-bit offset to IMPORT";
-			break;
-		case 5:
-			kindStr = "thumb2 movw";
-			break;
-		case 6:
-			kindStr = "ARM movw";
+		case DYLD_CACHE_ADJ_V1_ADRP:
+			kindStr = "arm64 ADRP";
 			break;
-		case 0x10:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+0:
 			kindStr = "thumb2 movt low high 4 bits=0";
 			break;
-		case 0x11:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+1:
 			kindStr = "thumb2 movt low high 4 bits=1";
 			break;
-		case 0x12:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+2:
 			kindStr = "thumb2 movt low high 4 bits=2";
 			break;
-		case 0x13:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+3:
 			kindStr = "thumb2 movt low high 4 bits=3";
 			break;
-		case 0x14:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+4:
 			kindStr = "thumb2 movt low high 4 bits=4";
 			break;
-		case 0x15:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+5:
 			kindStr = "thumb2 movt low high 4 bits=5";
 			break;
-		case 0x16:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+6:
 			kindStr = "thumb2 movt low high 4 bits=6";
 			break;
-		case 0x17:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+7:
 			kindStr = "thumb2 movt low high 4 bits=7";
 			break;
-		case 0x18:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+8:
 			kindStr = "thumb2 movt low high 4 bits=8";
 			break;
-		case 0x19:
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+9:
 			kindStr = "thumb2 movt low high 4 bits=9";
 			break;
-		case 0x1A:
-			kindStr = "thumb2 movt low high 4 bits=0xA";
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+10:
+			kindStr = "thumb2 movt low high 4 bits=10";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+11:
+			kindStr = "thumb2 movt low high 4 bits=11";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+12:
+			kindStr = "thumb2 movt low high 4 bits=12";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+13:
+			kindStr = "thumb2 movt low high 4 bits=13";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+14:
+			kindStr = "thumb2 movt low high 4 bits=14";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT+15:
+			kindStr = "thumb2 movt low high 4 bits=15";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+0:
+			kindStr = "arm movt low high 4 bits=0";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+1:
+			kindStr = "arm movt low high 4 bits=1";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+2:
+			kindStr = "arm movt low high 4 bits=2";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+3:
+			kindStr = "arm movt low high 4 bits=3";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+4:
+			kindStr = "arm movt low high 4 bits=4";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+5:
+			kindStr = "arm movt low high 4 bits=5";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+6:
+			kindStr = "arm movt low high 4 bits=6";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+7:
+			kindStr = "arm movt low high 4 bits=7";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+8:
+			kindStr = "arm movt low high 4 bits=8";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+9:
+			kindStr = "arm movt low high 4 bits=9";
+			break;
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+10:
+			kindStr = "arm movt low high 4 bits=10";
 			break;
-		case 0x1B:
-			kindStr = "thumb2 movt low high 4 bits=0xB";
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+11:
+			kindStr = "arm movt low high 4 bits=11";
 			break;
-		case 0x1C:
-			kindStr = "thumb2 movt low high 4 bits=0xC";
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+12:
+			kindStr = "arm movt low high 4 bits=12";
 			break;
-		case 0x1D:
-			kindStr = "thumb2 movt low high 4 bits=0xD";
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+13:
+			kindStr = "arm movt low high 4 bits=13";
 			break;
-		case 0x1E:
-			kindStr = "thumb2 movt low high 4 bits=0xE";
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+14:
+			kindStr = "arm movt low high 4 bits=14";
 			break;
-		case 0x1F:
-			kindStr = "thumb2 movt low high 4 bits=0xF";
+		case DYLD_CACHE_ADJ_V1_ARM_MOVT+15:
+			kindStr = "arm movt low high 4 bits=15";
 			break;
+		default:
+			kindStr = "<<unknown>>";
 	}
 	uint64_t address = 0;
 	uint64_t delta = 0;
-	uint32_t shift = 0;
-	bool more = true;
 	do {
-		uint8_t byte = *p++;
-		delta |= ((byte & 0x7F) << shift);
-		shift += 7;
-		if ( byte < 0x80 ) {
-			if ( delta != 0 ) {
-				address += delta;
-				printf("0x%0llX   %s\n", address+fBaseAddress, kindStr); 
-				delta = 0;
-				shift = 0;
-			}
-			else {
-				more = false;
-			}
-		}
-	} while (more);
+		delta = read_uleb128(p, end);
+		address += delta;
+		printf("0x%0llX   %s\n", address+fBaseAddress, kindStr); 
+	} while (delta);
+
 	return p;
 }
 
@@ -1593,14 +1638,96 @@ void DyldInfoPrinter<A>::printSharedRegionInfo()
 	else {
 		const uint8_t* infoStart = (uint8_t*)fHeader + fSharedRegionInfo->dataoff();
 		const uint8_t* infoEnd = &infoStart[fSharedRegionInfo->datasize()];
-		for(const uint8_t* p = infoStart; (*p != 0) && (p < infoEnd);) {
-			uint8_t kind = *p++;
-			p = this->printSharedRegionInfoForEachULEB128Address(p, kind);
+		if ( *infoStart == DYLD_CACHE_ADJ_V2_FORMAT ) {
+			++infoStart;
+			// Whole		 :== <count> FromToSection+
+			// FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+
+			// ToOffset		 :== <to-sect-offset-delta> <count> FromOffset+
+			// FromOffset	 :== <kind> <count> <from-sect-offset-delta>
+			const uint8_t* p = infoStart;
+			uint64_t sectionCount = read_uleb128(p, infoEnd);
+			for (uint64_t i=0; i < sectionCount; ++i) {
+				uint64_t fromSectionIndex = read_uleb128(p, infoEnd);
+				uint64_t toSectionIndex = read_uleb128(p, infoEnd);
+				uint64_t toOffsetCount = read_uleb128(p, infoEnd);
+				const macho_section<P>* fromSection = fSections[fromSectionIndex];
+				const macho_section<P>* toSection = fSections[toSectionIndex];
+				printf("from sect=%s, to sect=%s, count=%lld:\n", fromSection->sectname(), toSection->sectname(), toOffsetCount);
+				uint64_t toSectionOffset = 0;
+				const char* lastFromSymbol = NULL;
+				for (uint64_t j=0; j < toOffsetCount; ++j) {
+					uint64_t toSectionDelta = read_uleb128(p, infoEnd);
+					uint64_t fromOffsetCount = read_uleb128(p, infoEnd);
+					toSectionOffset += toSectionDelta;
+					for (uint64_t k=0; k < fromOffsetCount; ++k) {
+						uint64_t kind = read_uleb128(p, infoEnd);
+						uint64_t fromSectDeltaCount = read_uleb128(p, infoEnd);
+						uint64_t fromSectionOffset = 0;
+						for (uint64_t l=0; l < fromSectDeltaCount; ++l) {
+							uint64_t delta = read_uleb128(p, infoEnd);
+							fromSectionOffset += delta;
+							uint64_t symbolOffset;
+							const char* s = closestSymbolNameForAddress(fromSection->addr()+fromSectionOffset, &symbolOffset, fromSectionIndex);
+							if ( (s != lastFromSymbol) && (s != NULL) )
+								printf("  %s:\n", s);
+							const char* toSymbol = closestSymbolNameForAddress(toSection->addr()+toSectionOffset, &symbolOffset, toSectionIndex);
+							printf("       from addr=0x%0llX %s to addr=0x%0llX", fromSection->addr()+fromSectionOffset, sharedRegionKindName(kind), toSection->addr()+toSectionOffset);
+							if ( toSymbol != NULL ) {
+								if ( symbolOffset == 0 )
+									printf(" (%s)", toSymbol);
+								else
+									printf(" (%s + %lld)", toSymbol, symbolOffset);
+							}
+							printf("\n");
+							lastFromSymbol = s;
+						}
+					}
+				}
+			}
+		}
+		else {
+			for(const uint8_t* p = infoStart; (*p != 0) && (p < infoEnd);) {
+				uint8_t kind = *p++;
+				p = this->printSharedRegionV1InfoForEachULEB128Address(p, infoEnd, kind);
+			}
 		}
+	}
+}
 
+template <typename A>
+const char* DyldInfoPrinter<A>::sharedRegionKindName(uint8_t kind)
+{
+	switch (kind) {
+		default:
+			return "<<unknown>>";
+		case DYLD_CACHE_ADJ_V2_POINTER_32:
+			return "pointer32";
+		case DYLD_CACHE_ADJ_V2_POINTER_64:
+			return "pointer64";
+		case DYLD_CACHE_ADJ_V2_DELTA_32:
+			return "delta32";
+		case DYLD_CACHE_ADJ_V2_DELTA_64:
+			return "delta64";
+		case DYLD_CACHE_ADJ_V2_ARM64_ADRP:
+			return "adrp";
+		case DYLD_CACHE_ADJ_V2_ARM64_OFF12:
+			return "off12";
+		case DYLD_CACHE_ADJ_V2_ARM64_BR26:
+			return "br26";
+		case DYLD_CACHE_ADJ_V2_ARM_MOVW_MOVT:
+			return "movw/movt";
+		case DYLD_CACHE_ADJ_V2_ARM_BR24:
+			return "br24";
+		case DYLD_CACHE_ADJ_V2_THUMB_MOVW_MOVT:
+			return "movw/movt";
+		case DYLD_CACHE_ADJ_V2_THUMB_BR22:
+			return "br22";
+		case DYLD_CACHE_ADJ_V2_IMAGE_OFF_32:
+			return "off32";
 	}
 }
 
+
 #if SUPPORT_ARCH_arm_any
 template <>
 void DyldInfoPrinter<arm>::printFunctionStartLine(uint64_t addr)
@@ -1686,7 +1813,6 @@ void DyldInfoPrinter<A>::printDRInfo()
 		const uint8_t* start = ((uint8_t*)fHeader + fDRInfo->dataoff());
 		//const uint8_t* end   = ((uint8_t*)fHeader + fDRInfo->dataoff() + fDRInfo->datasize());
 		typedef Security::SuperBlob<Security::kSecCodeMagicDRList> DRListSuperBlob;
-		typedef Security::SuperBlob<Security::kSecCodeMagicRequirementSet> InternalRequirementsSetBlob;
 		const DRListSuperBlob* topBlob = (DRListSuperBlob*)start;
 		if ( topBlob->validateBlob(fDRInfo->datasize()) ) {
 			if ( topBlob->count() == fDylibLoadCommands.size() ) {
@@ -1951,37 +2077,65 @@ void DyldInfoPrinter<A>::printSymbolTableExportInfo()
 }
 
 template <typename A>
-const char* DyldInfoPrinter<A>::symbolNameForAddress(uint64_t addr)
+const char* DyldInfoPrinter<A>::closestSymbolNameForAddress(uint64_t addr, uint64_t* offset, uint8_t sectIndex)
 {
+	const macho_nlist<P>* bestSymbol = NULL;
 	if ( fDynamicSymbolTable != NULL ) {
-		// find exact match in globals
-		const macho_nlist<P>* lastExport = &fSymbols[fDynamicSymbolTable->iextdefsym()+fDynamicSymbolTable->nextdefsym()];
-		for (const macho_nlist<P>* sym = &fSymbols[fDynamicSymbolTable->iextdefsym()]; sym < lastExport; ++sym) {
-			if ( (sym->n_value() == addr) && ((sym->n_type() & N_TYPE) == N_SECT) && ((sym->n_type() & N_STAB) == 0) ) {
-				return &fStrings[sym->n_strx()];
+		// find closest match in globals
+		const macho_nlist<P>* const globalsStart = &fSymbols[fDynamicSymbolTable->iextdefsym()];
+		const macho_nlist<P>* const globalsEnd   = &globalsStart[fDynamicSymbolTable->nextdefsym()];
+		for (const macho_nlist<P>* s = globalsStart; s < globalsEnd; ++s) {
+			if ( (s->n_type() & N_TYPE) == N_SECT ) {
+				if ( (s->n_value() <= addr) && ((s->n_sect() == sectIndex) || (sectIndex ==0)) ) {
+					if ( (bestSymbol == NULL) || (bestSymbol->n_value() < s->n_value()) )
+						bestSymbol = s;
+				}
 			}
 		}
-		// find exact match in local symbols
-		const macho_nlist<P>* lastLocal = &fSymbols[fDynamicSymbolTable->ilocalsym()+fDynamicSymbolTable->nlocalsym()];
-		for (const macho_nlist<P>* sym = &fSymbols[fDynamicSymbolTable->ilocalsym()]; sym < lastLocal; ++sym) {
-			if ( (sym->n_value() == addr) && ((sym->n_type() & N_TYPE) == N_SECT) && ((sym->n_type() & N_STAB) == 0) ) {
-				return &fStrings[sym->n_strx()];
+
+		// find closest match in locals
+		const macho_nlist<P>* const localsStart = &fSymbols[fDynamicSymbolTable->ilocalsym()];
+		const macho_nlist<P>* const localsEnd   = &localsStart[fDynamicSymbolTable->nlocalsym()];
+		for (const macho_nlist<P>* s = localsStart; s < localsEnd; ++s) {
+			if ( ((s->n_type() & N_TYPE) == N_SECT) && ((s->n_type() & N_STAB) == 0) ) {
+				if ( (s->n_value() <= addr) && ((s->n_sect() == sectIndex) || (sectIndex ==0)) ) {
+					if ( (bestSymbol == NULL) || (bestSymbol->n_value() < s->n_value()) )
+						bestSymbol = s;
+				}
 			}
 		}
 	}
 	else {
-		// find exact match in all symbols
-		const macho_nlist<P>* lastSym = &fSymbols[fSymbolCount];
-		for (const macho_nlist<P>* sym = &fSymbols[0]; sym < lastSym; ++sym) {
-			if ( (sym->n_value() == addr) && ((sym->n_type() & N_TYPE) == N_SECT) && ((sym->n_type() & N_STAB) == 0) ) {
-				return &fStrings[sym->n_strx()];
+		// find closest match in locals
+		const macho_nlist<P>* const allStart = &fSymbols[0];
+		const macho_nlist<P>* const allEnd   = &fSymbols[fSymbolCount];
+		for (const macho_nlist<P>* s = allStart; s < allEnd; ++s) {
+			if ( ((s->n_type() & N_TYPE) == N_SECT) && ((s->n_type() & N_STAB) == 0) ) {
+				if ( (s->n_value() <= addr) && ((s->n_sect() == sectIndex) || (sectIndex ==0)) ) {
+					if ( (bestSymbol == NULL) || (bestSymbol->n_value() < s->n_value()) )
+						bestSymbol = s;
+				}
 			}
 		}
 	}
+	if ( bestSymbol != NULL ) {
+		*offset = addr - bestSymbol->n_value();
+		return &fStrings[bestSymbol->n_strx()];
+	}
+	*offset = 0;
+	return NULL;
+}
 
+template <typename A>
+const char* DyldInfoPrinter<A>::symbolNameForAddress(uint64_t addr)
+{
+	uint64_t offset;
+	const char* s = closestSymbolNameForAddress(addr, &offset);
+	if ( (offset == 0) && (s != NULL) )
+		return s;
 	return "?";
 }
- 
+
 template <typename A>
 void DyldInfoPrinter<A>::printClassicBindingInfo()
 {
@@ -2223,7 +2377,7 @@ static void usage()
 			"\t-opcodes          print opcodes used to generate the rebase and binding information\n"
 			"\t-function_starts  print table of function start addresses\n"
 			"\t-export_dot       print a GraphViz .dot file of the exported symbols trie\n"
-			"\t-data_in_code     print any data-in-code inforamtion\n"
+			"\t-data_in_code     print any data-in-code information\n"
 		);
 }
 
diff --git a/unit-tests/include/common.makefile b/unit-tests/include/common.makefile
index 545b4a7..f0cbbf1 100644
--- a/unit-tests/include/common.makefile
+++ b/unit-tests/include/common.makefile
@@ -55,7 +55,7 @@ ifeq ($(ARCH),ppc)
 	SDKExtra = -isysroot /Developer/SDKs/MacOSX10.6.sdk
 endif
 
-CC		 = $(shell xcrun -find clang) -arch ${ARCH} ${SDKExtra}
+CC		 = $(shell xcrun -find clang) -arch ${ARCH} ${SDKExtra} -mmacosx-version-min=10.8
 CCFLAGS = -Wall 
 ASMFLAGS =
 VERSION_NEW_LINKEDIT = -mmacosx-version-min=10.6
@@ -65,7 +65,7 @@ LD_NEW_LINKEDIT = -macosx_version_min 10.6
 CXX		  = $(shell xcrun -find clang++) -arch ${ARCH} ${SDKExtra}
 CXXFLAGS = -Wall -stdlib=libc++ 
 
-IOS_SDK = $(shell xcodebuild -sdk iphoneos8.0.internal -version Path  2>/dev/null)
+IOS_SDK = $(shell xcodebuild -sdk iphoneos.internal -version Path  2>/dev/null)
 
 ifeq ($(ARCH),armv6)
   LDFLAGS := -syslibroot $(IOS_SDK)
@@ -127,16 +127,13 @@ endif
 
 ifeq ($(ARCH),arm64)
   LDFLAGS := -syslibroot $(IOS_SDK)
-  CC = /Applications/Xcode.app/Contents/Developer/Toolchains/iOS7.1.xctoolchain/usr/bin/clang -arch ${ARCH} -ccc-install-dir ${LD_PATH} -miphoneos-version-min=7.0 -isysroot $(IOS_SDK)
-  #CC = $(shell xcrun --sdk iphoneos.internal -find clang) -arch ${ARCH} -ccc-install-dir ${LD_PATH} -miphoneos-version-min=7.0 -isysroot $(IOS_SDK)
-  #CC =  /Applications/Xcode.app/Contents/Developer/Toolchains/iOS7.0.xctoolchain/usr/bin/clang-loh -arch ${ARCH} -ccc-install-dir ${LD_PATH} -miphoneos-version-min=7.0 -isysroot $(IOS_SDK)
-  CXX = $(shell xcrun --sdk iphoneos.internal -find clang++) -arch ${ARCH} -ccc-install-dir ${LD_PATH} -miphoneos-version-min=7.0 -isysroot $(IOS_SDK)
+  CC  = $(shell xcrun --sdk iphoneos.internal -find clang) -arch ${ARCH} -ccc-install-dir ${LD_PATH} -miphoneos-version-min=9.0 -isysroot $(IOS_SDK)
+  CXX = $(shell xcrun --sdk iphoneos.internal -find clang++) -arch ${ARCH} -ccc-install-dir ${LD_PATH} -miphoneos-version-min=9.0 -isysroot $(IOS_SDK)
   VERSION_NEW_LINKEDIT = -miphoneos-version-min=7.0
   VERSION_OLD_LINKEDIT = -miphoneos-version-min=3.0
   LD_SYSROOT = -syslibroot $(IOS_SDK)
   LD_NEW_LINKEDIT = -ios_version_min 7.0
-  OTOOL =   /Applications/Xcode.app/Contents/Developer/Toolchains/iOS7.1.xctoolchain/usr/bin/otool
-  #OTOOL =  $(shell xcrun --sdk iphoneos.internal -find otool)
+  OTOOL =  $(shell xcrun --sdk iphoneos.internal -find otool)
 else
   FILEARCH = $(ARCH)
 endif
diff --git a/unit-tests/test-cases/dead_strip-live-if-ref-live/Makefile b/unit-tests/test-cases/dead_strip-live-if-ref-live/Makefile
new file mode 100644
index 0000000..0949507
--- /dev/null
+++ b/unit-tests/test-cases/dead_strip-live-if-ref-live/Makefile
@@ -0,0 +1,48 @@
+##
+# Copyright (c) 2014 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
+
+#
+# Sanity check -dead_strip does not remove initializers and terminators
+#
+
+
+run: all
+
+all:
+	${CC} ${CCFLAGS} main.c -c -o main.o
+	${CC} ${CCFLAGS} main.o -dead_strip -o main
+	${FAIL_IF_BAD_MACHO} main
+	nm main | grep _aa | ${FAIL_IF_EMPTY}
+	nm main | grep _aaInfo | ${FAIL_IF_EMPTY}
+	nm main | grep _bb | ${FAIL_IF_STDIN}
+	${LD} -r main.o -o main-r.o
+	${CC} ${CCFLAGS} main-r.o -dead_strip -o main-r
+	nm main-r | grep _aa | ${FAIL_IF_EMPTY}
+	nm main-r | grep _aaInfo | ${FAIL_IF_EMPTY}
+	nm main-r | grep _bb | ${FAIL_IF_STDIN}
+	${PASS_IFF_GOOD_MACHO} main-r
+
+clean:
+	rm -rf main.o main main-r.o main-r
diff --git a/unit-tests/test-cases/dead_strip-live-if-ref-live/main.c b/unit-tests/test-cases/dead_strip-live-if-ref-live/main.c
new file mode 100644
index 0000000..e038a28
--- /dev/null
+++ b/unit-tests/test-cases/dead_strip-live-if-ref-live/main.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+
+int aa = 10;
+int bb = 20;
+int cc = 30;
+
+
+int main()
+{
+  printf("%p %p\n", &aa, &cc);
+	return 0;
+}
+
+
+struct MetaData {
+  void*		addr;
+  unsigned long	size;
+  const char*	name;
+};
+
+
+#define META_DATA(__x)							  \
+  __attribute__((used, section("__DATA,__meta,regular,live_support")))	  \
+  static struct MetaData __x##Info = { &__x, sizeof(__x), #__x };
+
+
+META_DATA(aa);
+META_DATA(bb);
+META_DATA(cc);
diff --git a/unit-tests/test-cases/tlv-basic/get.s b/unit-tests/test-cases/tlv-basic/get.s
index 9255841..b0eb6de 100644
--- a/unit-tests/test-cases/tlv-basic/get.s
+++ b/unit-tests/test-cases/tlv-basic/get.s
@@ -159,4 +159,117 @@ _get_d:
 
 #endif
 
+
+#if __arm__
+
+		# _a is global TLV
+		.tlv
+		.globl _a
+_a:		.long	__tlv_bootstrap
+		.long	0
+		.long	_a$tlv$init
+
+		# _b is a global TLV
+		.tlv
+		.globl _b
+_b:		.long	__tlv_bootstrap
+		.long	0
+		.long	_b$tlv$init
+
+		# _c is a non-external TLV
+		.tlv
+_c:		.long	__tlv_bootstrap
+		.long	0
+		.long	_c$tlv$init
+
+		# _d is a non-external TLV
+		.tlv
+_d:		.long	__tlv_bootstrap
+		.long	0
+		.long	_d$tlv$init
+
+
+  .text
+
+  .globl	_get_a
+	.align	2
+	.code	16
+	.thumb_func	_get_a
+_get_a:
+  push	{r7, lr}
+  mov	r7, sp
+	movw	r0, :lower16:(La-(LPC0_0+4))
+	movt	r0, :upper16:(La-(LPC0_0+4))
+LPC0_0:
+	add	r0, pc
+	ldr	r0, [r0]
+	ldr	ip, [r0]
+  blx ip
+  pop	{r7, pc}
+
+
+  .globl	_get_b
+	.align	2
+	.code	16
+	.thumb_func	_get_b
+_get_b:
+  push	{r7, lr}
+  mov	r7, sp
+	movw	r0, :lower16:(Lb-(LPC0_1+4))
+	movt	r0, :upper16:(Lb-(LPC0_1+4))
+LPC0_1:
+	add	r0, pc
+	ldr	r0, [r0]
+	ldr	ip, [r0]
+  blx ip
+  pop	{r7, pc}
+
+
+  .globl	_get_c
+	.align	2
+	.code	16
+	.thumb_func	_get_c
+_get_c:
+  push	{r7, lr}
+  mov	r7, sp
+	movw	r0, :lower16:(Lc-(LPC0_2+4))
+	movt	r0, :upper16:(Lc-(LPC0_2+4))
+LPC0_2:
+	add	r0, pc
+	ldr	r0, [r0]
+	ldr	ip, [r0]
+  blx ip
+  pop	{r7, pc}
+
+
+  .globl	_get_d
+	.align	2
+	.code	16
+	.thumb_func	_get_d
+_get_d:
+  push	{r7, lr}
+  mov	r7, sp
+	movw	r0, :lower16:(Ld-(LPC0_3+4))
+	movt	r0, :upper16:(Ld-(LPC0_3+4))
+LPC0_3:
+	add	r0, pc
+	ldr	r0, [r0]
+	ldr	ip, [r0]
+  blx ip
+  pop	{r7, pc}
+
+
+  .section __DATA,__thread_ptr,thread_local_variable_pointers
+La:
+  .long _a
+Lb:
+  .long _b
+Lc:
+  .long _c
+Ld:
+  .long _d
+
+
+#endif
+
 .subsections_via_symbols
diff --git a/unit-tests/test-cases/tlv-basic/main.c b/unit-tests/test-cases/tlv-basic/main.c
index fc56a13..b5fd7f6 100644
--- a/unit-tests/test-cases/tlv-basic/main.c
+++ b/unit-tests/test-cases/tlv-basic/main.c
@@ -22,6 +22,8 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 
+#include <stdio.h>
+
 // work around until compiler supports __thread
 extern int* get_a();		
 extern int* get_b();
@@ -30,10 +32,19 @@ extern int* get_d();
 
 int main()
 {
-	get_a();
-	get_b();
-	get_c();
-	get_d();
+	int* p;
+  p = get_a();
+  printf("&a=%p, a=%d\n", p, *p);
+
+	p = get_b();
+  printf("&b=%p, b=%d\n", p, *p);
+
+	p = get_c();
+  printf("&c=%p, c=%d\n", p, *p);
+
+	p = get_d();
+  printf("&d=%p, e=%d\n", p, *p);
+
 	return 0;
 }
 
-- 
2.47.2