1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
   3  * Copyright (c) 2006-2010 Apple Inc. All rights reserved. 
   5  * @APPLE_LICENSE_HEADER_START@ 
   7  * This file contains Original Code and/or Modifications of Original Code 
   8  * as defined in and that are subject to the Apple Public Source License 
   9  * Version 2.0 (the 'License'). You may not use this file except in 
  10  * compliance with the License. Please obtain a copy of the License at 
  11  * http://www.opensource.apple.com/apsl/ and read it before using this 
  14  * The Original Code and all software distributed under the License are 
  15  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  16  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  17  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  18  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  19  * Please see the License for the specific language governing rights and 
  20  * limitations under the License. 
  22  * @APPLE_LICENSE_HEADER_END@ 
  25 #ifndef __LTO_READER_H__ 
  26 #define __LTO_READER_H__ 
  29 #include <sys/param.h> 
  30 #include <sys/fcntl.h> 
  34 #include <mach-o/dyld.h> 
  36 #include <unordered_set> 
  37 #include <unordered_map> 
  39 #include "MachOFileAbstraction.hpp" 
  40 #include "Architectures.hpp" 
  42 #include "macho_relocatable_file.h" 
  45 // #defines are a work around for <rdar://problem/8760268> 
  46 #define __STDC_LIMIT_MACROS 1 
  47 #define __STDC_CONSTANT_MACROS 1 
  48 #include "llvm-c/lto.h" 
  54 // ld64 only tracks non-internal symbols from an llvm bitcode file.   
  55 // We model this by having an InternalAtom which represent all internal functions and data. 
  56 // All non-interal symbols from a bitcode file are represented by an Atom 
  57 // and each Atom has a reference to the InternalAtom.  The InternalAtom 
  58 // also has references to each symbol external to the bitcode file.  
  60 class InternalAtom 
: public ld::Atom
 
  63                                                                                                 InternalAtom(class File
& f
); 
  64         // overrides of ld::Atom 
  65         virtual ld::File
*                                                       file() const            { return &_file
; } 
  66         virtual const char*                                                     name() const            { return "import-atom"; } 
  67         virtual uint64_t                                                        size() const            { return 0; } 
  68         virtual uint64_t                                                        objectAddress() const { return 0; } 
  69         virtual void                                                            copyRawContent(uint8_t buffer
[]) const { } 
  70         virtual void                                                            setScope(Scope
)         { } 
  71         virtual ld::Fixup::iterator                                     
fixupsBegin() const     { return &_undefs
[0]; } 
  72         virtual ld::Fixup::iterator                                     
fixupsEnd()     const   { return &_undefs
[_undefs
.size()]; } 
  74         // for adding references to symbols outside bitcode file 
  75         void                                                                            addReference(const char* nm
) 
  76                                                                                                                                         { _undefs
.push_back(ld::Fixup(0, ld::Fixup::k1of1
,  
  77                                                                                                                                                                 ld::Fixup::kindNone
, false, strdup(nm
))); } 
  81         mutable std::vector
<ld::Fixup
>                          _undefs
; 
  88 class File 
: public ld::relocatable::File
 
  91                                                                                         File(const char* path
, time_t mTime
, ld::File::Ordinal ordinal
,  
  92                                                                                                          const uint8_t* content
, uint32_t contentLength
, cpu_type_t arch
); 
  95         // overrides of ld::File 
  96         virtual bool                                                                            forEachAtom(ld::File::AtomHandler
&) const; 
  97         virtual bool                                                                            justInTimeforEachAtom(const char* name
, ld::File::AtomHandler
&) const  
  99         virtual uint32_t                                                                        cpuSubType() const                      { return _cpuSubType
; } 
 101         // overrides of ld::relocatable::File  
 102         virtual DebugInfoKind                                                           
debugInfo()     const                   { return _debugInfo
; } 
 103         virtual const char*                                                                     debugInfoPath() const           { return _debugInfoPath
; } 
 104         virtual time_t                                                                          debugInfoModificationTime() const  
 105                                                                                                                                                                         { return _debugInfoModTime
; } 
 106         virtual const std::vector
<ld::relocatable::File::Stab
>* stabs() const                   { return NULL
; } 
 107         virtual bool                                                                            canScatterAtoms() const         { return true; } 
 108         virtual LinkerOptionsList
*                                                      linkerOptions() const           { return NULL
; } 
 112         lto_module_t                                                                            
module()                                        { return _module
; } 
 113         class InternalAtom
&                                                                     internalAtom()                          { return _internalAtom
; } 
 114         void                                                                                            setDebugInfo(ld::relocatable::File::DebugInfoKind k
, 
 115                                                                                                                                         const char* pth
, time_t modTime
, uint32_t subtype
) 
 117                                                                                                                                                                                 _debugInfoPath 
= pth
;  
 118                                                                                                                                                                                 _debugInfoModTime 
= modTime
;  
 119                                                                                                                                                                                 _cpuSubType 
= subtype
;} 
 123         friend class InternalAtom
; 
 126         cpu_type_t                                                              _architecture
; 
 127         class InternalAtom                                              _internalAtom
; 
 128         class Atom
*                                                             _atomArray
; 
 129         uint32_t                                                                _atomArrayCount
; 
 130         lto_module_t                                                    _module
; 
 131         const char*                                                             _debugInfoPath
; 
 132         time_t                                                                  _debugInfoModTime
; 
 133         ld::Section                                                             _section
; 
 134         ld::Fixup                                                               _fixupToInternal
; 
 135         ld::relocatable::File::DebugInfoKind    _debugInfo
;  
 136         uint32_t                                                                _cpuSubType
; 
 140 // Atom acts as a proxy Atom for the symbols that are exported by LLVM bitcode file. Initially, 
 141 // Reader creates Atoms to allow linker proceed with usual symbol resolution phase. After 
 142 // optimization is performed, real Atoms are created for these symobls. However these real Atoms 
 143 // are not inserted into global symbol table. Atom holds real Atom and forwards appropriate 
 144 // methods to real atom. 
 146 class Atom 
: public ld::Atom
 
 149                                                                                 Atom(File
& f
, const char* name
, ld::Atom::Scope s
,  
 150                                                                                                 ld::Atom::Definition d
, ld::Atom::Combine c
, ld::Atom::Alignment a
, bool ah
); 
 152         // overrides of ld::Atom 
 153         virtual ld::File
*                                       file() const            { return &_file
; } 
 154         virtual const char*                                     translationUnitSource() const 
 155                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->translationUnitSource() : NULL
); } 
 156         virtual const char*                                     name() const            { return _name
; } 
 157         virtual uint64_t                                        size() const            { return (_compiledAtom 
? _compiledAtom
->size() : 0); } 
 158         virtual uint64_t                                        objectAddress() const { return (_compiledAtom 
? _compiledAtom
->objectAddress() : 0); } 
 159         virtual void                                            copyRawContent(uint8_t buffer
[]) const  
 160                                                                                                                         { if (_compiledAtom
) _compiledAtom
->copyRawContent(buffer
); } 
 161         virtual const uint8_t*                          rawContentPointer() const  
 162                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->rawContentPointer() : NULL
);  } 
 163         virtual unsigned long                           contentHash(const class ld::IndirectBindingTable
& ibt
) const  
 164                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->contentHash(ibt
) : 0);  } 
 165         virtual bool                                            canCoalesceWith(const ld::Atom
& rhs
, const class ld::IndirectBindingTable
& ibt
) const  
 166                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->canCoalesceWith(rhs
,ibt
) : false); } 
 167         virtual ld::Fixup::iterator                             
fixupsBegin() const      
 168                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->fixupsBegin() : (ld::Fixup
*)&_file
._fixupToInternal
); } 
 169         virtual ld::Fixup::iterator                             
fixupsEnd() const        
 170                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->fixupsEnd() : &((ld::Fixup
*)&_file
._fixupToInternal
)[1]); } 
 171         virtual ld::Atom::UnwindInfo::iterator  
beginUnwind() const  
 172                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->beginUnwind() : NULL
); } 
 173         virtual ld::Atom::UnwindInfo::iterator  
endUnwind() const        
 174                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->endUnwind() : NULL
); } 
 175         virtual ld::Atom::LineInfo::iterator    
beginLineInfo() const  
 176                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->beginLineInfo() : NULL
); } 
 177         virtual ld::Atom::LineInfo::iterator    
endLineInfo() const  
 178                                                                                                                         { return (_compiledAtom 
? _compiledAtom
->endLineInfo() : NULL
); } 
 180         const ld::Atom
*                                         compiledAtom()          { return _compiledAtom
; } 
 181         void                                                            setCompiledAtom(const ld::Atom
& atom
); 
 187         const ld::Atom
*                                         _compiledAtom
; 
 199         static bool                                             validFile(const uint8_t* fileContent
, uint64_t fileLength
, cpu_type_t architecture
, cpu_subtype_t subarch
); 
 200         static const char*                              fileKind(const uint8_t* fileContent
, uint64_t fileLength
); 
 201         static File
*                                    parse(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
,  
 202                                                                                         time_t modTime
, ld::File::Ordinal ordinal
, cpu_type_t architecture
, cpu_subtype_t subarch
, 
 203                                                                                         bool logAllFiles
, bool verboseOptimizationHints
); 
 204         static bool                                             libLTOisLoaded() { return (::lto_get_version() != NULL
); } 
 205         static bool                                             optimize(   const std::vector
<const ld::Atom
*>& allAtoms
, 
 207                                                                                                 const OptimizeOptions
&                          options
, 
 208                                                                                                 ld::File::AtomHandler
&                          handler
, 
 209                                                                                                 std::vector
<const ld::Atom
*>&           newAtoms
,  
 210                                                                                                 std::vector
<const char*>&                       additionalUndefines
); 
 212         static const char*                      ltoVersion()    { return ::lto_get_version(); } 
 215         static const char*                              tripletPrefixForArch(cpu_type_t arch
); 
 216         static ld::relocatable::File
*   parseMachOFile(const uint8_t* p
, size_t len
, const OptimizeOptions
& options
); 
 217 #if LTO_API_VERSION >= 7 
 218         static void ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t
, const char*, void*); 
 221         typedef std::unordered_set
<const char*, ld::CStringHash
, ld::CStringEquals
>  CStringSet
; 
 222         typedef std::unordered_map
<const char*, Atom
*, ld::CStringHash
, ld::CStringEquals
> CStringToAtom
; 
 224         class AtomSyncer 
: public ld::File::AtomHandler 
{ 
 226                                                         AtomSyncer(std::vector
<const char*>& a
, std::vector
<const ld::Atom
*>&na
, 
 227                                                                                 CStringToAtom la
, CStringToAtom dla
, const OptimizeOptions
& options
) : 
 228                                                                                 _options(options
), _additionalUndefines(a
), _newAtoms(na
), _llvmAtoms(la
), _deadllvmAtoms(dla
) { } 
 229                 virtual void            doAtom(const class ld::Atom
&); 
 230                 virtual void            doFile(const class ld::File
&) { } 
 233                 const OptimizeOptions
&                  _options
; 
 234                 std::vector
<const char*>&               _additionalUndefines
; 
 235                 std::vector
<const ld::Atom
*>&   _newAtoms
; 
 236                 CStringToAtom                                   _llvmAtoms
; 
 237                 CStringToAtom                                   _deadllvmAtoms
; 
 240         static std::vector
<File
*>               _s_files
; 
 243 std::vector
<File
*> Parser::_s_files
; 
 246 bool Parser::validFile(const uint8_t* fileContent
, uint64_t fileLength
, cpu_type_t architecture
, cpu_subtype_t subarch
) 
 248         for (const ArchInfo
* t
=archInfoArray
; t
->archName 
!= NULL
; ++t
) { 
 249                 if ( (architecture 
== t
->cpuType
) && (!(t
->isSubType
) || (subarch 
== t
->cpuSubType
)) ) { 
 250                         bool result 
= ::lto_module_is_object_file_in_memory_for_target(fileContent
, fileLength
, t
->llvmTriplePrefix
); 
 252                                 // <rdar://problem/8434487> LTO only supports thumbv7 not armv7 
 253                                 if ( t
->llvmTriplePrefixAlt
[0] != '\0' ) { 
 254                                         result 
= ::lto_module_is_object_file_in_memory_for_target(fileContent
, fileLength
, t
->llvmTriplePrefixAlt
); 
 263 const char* Parser::fileKind(const uint8_t* p
, uint64_t fileLength
) 
 265         if ( (p
[0] == 0xDE) && (p
[1] == 0xC0) && (p
[2] == 0x17) && (p
[3] == 0x0B) ) { 
 266                 cpu_type_t arch 
= LittleEndian::get32(*((uint32_t*)(&p
[16]))); 
 267                 for (const ArchInfo
* t
=archInfoArray
; t
->archName 
!= NULL
; ++t
) { 
 268                         if ( arch 
== t
->cpuType 
) { 
 269                                  if ( t
->isSubType 
) { 
 270                                         if ( ::lto_module_is_object_file_in_memory_for_target(p
, fileLength
, t
->llvmTriplePrefix
) ) 
 278                 return "unknown bitcode architecture"; 
 283 File
* Parser::parse(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
, time_t modTime
, ld::File::Ordinal ordinal
, 
 284                                                                                                         cpu_type_t architecture
, cpu_subtype_t subarch
, bool logAllFiles
, bool verboseOptimizationHints
)  
 286         File
* f 
= new File(path
, modTime
, ordinal
, fileContent
, fileLength
, architecture
); 
 287         _s_files
.push_back(f
); 
 289                 printf("%s\n", path
); 
 294 ld::relocatable::File
* Parser::parseMachOFile(const uint8_t* p
, size_t len
, const OptimizeOptions
& options
)  
 296         mach_o::relocatable::ParserOptions objOpts
; 
 297         objOpts
.architecture            
= options
.arch
; 
 298         objOpts
.objSubtypeMustMatch 
= false;  
 299         objOpts
.logAllFiles                     
= false; 
 300         objOpts
.warnUnwindConversionProblems    
= options
.needsUnwindInfoSection
; 
 301         objOpts
.keepDwarfUnwind         
= options
.keepDwarfUnwind
; 
 302         objOpts
.forceDwarfConversion 
= false; 
 303         objOpts
.neverConvertDwarf   
= false; 
 304         objOpts
.verboseOptimizationHints 
= options
.verboseOptimizationHints
; 
 308         // mach-o parsing is done in-memory, but need path for debug notes 
 309         const char* path 
= "/tmp/lto.o"; 
 311         if ( options
.tmpObjectFilePath 
!= NULL 
) { 
 312                 path 
= options
.tmpObjectFilePath
; 
 313                 struct stat statBuffer
; 
 314                 if ( stat(options
.tmpObjectFilePath
, &statBuffer
) == 0 ) 
 315                         modTime 
= statBuffer
.st_mtime
; 
 318         ld::relocatable::File
* result 
= mach_o::relocatable::parse(p
, len
, path
, modTime
, ld::File::Ordinal::LTOOrdinal(), objOpts
); 
 319         if ( result 
!= NULL 
) 
 321         throw "LLVM LTO, file is not of required architecture"; 
 326 File::File(const char* pth
, time_t mTime
, ld::File::Ordinal ordinal
, const uint8_t* content
, uint32_t contentLength
, cpu_type_t arch
)  
 327         : ld::relocatable::File(pth
,mTime
,ordinal
), _architecture(arch
), _internalAtom(*this),  
 328         _atomArray(NULL
), _atomArrayCount(0), _module(NULL
), _debugInfoPath(pth
),  
 329         _section("__TEXT_", "__tmp_lto", ld::Section::typeTempLTO
), 
 330         _fixupToInternal(0, ld::Fixup::k1of1
, ld::Fixup::kindNone
, &_internalAtom
), 
 331         _debugInfo(ld::relocatable::File::kDebugInfoNone
), _cpuSubType(0) 
 333         const bool log 
= false; 
 335         // create llvm module 
 336 #if LTO_API_VERSION >= 9 
 337         _module 
= ::lto_module_create_from_memory_with_path(content
, contentLength
, pth
); 
 338         if ( _module 
== NULL 
) 
 340         _module 
= ::lto_module_create_from_memory(content
, contentLength
); 
 341     if ( _module 
== NULL 
) 
 342                 throwf("could not parse object file %s: '%s', using libLTO version '%s'", pth
, ::lto_get_error_message(), ::lto_get_version()); 
 344         if ( log 
) fprintf(stderr
, "bitcode file: %s\n", pth
); 
 346         // create atom for each global symbol in module 
 347         uint32_t count 
= ::lto_module_get_num_symbols(_module
); 
 348         _atomArray 
= (Atom
*)malloc(sizeof(Atom
)*count
); 
 349         for (uint32_t i
=0; i 
< count
; ++i
) { 
 350                 const char* name 
= ::lto_module_get_symbol_name(_module
, i
); 
 351                 lto_symbol_attributes attr 
= lto_module_get_symbol_attribute(_module
, i
); 
 353                 // <rdar://problem/6378110> LTO doesn't like dtrace symbols 
 354                 // ignore dtrace static probes for now 
 355                 // later when codegen is done and a mach-o file is produces the probes will be processed 
 356                 if ( (strncmp(name
, "___dtrace_probe$", 16) == 0) || (strncmp(name
, "___dtrace_isenabled$", 20) == 0) ) 
 359                 ld::Atom::Definition def
; 
 360                 ld::Atom::Combine combine 
= ld::Atom::combineNever
; 
 361                 switch ( attr 
& LTO_SYMBOL_DEFINITION_MASK 
) { 
 362                         case LTO_SYMBOL_DEFINITION_REGULAR
: 
 363                                 def 
= ld::Atom::definitionRegular
; 
 365                         case LTO_SYMBOL_DEFINITION_TENTATIVE
: 
 366                                 def 
= ld::Atom::definitionTentative
; 
 368                         case LTO_SYMBOL_DEFINITION_WEAK
: 
 369                                 def 
= ld::Atom::definitionRegular
; 
 370                                 combine 
= ld::Atom::combineByName
; 
 372                         case LTO_SYMBOL_DEFINITION_UNDEFINED
: 
 373                         case LTO_SYMBOL_DEFINITION_WEAKUNDEF
: 
 374                                 def 
= ld::Atom::definitionProxy
; 
 377                                 throwf("unknown definition kind for symbol %s in bitcode file %s", name
, pth
); 
 380                 // make LLVM atoms for definitions and a reference for undefines 
 381                 if ( def 
!= ld::Atom::definitionProxy 
) { 
 382                         ld::Atom::Scope scope
; 
 383                         bool autohide 
= false; 
 384                         switch ( attr 
& LTO_SYMBOL_SCOPE_MASK
) { 
 385                                 case LTO_SYMBOL_SCOPE_INTERNAL
: 
 386                                         scope 
= ld::Atom::scopeTranslationUnit
; 
 388                                 case LTO_SYMBOL_SCOPE_HIDDEN
: 
 389                                         scope 
= ld::Atom::scopeLinkageUnit
; 
 391                                 case LTO_SYMBOL_SCOPE_DEFAULT
: 
 392                                         scope 
= ld::Atom::scopeGlobal
; 
 394 #if LTO_API_VERSION >= 4 
 395                                 case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN
: 
 396                                         scope 
= ld::Atom::scopeGlobal
; 
 401                                         throwf("unknown scope for symbol %s in bitcode file %s", name
, pth
); 
 403                         // only make atoms for non-internal symbols  
 404                         if ( scope 
== ld::Atom::scopeTranslationUnit 
) 
 406                         uint8_t alignment 
= (attr 
& LTO_SYMBOL_ALIGNMENT_MASK
); 
 407                         // make Atom using placement new operator 
 408                         new (&_atomArray
[_atomArrayCount
++]) Atom(*this, name
, scope
, def
, combine
, alignment
, autohide
); 
 409                         if ( scope 
!= ld::Atom::scopeTranslationUnit 
) 
 410                                 _internalAtom
.addReference(name
); 
 411                         if ( log 
) fprintf(stderr
, "\t0x%08X %s\n", attr
, name
); 
 414                         // add to list of external references 
 415                         _internalAtom
.addReference(name
); 
 416                         if ( log 
) fprintf(stderr
, "\t%s (undefined)\n", name
); 
 428         if ( _module 
!= NULL 
) 
 429                 ::lto_module_dispose(_module
); 
 433 bool File::forEachAtom(ld::File::AtomHandler
& handler
) const 
 435         handler
.doAtom(_internalAtom
); 
 436         for(uint32_t i
=0; i 
< _atomArrayCount
; ++i
) { 
 437                 handler
.doAtom(_atomArray
[i
]); 
 442 InternalAtom::InternalAtom(File
& f
) 
 443         : ld::Atom(f
._section
, ld::Atom::definitionRegular
, ld::Atom::combineNever
, ld::Atom::scopeTranslationUnit
,  
 444                                 ld::Atom::typeLTOtemporary
, ld::Atom::symbolTableNotIn
, true, false, false, ld::Atom::Alignment(0)), 
 449 Atom::Atom(File
& f
, const char* nm
, ld::Atom::Scope s
, ld::Atom::Definition d
, ld::Atom::Combine c
,  
 450                         ld::Atom::Alignment a
, bool ah
) 
 451         : ld::Atom(f
._section
, d
, c
, s
, ld::Atom::typeLTOtemporary
,  
 452                                 ld::Atom::symbolTableIn
, false, false, false, a
), 
 453                 _file(f
), _name(strdup(nm
)), _compiledAtom(NULL
) 
 459 void Atom::setCompiledAtom(const ld::Atom
& atom
) 
 461         // set delegate so virtual methods go to it 
 462         _compiledAtom 
= &atom
; 
 464         //fprintf(stderr, "setting lto atom %p to delegate to mach-o atom %p (%s)\n", this, &atom, atom.name()); 
 466         // update fields in ld::Atom to match newly constructed mach-o atom 
 467         (const_cast<Atom
*>(this))->setAttributesFromAtom(atom
); 
 472 // <rdar://problem/12379604> The order that files are merged must match command line order 
 473 struct CommandLineOrderFileSorter
 
 475      bool operator()(File
* left
, File
* right
) 
 477         return ( left
->ordinal() < right
->ordinal() ); 
 482 #if LTO_API_VERSION >= 7 
 483 void Parser::ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity
, const char* message
, void*)  
 485         switch ( severity 
) { 
 486 #if LTO_API_VERSION >= 10 
 488                         fprintf(stderr
, "ld: LTO remark: %s\n", message
); 
 493                         warning("%s", message
); 
 496                         throwf("%s", message
); 
 501 bool Parser::optimize(  const std::vector
<const ld::Atom
*>&     allAtoms
, 
 503                                                 const OptimizeOptions
&                          options
, 
 504                                                 ld::File::AtomHandler
&                          handler
, 
 505                                                 std::vector
<const ld::Atom
*>&           newAtoms
,  
 506                                                 std::vector
<const char*>&                       additionalUndefines
) 
 508         const bool logMustPreserve 
= false; 
 509         const bool logExtraOptions 
= false; 
 510         const bool logBitcodeFiles 
= false; 
 511         const bool logAtomsBeforeSync 
= false; 
 513         // exit quickly if nothing to do 
 514         if ( _s_files
.size() == 0 )  
 517         // print out LTO version string if -v was used 
 518         if ( options
.verbose 
) 
 519                 fprintf(stderr
, "%s\n", ::lto_get_version()); 
 521         // create optimizer and add each Reader 
 522         lto_code_gen_t generator 
= ::lto_codegen_create(); 
 523 #if LTO_API_VERSION >= 7 
 524         lto_codegen_set_diagnostic_handler(generator
, ltoDiagnosticHandler
, NULL
); 
 527         // <rdar://problem/12379604> The order that files are merged must match command line order 
 528         std::sort(_s_files
.begin(), _s_files
.end(), CommandLineOrderFileSorter()); 
 529         ld::File::Ordinal lastOrdinal
; 
 530         for (std::vector
<File
*>::iterator it
=_s_files
.begin(); it 
!= _s_files
.end(); ++it
) { 
 532                 assert(f
->ordinal() > lastOrdinal
); 
 533                 if ( logBitcodeFiles 
) fprintf(stderr
, "lto_codegen_add_module(%s)\n", f
->path()); 
 534                 if ( ::lto_codegen_add_module(generator
, f
->module()) ) 
 535                         throwf("lto: could not merge in %s because '%s', using libLTO version '%s'", f
->path(), ::lto_get_error_message(), ::lto_get_version()); 
 536                 // <rdar://problem/15471128> linker should release module as soon as possible 
 538                 lastOrdinal 
= f
->ordinal(); 
 541         // add any -mllvm command line options 
 542         for (std::vector
<const char*>::const_iterator it
=options
.llvmOptions
->begin(); it 
!= options
.llvmOptions
->end(); ++it
) { 
 543                 if ( logExtraOptions 
) fprintf(stderr
, "passing option to llvm: %s\n", *it
); 
 544                 ::lto_codegen_debug_options(generator
, *it
); 
 547         // <rdar://problem/13687397> Need a way for LTO to get cpu variants (until that info is in bitcode) 
 548         if ( options
.mcpu 
!= NULL 
) 
 549                 ::lto_codegen_set_cpu(generator
, options
.mcpu
); 
 551         // The atom graph uses directed edges (references). Collect all references where  
 552         // originating atom is not part of any LTO Reader. This allows optimizer to optimize an  
 553         // external (i.e. not originated from same .o file) reference if all originating atoms are also  
 554         // defined in llvm bitcode file. 
 555         CStringSet nonLLVMRefs
; 
 556         CStringToAtom llvmAtoms
; 
 557     bool hasNonllvmAtoms 
= false; 
 558         for (std::vector
<const ld::Atom
*>::const_iterator it 
= allAtoms
.begin(); it 
!= allAtoms
.end(); ++it
) { 
 559                 const ld::Atom
* atom 
= *it
; 
 560                 // only look at references that come from an atom that is not an llvm atom 
 561                 if ( atom
->contentType() != ld::Atom::typeLTOtemporary 
) { 
 562                         if ( (atom
->section().type() != ld::Section::typeMachHeader
) && (atom
->definition() != ld::Atom::definitionProxy
) ) { 
 563                                 hasNonllvmAtoms 
= true; 
 565                         const ld::Atom
* target
; 
 566                         for (ld::Fixup::iterator fit
=atom
->fixupsBegin(); fit 
!= atom
->fixupsEnd(); ++fit
) { 
 567                                 switch ( fit
->binding 
) { 
 568                                         case ld::Fixup::bindingDirectlyBound
: 
 569                                                 // that reference an llvm atom 
 570                                                 if ( fit
->u
.target
->contentType() == ld::Atom::typeLTOtemporary 
)  
 571                                                         nonLLVMRefs
.insert(fit
->u
.target
->name()); 
 573                                         case ld::Fixup::bindingsIndirectlyBound
: 
 574                                                 target 
= state
.indirectBindingTable
[fit
->u
.bindingIndex
]; 
 575                                                 if ( (target 
!= NULL
) && (target
->contentType() == ld::Atom::typeLTOtemporary
) ) 
 576                                                         nonLLVMRefs
.insert(target
->name()); 
 582                 else if ( atom
->scope() >= ld::Atom::scopeLinkageUnit 
) { 
 583                         llvmAtoms
[atom
->name()] = (Atom
*)atom
; 
 586         // if entry point is in a llvm bitcode file, it must be preserved by LTO 
 587         if ( state
.entryPoint
!= NULL 
) { 
 588                 if ( state
.entryPoint
->contentType() == ld::Atom::typeLTOtemporary 
)  
 589                         nonLLVMRefs
.insert(state
.entryPoint
->name()); 
 592         // deadAtoms are the atoms that the linker coalesced.  For instance weak or tentative definitions 
 593         // overriden by another atom.  If any of these deadAtoms are llvm atoms and they were replaced 
 594         // with a mach-o atom, we need to tell the lto engine to preserve (not optimize away) its dead  
 595         // atom so that the linker can replace it with the mach-o one later. 
 596         CStringToAtom deadllvmAtoms
; 
 597         for (std::vector
<const ld::Atom
*>::const_iterator it 
= allAtoms
.begin(); it 
!= allAtoms
.end(); ++it
) { 
 598                 const ld::Atom
* atom 
= *it
; 
 599                 if ( atom
->coalescedAway() && (atom
->contentType() == ld::Atom::typeLTOtemporary
) ) { 
 600                         const char* name 
= atom
->name(); 
 601                         if ( logMustPreserve 
) fprintf(stderr
, "lto_codegen_add_must_preserve_symbol(%s) because linker coalesce away and replace with a mach-o atom\n", name
); 
 602                         ::lto_codegen_add_must_preserve_symbol(generator
, name
); 
 603                         deadllvmAtoms
[name
] = (Atom
*)atom
; 
 606         for (std::vector
<File
*>::iterator it
=_s_files
.begin(); it 
!= _s_files
.end(); ++it
) { 
 608                 for(uint32_t i
=0; i 
< file
->_atomArrayCount
; ++i
) { 
 609                         Atom
* llvmAtom 
= &file
->_atomArray
[i
]; 
 610                         if ( llvmAtom
->coalescedAway()  ) { 
 611                                 const char* name 
= llvmAtom
->name(); 
 612                                 if ( deadllvmAtoms
.find(name
) == deadllvmAtoms
.end() ) { 
 613                                         if ( logMustPreserve 
)  
 614                                                 fprintf(stderr
, "lto_codegen_add_must_preserve_symbol(%s) because linker coalesce away and replace with a mach-o atom\n", name
); 
 615                                         ::lto_codegen_add_must_preserve_symbol(generator
, name
); 
 616                                         deadllvmAtoms
[name
] = (Atom
*)llvmAtom
; 
 619                         else if ( options
.linkerDeadStripping 
&& !llvmAtom
->live() ) { 
 620                                 const char* name 
= llvmAtom
->name(); 
 621                                 deadllvmAtoms
[name
] = (Atom
*)llvmAtom
; 
 626         // tell code generator about symbols that must be preserved 
 627         for (CStringToAtom::iterator it 
= llvmAtoms
.begin(); it 
!= llvmAtoms
.end(); ++it
) { 
 628                 const char* name 
= it
->first
; 
 629                 Atom
* atom 
= it
->second
; 
 630                 // Include llvm Symbol in export list if it meets one of following two conditions 
 631                 // 1 - atom scope is global (and not linkage unit). 
 632                 // 2 - included in nonLLVMRefs set. 
 633                 // If a symbol is not listed in exportList then LTO is free to optimize it away. 
 634                 if ( (atom
->scope() == ld::Atom::scopeGlobal
) && options
.preserveAllGlobals 
) {  
 635                         if ( logMustPreserve 
) fprintf(stderr
, "lto_codegen_add_must_preserve_symbol(%s) because global symbol\n", name
); 
 636                         ::lto_codegen_add_must_preserve_symbol(generator
, name
); 
 638                 else if ( nonLLVMRefs
.find(name
) != nonLLVMRefs
.end() ) { 
 639                         if ( logMustPreserve 
) fprintf(stderr
, "lto_codegen_add_must_preserve_symbol(%s) because referenced by a mach-o atom\n", name
); 
 640                         ::lto_codegen_add_must_preserve_symbol(generator
, name
); 
 642                 else if ( options
.relocatable 
&& hasNonllvmAtoms 
) { 
 643                         // <rdar://problem/14334895> ld -r mode but merging in some mach-o files, so need to keep libLTO from optimizing away anything 
 644                         if ( logMustPreserve 
) fprintf(stderr
, "lto_codegen_add_must_preserve_symbol(%s) because -r mode disable LTO dead stripping\n", name
); 
 645                         ::lto_codegen_add_must_preserve_symbol(generator
, name
); 
 649         // <rdar://problem/16165191> tell code generator to preserve initial undefines 
 650         for( std::vector
<const char*>::const_iterator it
=options
.initialUndefines
->begin(); it 
!= options
.initialUndefines
->end(); ++it
) { 
 651                 if ( logMustPreserve 
) fprintf(stderr
, "lto_codegen_add_must_preserve_symbol(%s) because it is an initial undefine\n", *it
); 
 652                 ::lto_codegen_add_must_preserve_symbol(generator
, *it
); 
 655     // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o) 
 656     if ( options
.relocatable 
&& !hasNonllvmAtoms 
) { 
 657                 if ( ! ::lto_codegen_write_merged_modules(generator
, options
.outputFilePath
) ) { 
 658                         // HACK, no good way to tell linker we are all done, so just quit 
 661                 warning("could not produce merged bitcode file"); 
 664         // set code-gen model 
 665         lto_codegen_model model 
= LTO_CODEGEN_PIC_MODEL_DYNAMIC
; 
 666         if ( options
.mainExecutable 
) { 
 667                 if ( options
.staticExecutable 
) { 
 668                         // x86_64 "static" or any "-static -pie" is really dynamic code model 
 669                         if ( (options
.arch 
== CPU_TYPE_X86_64
) || options
.pie 
) 
 670                                 model 
= LTO_CODEGEN_PIC_MODEL_DYNAMIC
; 
 672                                 model 
= LTO_CODEGEN_PIC_MODEL_STATIC
; 
 676                                 model 
= LTO_CODEGEN_PIC_MODEL_DYNAMIC
; 
 678                                 model 
= LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC
; 
 682                 if ( options
.allowTextRelocs 
) 
 683                         model 
= LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC
; 
 685                         model 
= LTO_CODEGEN_PIC_MODEL_DYNAMIC
; 
 687         if ( ::lto_codegen_set_pic_model(generator
, model
) ) 
 688                 throwf("could not create set codegen model: %s", lto_get_error_message()); 
 690     // if requested, save off merged bitcode file 
 691     if ( options
.saveTemps 
) { 
 692         char tempBitcodePath
[MAXPATHLEN
]; 
 693         strcpy(tempBitcodePath
, options
.outputFilePath
); 
 694         strcat(tempBitcodePath
, ".lto.bc"); 
 695         ::lto_codegen_write_merged_modules(generator
, tempBitcodePath
); 
 698 #if LTO_API_VERSION >= 3 
 699         // find assembler next to linker 
 701         uint32_t bufSize 
= PATH_MAX
; 
 702         if ( _NSGetExecutablePath(path
, &bufSize
) != -1 ) { 
 703                 char* lastSlash 
= strrchr(path
, '/'); 
 704                 if ( lastSlash 
!= NULL 
) { 
 705                         strcpy(lastSlash
+1, "as"); 
 706                         struct stat statInfo
; 
 707                         if ( stat(path
, &statInfo
) == 0 ) 
 708                                 ::lto_codegen_set_assembler_path(generator
, path
); 
 712         // run code generator 
 714         const uint8_t* machOFile 
= (uint8_t*)::lto_codegen_compile(generator
, &machOFileLen
); 
 715         if ( machOFile 
== NULL 
)  
 716                 throwf("could not do LTO codegen: '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version()); 
 718     // if requested, save off temp mach-o file 
 719     if ( options
.saveTemps 
) { 
 720         char tempMachoPath
[MAXPATHLEN
]; 
 721         strcpy(tempMachoPath
, options
.outputFilePath
); 
 722         strcat(tempMachoPath
, ".lto.o"); 
 723         int fd 
= ::open(tempMachoPath
, O_CREAT 
| O_WRONLY 
| O_TRUNC
, 0666); 
 725                         ::write(fd
, machOFile
, machOFileLen
); 
 728                 //      save off merged bitcode file 
 729                 char tempOptBitcodePath
[MAXPATHLEN
]; 
 730         strcpy(tempOptBitcodePath
, options
.outputFilePath
); 
 731         strcat(tempOptBitcodePath
, ".lto.opt.bc"); 
 732         ::lto_codegen_write_merged_modules(generator
, tempOptBitcodePath
); 
 735         // if needed, save temp mach-o file to specific location 
 736         if ( options
.tmpObjectFilePath 
!= NULL 
) { 
 737                 int fd 
= ::open(options
.tmpObjectFilePath
, O_CREAT 
| O_WRONLY 
| O_TRUNC
, 0666); 
 739                         ::write(fd
, machOFile
, machOFileLen
); 
 743                         warning("could not write LTO temp file '%s', errno=%d", options
.tmpObjectFilePath
, errno
); 
 747         // parse generated mach-o file into a MachOReader 
 748         ld::relocatable::File
* machoFile 
= parseMachOFile(machOFile
, machOFileLen
, options
); 
 750         // sync generated mach-o atoms with existing atoms ld knows about 
 751         if ( logAtomsBeforeSync 
) { 
 752                 fprintf(stderr
, "llvmAtoms:\n"); 
 753                 for (CStringToAtom::iterator it 
= llvmAtoms
.begin(); it 
!= llvmAtoms
.end(); ++it
) { 
 754                         const char* name 
= it
->first
; 
 755                         Atom
* atom 
= it
->second
; 
 756                         fprintf(stderr
, "\t%p\t%s\n", atom
, name
); 
 758                 fprintf(stderr
, "deadllvmAtoms:\n"); 
 759                 for (CStringToAtom::iterator it 
= deadllvmAtoms
.begin(); it 
!= deadllvmAtoms
.end(); ++it
) { 
 760                         const char* name 
= it
->first
; 
 761                         Atom
* atom 
= it
->second
; 
 762                         fprintf(stderr
, "\t%p\t%s\n", atom
, name
); 
 765         AtomSyncer 
syncer(additionalUndefines
, newAtoms
, llvmAtoms
, deadllvmAtoms
, options
); 
 766         machoFile
->forEachAtom(syncer
); 
 768         // Remove InternalAtoms from ld 
 769         for (std::vector
<File
*>::iterator it
=_s_files
.begin(); it 
!= _s_files
.end(); ++it
) { 
 770                 (*it
)->internalAtom().setCoalescedAway(); 
 772         // Remove Atoms from ld if code generator optimized them away 
 773         for (CStringToAtom::iterator li 
= llvmAtoms
.begin(), le 
= llvmAtoms
.end(); li 
!= le
; ++li
) { 
 774                 // check if setRealAtom() called on this Atom 
 775                 if ( li
->second
->compiledAtom() == NULL 
) { 
 776                         //fprintf(stderr, "llvm optimized away %p %s\n", li->second, li->second->name()); 
 777                         li
->second
->setCoalescedAway(); 
 781         // notify about file level attributes 
 782         handler
.doFile(*machoFile
); 
 784         // if final mach-o file has debug info, update original bitcode files to match 
 785         for (std::vector
<File
*>::iterator it
=_s_files
.begin(); it 
!= _s_files
.end(); ++it
) { 
 786                 (*it
)->setDebugInfo(machoFile
->debugInfo(), machoFile
->path(), 
 787                                                         machoFile
->modificationTime(), machoFile
->cpuSubType()); 
 794 void Parser::AtomSyncer::doAtom(const ld::Atom
& machoAtom
) 
 796         static const bool log 
= false; 
 797         static const ld::Atom
* lastProxiedAtom 
= NULL
; 
 798         static const ld::File
* lastProxiedFile 
= NULL
; 
 799         // update proxy atoms to point to real atoms and find new atoms 
 800         const char* name 
= machoAtom
.name(); 
 801         CStringToAtom::iterator pos 
= _llvmAtoms
.find(name
); 
 802         if ( pos 
!= _llvmAtoms
.end() ) { 
 803                 // turn Atom into a proxy for this mach-o atom 
 804                 pos
->second
->setCompiledAtom(machoAtom
); 
 805                 lastProxiedAtom 
= &machoAtom
; 
 806                 lastProxiedFile 
= pos
->second
->file(); 
 807                 if (log
) fprintf(stderr
, "AtomSyncer, mach-o atom %p synced to lto atom %p (name=%s)\n", &machoAtom
, pos
->second
, machoAtom
.name()); 
 810                 // an atom of this name was not in the allAtoms list the linker gave us 
 811                 if ( _deadllvmAtoms
.find(name
) != _deadllvmAtoms
.end() ) { 
 812                         // this corresponding to an atom that the linker coalesced away or marked not-live 
 813                         if ( _options
.linkerDeadStripping 
) { 
 814                                 // llvm seems to want this atom and -dead_strip is enabled, so it will be deleted if not needed, so add back 
 815                                 Atom
* llvmAtom 
= _deadllvmAtoms
[name
]; 
 816                                 llvmAtom
->setCompiledAtom(machoAtom
); 
 817                                 _newAtoms
.push_back(&machoAtom
); 
 818                                 if (log
) fprintf(stderr
, "AtomSyncer, mach-o atom %p matches dead lto atom %p but adding back (name=%s)\n", &machoAtom
, llvmAtom
, machoAtom
.name()); 
 821                                 // Don't pass it back as a new atom 
 822                                 if (log
) fprintf(stderr
, "AtomSyncer, mach-o atom %p matches dead lto atom %p (name=%s)\n", &machoAtom
, _deadllvmAtoms
[name
], machoAtom
.name()); 
 827                         // this is something new that lto conjured up, tell ld its new 
 828                         _newAtoms
.push_back(&machoAtom
); 
 829                         // <rdar://problem/15469363> if new static atom in same section as previous non-static atom, assign to same file as previous 
 830                         if ( (lastProxiedAtom 
!= NULL
) && (lastProxiedAtom
->section() == machoAtom
.section()) ) { 
 831                                 ld::Atom
* ma 
= const_cast<ld::Atom
*>(&machoAtom
); 
 832                                 ma
->setFile(lastProxiedFile
); 
 834                         if (log
) fprintf(stderr
, "AtomSyncer, mach-o atom %p is totally new (name=%s)\n", &machoAtom
, machoAtom
.name()); 
 838         // adjust fixups to go through proxy atoms 
 839         if (log
) fprintf(stderr
, "  adjusting fixups in atom: %s\n", machoAtom
.name()); 
 840         for (ld::Fixup::iterator fit
=machoAtom
.fixupsBegin(); fit 
!= machoAtom
.fixupsEnd(); ++fit
) { 
 841                 switch ( fit
->binding 
) { 
 842                         case ld::Fixup::bindingNone
: 
 844                         case ld::Fixup::bindingByNameUnbound
: 
 845                                 // don't know if this target has been seen by linker before or if it is new 
 846                                 // be conservative and tell linker it is new 
 847                                 _additionalUndefines
.push_back(fit
->u
.name
); 
 848                                 if (log
) fprintf(stderr
, "    adding by-name symbol %s\n", fit
->u
.name
); 
 850                         case ld::Fixup::bindingDirectlyBound
: 
 851                                 // If mach-o atom is referencing another mach-o atom then  
 852                                 // reference is not going through Atom proxy. Fix it here to ensure that all 
 853                                 // llvm symbol references always go through Atom proxy. 
 855                                         const char* targetName 
= fit
->u
.target
->name(); 
 856                                         CStringToAtom::iterator post 
= _llvmAtoms
.find(targetName
); 
 857                                         if ( post 
!= _llvmAtoms
.end() ) { 
 858                                                 const ld::Atom
* t 
= post
->second
; 
 859                                                 if (log
) fprintf(stderr
, "    updating direct reference to %p to be ref to %p: %s\n", fit
->u
.target
, t
, targetName
); 
 863                                                 // <rdar://problem/12859831> Don't unbind follow-on reference into by-name reference  
 864                                                 if ( (_deadllvmAtoms
.find(targetName
) != _deadllvmAtoms
.end()) && (fit
->kind 
!= ld::Fixup::kindNoneFollowOn
) ) { 
 865                                                         // target was coalesed away and replace by mach-o atom from a non llvm .o file 
 866                                                         fit
->binding 
= ld::Fixup::bindingByNameUnbound
; 
 867                                                         fit
->u
.name 
= targetName
; 
 871                                 //fprintf(stderr, "    direct ref to: %s (scope=%d)\n", fit->u.target->name(), fit->u.target->scope()); 
 873                         case ld::Fixup::bindingByContentBound
: 
 874                                 //fprintf(stderr, "    direct by content to: %s\n", fit->u.target->name()); 
 876                         case ld::Fixup::bindingsIndirectlyBound
: 
 877                                 assert(0 && "indirect binding found in initial mach-o file?"); 
 878                                 //fprintf(stderr, "    indirect by content to: %u\n", fit->u.bindingIndex); 
 886         static pthread_mutex_t lto_lock
; 
 888         Mutex() { pthread_mutex_lock(<o_lock
); } 
 889         ~Mutex() { pthread_mutex_unlock(<o_lock
); } 
 891 pthread_mutex_t 
Mutex::lto_lock 
= PTHREAD_MUTEX_INITIALIZER
; 
 894 // Used by archive reader to see if member is an llvm bitcode file 
 896 bool isObjectFile(const uint8_t* fileContent
, uint64_t fileLength
, cpu_type_t architecture
, cpu_subtype_t subarch
) 
 899         return Parser::validFile(fileContent
, fileLength
, architecture
, subarch
); 
 904 // main function used by linker to instantiate ld::Files 
 906 ld::relocatable::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
,  
 907                                                                 const char* path
, time_t modTime
, ld::File::Ordinal ordinal
, 
 908                                                                 cpu_type_t architecture
, cpu_subtype_t subarch
, bool logAllFiles
, 
 909                                                                 bool verboseOptimizationHints
) 
 912         if ( Parser::validFile(fileContent
, fileLength
, architecture
, subarch
) ) 
 913                 return Parser::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, architecture
, subarch
, logAllFiles
, verboseOptimizationHints
); 
 919 // used by "ld -v" to report version of libLTO.dylib being used 
 921 const char* version() 
 924         return ::lto_get_version(); 
 929 // used by ld for error reporting 
 931 bool libLTOisLoaded() 
 934         return (::lto_get_version() != NULL
); 
 938 // used by ld for error reporting 
 940 const char* archName(const uint8_t* fileContent
, uint64_t fileLength
) 
 943         return Parser::fileKind(fileContent
, fileLength
); 
 947 // used by ld for doing link time optimization 
 949 bool optimize(  const std::vector
<const ld::Atom
*>&     allAtoms
, 
 951                                 const OptimizeOptions
&                          options
, 
 952                                 ld::File::AtomHandler
&                          handler
, 
 953                                 std::vector
<const ld::Atom
*>&           newAtoms
,  
 954                                 std::vector
<const char*>&                       additionalUndefines
) 
 957         return Parser::optimize(allAtoms
, state
, options
, handler
, newAtoms
, additionalUndefines
);