]> git.saurik.com Git - apple/ld64.git/blame - src/ld/parsers/lto_file.cpp
ld64-241.9.tar.gz
[apple/ld64.git] / src / ld / parsers / lto_file.cpp
CommitLineData
a645023d
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2006-2010 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#ifndef __LTO_READER_H__
26#define __LTO_READER_H__
27
28#include <stdlib.h>
29#include <sys/param.h>
30#include <sys/fcntl.h>
31#include <sys/stat.h>
32#include <errno.h>
d425e388 33#include <pthread.h>
a645023d
A
34#include <mach-o/dyld.h>
35#include <vector>
d425e388
A
36#include <unordered_set>
37#include <unordered_map>
a645023d
A
38
39#include "MachOFileAbstraction.hpp"
40#include "Architectures.hpp"
41#include "ld.hpp"
42#include "macho_relocatable_file.h"
43#include "lto_file.h"
44
afe874b1
A
45// #defines are a work around for <rdar://problem/8760268>
46#define __STDC_LIMIT_MACROS 1
47#define __STDC_CONSTANT_MACROS 1
a645023d
A
48#include "llvm-c/lto.h"
49
a645023d
A
50namespace lto {
51
52
53//
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.
59//
60class InternalAtom : public ld::Atom
61{
62public:
63 InternalAtom(class File& f);
64 // overrides of ld::Atom
65 virtual ld::File* file() const { return &_file; }
a645023d
A
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()]; }
73
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,
599556ff 77 ld::Fixup::kindNone, false, strdup(nm))); }
a645023d
A
78private:
79
80 ld::File& _file;
81 mutable std::vector<ld::Fixup> _undefs;
82};
83
84
85//
86// LLVM bitcode file
87//
88class File : public ld::relocatable::File
89{
90public:
b1f7435d
A
91 File(const char* path, time_t mTime, ld::File::Ordinal ordinal,
92 const uint8_t* content, uint32_t contentLength, cpu_type_t arch);
a645023d
A
93 virtual ~File();
94
95 // overrides of ld::File
96 virtual bool forEachAtom(ld::File::AtomHandler&) const;
97 virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const
98 { return false; }
99 virtual uint32_t cpuSubType() const { return _cpuSubType; }
100
101 // overrides of ld::relocatable::File
a645023d
A
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; }
f80fe69f
A
108 virtual LinkerOptionsList* linkerOptions() const { return NULL; }
109
a645023d 110
599556ff 111 void release();
a645023d
A
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)
116 { _debugInfo = k;
117 _debugInfoPath = pth;
118 _debugInfoModTime = modTime;
119 _cpuSubType = subtype;}
120
121private:
122 friend class Atom;
123 friend class InternalAtom;
124 friend class Parser;
125
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;
137};
138
139//
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.
145//
146class Atom : public ld::Atom
147{
148public:
149 Atom(File& f, const char* name, ld::Atom::Scope s,
b2fa67a8 150 ld::Atom::Definition d, ld::Atom::Combine c, ld::Atom::Alignment a, bool ah);
a645023d
A
151
152 // overrides of ld::Atom
153 virtual ld::File* file() const { return &_file; }
b1f7435d
A
154 virtual const char* translationUnitSource() const
155 { return (_compiledAtom ? _compiledAtom->translationUnitSource() : NULL); }
a645023d
A
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); }
179
180 const ld::Atom* compiledAtom() { return _compiledAtom; }
181 void setCompiledAtom(const ld::Atom& atom);
182
183private:
184
185 File& _file;
186 const char* _name;
187 const ld::Atom* _compiledAtom;
188};
189
190
191
192
193
194
195
196class Parser
197{
198public:
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,
9543cb2f
A
202 time_t modTime, ld::File::Ordinal ordinal, cpu_type_t architecture, cpu_subtype_t subarch,
203 bool logAllFiles, bool verboseOptimizationHints);
a645023d
A
204 static bool libLTOisLoaded() { return (::lto_get_version() != NULL); }
205 static bool optimize( const std::vector<const ld::Atom*>& allAtoms,
206 ld::Internal& state,
a645023d
A
207 const OptimizeOptions& options,
208 ld::File::AtomHandler& handler,
209 std::vector<const ld::Atom*>& newAtoms,
210 std::vector<const char*>& additionalUndefines);
211
212 static const char* ltoVersion() { return ::lto_get_version(); }
213
214private:
215 static const char* tripletPrefixForArch(cpu_type_t arch);
ebf6f434 216 static ld::relocatable::File* parseMachOFile(const uint8_t* p, size_t len, const OptimizeOptions& options);
9543cb2f
A
217#if LTO_API_VERSION >= 7
218 static void ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t, const char*, void*);
219#endif
a645023d 220
d425e388
A
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;
a645023d
A
223
224 class AtomSyncer : public ld::File::AtomHandler {
225 public:
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&) { }
231
599556ff 232
a645023d
A
233 const OptimizeOptions& _options;
234 std::vector<const char*>& _additionalUndefines;
235 std::vector<const ld::Atom*>& _newAtoms;
236 CStringToAtom _llvmAtoms;
237 CStringToAtom _deadllvmAtoms;
238 };
239
240 static std::vector<File*> _s_files;
241};
242
243std::vector<File*> Parser::_s_files;
244
245
246bool Parser::validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture, cpu_subtype_t subarch)
247{
ebf6f434
A
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);
251 if ( !result ) {
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);
255 }
a645023d 256 }
ebf6f434
A
257 return result;
258 }
a645023d
A
259 }
260 return false;
261}
262
263const char* Parser::fileKind(const uint8_t* p, uint64_t fileLength)
264{
265 if ( (p[0] == 0xDE) && (p[1] == 0xC0) && (p[2] == 0x17) && (p[3] == 0x0B) ) {
ebf6f434
A
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 ) {
afe874b1 270 if ( ::lto_module_is_object_file_in_memory_for_target(p, fileLength, t->llvmTriplePrefix) )
ebf6f434
A
271 return t->archName;
272 }
273 else {
274 return t->archName;
afe874b1 275 }
ebf6f434 276 }
a645023d
A
277 }
278 return "unknown bitcode architecture";
279 }
280 return NULL;
281}
282
b1f7435d 283File* Parser::parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, ld::File::Ordinal ordinal,
9543cb2f 284 cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles, bool verboseOptimizationHints)
a645023d 285{
b1f7435d 286 File* f = new File(path, modTime, ordinal, fileContent, fileLength, architecture);
a645023d
A
287 _s_files.push_back(f);
288 if ( logAllFiles )
289 printf("%s\n", path);
290 return f;
291}
292
293
ebf6f434 294ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, const OptimizeOptions& options)
a645023d
A
295{
296 mach_o::relocatable::ParserOptions objOpts;
297 objOpts.architecture = options.arch;
298 objOpts.objSubtypeMustMatch = false;
299 objOpts.logAllFiles = false;
f80fe69f
A
300 objOpts.warnUnwindConversionProblems = options.needsUnwindInfoSection;
301 objOpts.keepDwarfUnwind = options.keepDwarfUnwind;
302 objOpts.forceDwarfConversion = false;
9543cb2f
A
303 objOpts.neverConvertDwarf = false;
304 objOpts.verboseOptimizationHints = options.verboseOptimizationHints;
599556ff 305
a645023d
A
306 objOpts.subType = 0;
307
308 // mach-o parsing is done in-memory, but need path for debug notes
309 const char* path = "/tmp/lto.o";
310 time_t modTime = 0;
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;
316 }
317
ebf6f434 318 ld::relocatable::File* result = mach_o::relocatable::parse(p, len, path, modTime, ld::File::Ordinal::LTOOrdinal(), objOpts);
a645023d
A
319 if ( result != NULL )
320 return result;
321 throw "LLVM LTO, file is not of required architecture";
322}
323
324
325
b1f7435d
A
326File::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),
a645023d
A
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)
332{
333 const bool log = false;
334
335 // create llvm module
599556ff
A
336#if LTO_API_VERSION >= 9
337 _module = ::lto_module_create_from_memory_with_path(content, contentLength, pth);
338 if ( _module == NULL )
339#endif
a645023d
A
340 _module = ::lto_module_create_from_memory(content, contentLength);
341 if ( _module == NULL )
d425e388 342 throwf("could not parse object file %s: '%s', using libLTO version '%s'", pth, ::lto_get_error_message(), ::lto_get_version());
a645023d
A
343
344 if ( log ) fprintf(stderr, "bitcode file: %s\n", pth);
345
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);
352
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) )
357 continue;
358
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;
364 break;
365 case LTO_SYMBOL_DEFINITION_TENTATIVE:
366 def = ld::Atom::definitionTentative;
367 break;
368 case LTO_SYMBOL_DEFINITION_WEAK:
369 def = ld::Atom::definitionRegular;
370 combine = ld::Atom::combineByName;
371 break;
372 case LTO_SYMBOL_DEFINITION_UNDEFINED:
373 case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
374 def = ld::Atom::definitionProxy;
375 break;
376 default:
377 throwf("unknown definition kind for symbol %s in bitcode file %s", name, pth);
378 }
379
380 // make LLVM atoms for definitions and a reference for undefines
381 if ( def != ld::Atom::definitionProxy ) {
382 ld::Atom::Scope scope;
b2fa67a8 383 bool autohide = false;
a645023d
A
384 switch ( attr & LTO_SYMBOL_SCOPE_MASK) {
385 case LTO_SYMBOL_SCOPE_INTERNAL:
386 scope = ld::Atom::scopeTranslationUnit;
387 break;
388 case LTO_SYMBOL_SCOPE_HIDDEN:
389 scope = ld::Atom::scopeLinkageUnit;
390 break;
391 case LTO_SYMBOL_SCOPE_DEFAULT:
392 scope = ld::Atom::scopeGlobal;
393 break;
b2fa67a8
A
394#if LTO_API_VERSION >= 4
395 case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN:
396 scope = ld::Atom::scopeGlobal;
397 autohide = true;
398 break;
399#endif
a645023d
A
400 default:
401 throwf("unknown scope for symbol %s in bitcode file %s", name, pth);
402 }
403 // only make atoms for non-internal symbols
404 if ( scope == ld::Atom::scopeTranslationUnit )
405 continue;
406 uint8_t alignment = (attr & LTO_SYMBOL_ALIGNMENT_MASK);
407 // make Atom using placement new operator
b2fa67a8 408 new (&_atomArray[_atomArrayCount++]) Atom(*this, name, scope, def, combine, alignment, autohide);
ebf6f434 409 if ( scope != ld::Atom::scopeTranslationUnit )
a645023d
A
410 _internalAtom.addReference(name);
411 if ( log ) fprintf(stderr, "\t0x%08X %s\n", attr, name);
412 }
413 else {
414 // add to list of external references
415 _internalAtom.addReference(name);
416 if ( log ) fprintf(stderr, "\t%s (undefined)\n", name);
417 }
418 }
419}
420
421File::~File()
599556ff
A
422{
423 this->release();
424}
425
426void File::release()
a645023d
A
427{
428 if ( _module != NULL )
429 ::lto_module_dispose(_module);
599556ff 430 _module = NULL;
a645023d
A
431}
432
433bool File::forEachAtom(ld::File::AtomHandler& handler) const
434{
435 handler.doAtom(_internalAtom);
436 for(uint32_t i=0; i < _atomArrayCount; ++i) {
437 handler.doAtom(_atomArray[i]);
438 }
439 return true;
440}
441
442InternalAtom::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)),
445 _file(f)
446{
447}
448
b2fa67a8
A
449Atom::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)
a645023d
A
451 : ld::Atom(f._section, d, c, s, ld::Atom::typeLTOtemporary,
452 ld::Atom::symbolTableIn, false, false, false, a),
599556ff 453 _file(f), _name(strdup(nm)), _compiledAtom(NULL)
a645023d 454{
b2fa67a8
A
455 if ( ah )
456 this->setAutoHide();
a645023d
A
457}
458
459void Atom::setCompiledAtom(const ld::Atom& atom)
460{
461 // set delegate so virtual methods go to it
462 _compiledAtom = &atom;
463
464 //fprintf(stderr, "setting lto atom %p to delegate to mach-o atom %p (%s)\n", this, &atom, atom.name());
465
466 // update fields in ld::Atom to match newly constructed mach-o atom
467 (const_cast<Atom*>(this))->setAttributesFromAtom(atom);
468}
469
470
471
f80fe69f
A
472// <rdar://problem/12379604> The order that files are merged must match command line order
473struct CommandLineOrderFileSorter
474{
475 bool operator()(File* left, File* right)
476 {
477 return ( left->ordinal() < right->ordinal() );
478 }
479};
480
481
9543cb2f
A
482#if LTO_API_VERSION >= 7
483void Parser::ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity, const char* message, void*)
484{
485 switch ( severity ) {
599556ff
A
486#if LTO_API_VERSION >= 10
487 case LTO_DS_REMARK:
488 fprintf(stderr, "ld: LTO remark: %s\n", message);
489 break;
490#endif
9543cb2f
A
491 case LTO_DS_NOTE:
492 case LTO_DS_WARNING:
493 warning("%s", message);
494 break;
495 case LTO_DS_ERROR:
496 throwf("%s", message);
497 }
498}
499#endif
500
a645023d
A
501bool Parser::optimize( const std::vector<const ld::Atom*>& allAtoms,
502 ld::Internal& state,
a645023d
A
503 const OptimizeOptions& options,
504 ld::File::AtomHandler& handler,
505 std::vector<const ld::Atom*>& newAtoms,
506 std::vector<const char*>& additionalUndefines)
507{
508 const bool logMustPreserve = false;
509 const bool logExtraOptions = false;
510 const bool logBitcodeFiles = false;
511 const bool logAtomsBeforeSync = false;
512
513 // exit quickly if nothing to do
514 if ( _s_files.size() == 0 )
515 return false;
516
517 // print out LTO version string if -v was used
518 if ( options.verbose )
d425e388 519 fprintf(stderr, "%s\n", ::lto_get_version());
a645023d
A
520
521 // create optimizer and add each Reader
522 lto_code_gen_t generator = ::lto_codegen_create();
9543cb2f
A
523#if LTO_API_VERSION >= 7
524 lto_codegen_set_diagnostic_handler(generator, ltoDiagnosticHandler, NULL);
525#endif
526
f80fe69f
A
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;
a645023d 530 for (std::vector<File*>::iterator it=_s_files.begin(); it != _s_files.end(); ++it) {
f80fe69f
A
531 File* f = *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());
599556ff
A
536 // <rdar://problem/15471128> linker should release module as soon as possible
537 f->release();
f80fe69f 538 lastOrdinal = f->ordinal();
a645023d
A
539 }
540
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);
545 }
546
f80fe69f
A
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);
550
a645023d
A
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;
564 }
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());
572 break;
573 case ld::Fixup::bindingsIndirectlyBound:
574 target = state.indirectBindingTable[fit->u.bindingIndex];
9543cb2f 575 if ( (target != NULL) && (target->contentType() == ld::Atom::typeLTOtemporary) )
a645023d
A
576 nonLLVMRefs.insert(target->name());
577 default:
578 break;
579 }
580 }
581 }
599556ff 582 else if ( atom->scope() >= ld::Atom::scopeLinkageUnit ) {
a645023d
A
583 llvmAtoms[atom->name()] = (Atom*)atom;
584 }
585 }
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());
590 }
591
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;
604 }
605 }
606 for (std::vector<File*>::iterator it=_s_files.begin(); it != _s_files.end(); ++it) {
607 File* file = *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;
617 }
618 }
619 else if ( options.linkerDeadStripping && !llvmAtom->live() ) {
620 const char* name = llvmAtom->name();
621 deadllvmAtoms[name] = (Atom*)llvmAtom;
622 }
623 }
624 }
625
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.
ebf6f434 634 if ( (atom->scope() == ld::Atom::scopeGlobal) && options.preserveAllGlobals ) {
a645023d
A
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);
637 }
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);
641 }
599556ff
A
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);
646 }
a645023d
A
647 }
648
599556ff
A
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);
653 }
654
a645023d
A
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
659 exit(0);
660 }
661 warning("could not produce merged bitcode file");
662 }
663
664 // set code-gen model
665 lto_codegen_model model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
666 if ( options.mainExecutable ) {
667 if ( options.staticExecutable ) {
d425e388
A
668 // x86_64 "static" or any "-static -pie" is really dynamic code model
669 if ( (options.arch == CPU_TYPE_X86_64) || options.pie )
a645023d
A
670 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
671 else
672 model = LTO_CODEGEN_PIC_MODEL_STATIC;
673 }
674 else {
675 if ( options.pie )
676 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
677 else
678 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
679 }
680 }
681 else {
682 if ( options.allowTextRelocs )
683 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
684 else
685 model = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
686 }
687 if ( ::lto_codegen_set_pic_model(generator, model) )
688 throwf("could not create set codegen model: %s", lto_get_error_message());
689
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);
696 }
697
698#if LTO_API_VERSION >= 3
699 // find assembler next to linker
700 char path[PATH_MAX];
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);
709 }
710 }
711#endif
712 // run code generator
713 size_t machOFileLen;
714 const uint8_t* machOFile = (uint8_t*)::lto_codegen_compile(generator, &machOFileLen);
715 if ( machOFile == NULL )
d425e388 716 throwf("could not do LTO codegen: '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version());
a645023d
A
717
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);
724 if ( fd != -1) {
725 ::write(fd, machOFile, machOFileLen);
726 ::close(fd);
727 }
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);
733 }
734
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);
738 if ( fd != -1) {
739 ::write(fd, machOFile, machOFileLen);
740 ::close(fd);
741 }
742 else {
743 warning("could not write LTO temp file '%s', errno=%d", options.tmpObjectFilePath, errno);
744 }
745 }
746
747 // parse generated mach-o file into a MachOReader
ebf6f434 748 ld::relocatable::File* machoFile = parseMachOFile(machOFile, machOFileLen, options);
a645023d
A
749
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;
599556ff
A
755 Atom* atom = it->second;
756 fprintf(stderr, "\t%p\t%s\n", atom, name);
a645023d
A
757 }
758 fprintf(stderr, "deadllvmAtoms:\n");
759 for (CStringToAtom::iterator it = deadllvmAtoms.begin(); it != deadllvmAtoms.end(); ++it) {
760 const char* name = it->first;
599556ff
A
761 Atom* atom = it->second;
762 fprintf(stderr, "\t%p\t%s\n", atom, name);
a645023d
A
763 }
764 }
765 AtomSyncer syncer(additionalUndefines, newAtoms, llvmAtoms, deadllvmAtoms, options);
766 machoFile->forEachAtom(syncer);
767
768 // Remove InternalAtoms from ld
769 for (std::vector<File*>::iterator it=_s_files.begin(); it != _s_files.end(); ++it) {
770 (*it)->internalAtom().setCoalescedAway();
771 }
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();
778 }
779 }
780
781 // notify about file level attributes
782 handler.doFile(*machoFile);
783
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());
788 }
789
790 return true;
791}
792
793
794void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom)
795{
599556ff 796 static const bool log = false;
9543cb2f
A
797 static const ld::Atom* lastProxiedAtom = NULL;
798 static const ld::File* lastProxiedFile = NULL;
a645023d
A
799 // update proxy atoms to point to real atoms and find new atoms
800 const char* name = machoAtom.name();
599556ff
A
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());
808 }
809 else {
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);
a645023d 817 _newAtoms.push_back(&machoAtom);
599556ff 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());
a645023d 819 }
599556ff
A
820 else {
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());
823 }
a645023d 824 }
599556ff
A
825 else
826 {
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);
833 }
834 if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p is totally new (name=%s)\n", &machoAtom, machoAtom.name());
9543cb2f 835 }
a645023d
A
836 }
837
838 // adjust fixups to go through proxy atoms
599556ff 839 if (log) fprintf(stderr, " adjusting fixups in atom: %s\n", machoAtom.name());
a645023d
A
840 for (ld::Fixup::iterator fit=machoAtom.fixupsBegin(); fit != machoAtom.fixupsEnd(); ++fit) {
841 switch ( fit->binding ) {
842 case ld::Fixup::bindingNone:
843 break;
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);
599556ff 848 if (log) fprintf(stderr, " adding by-name symbol %s\n", fit->u.name);
a645023d
A
849 break;
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.
599556ff 854 {
a645023d 855 const char* targetName = fit->u.target->name();
599556ff
A
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);
860 fit->u.target = t;
a645023d
A
861 }
862 else {
f80fe69f
A
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) ) {
a645023d
A
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;
868 }
869 }
870 }
871 //fprintf(stderr, " direct ref to: %s (scope=%d)\n", fit->u.target->name(), fit->u.target->scope());
872 break;
873 case ld::Fixup::bindingByContentBound:
874 //fprintf(stderr, " direct by content to: %s\n", fit->u.target->name());
875 break;
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);
879 break;
880 }
881 }
882
883}
884
ebf6f434
A
885class Mutex {
886 static pthread_mutex_t lto_lock;
887public:
888 Mutex() { pthread_mutex_lock(&lto_lock); }
889 ~Mutex() { pthread_mutex_unlock(&lto_lock); }
890};
891pthread_mutex_t Mutex::lto_lock = PTHREAD_MUTEX_INITIALIZER;
a645023d
A
892
893//
894// Used by archive reader to see if member is an llvm bitcode file
895//
896bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture, cpu_subtype_t subarch)
897{
ebf6f434 898 Mutex lock;
a645023d
A
899 return Parser::validFile(fileContent, fileLength, architecture, subarch);
900}
901
902
903//
904// main function used by linker to instantiate ld::Files
905//
906ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength,
b1f7435d 907 const char* path, time_t modTime, ld::File::Ordinal ordinal,
9543cb2f
A
908 cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles,
909 bool verboseOptimizationHints)
a645023d 910{
ebf6f434 911 Mutex lock;
a645023d 912 if ( Parser::validFile(fileContent, fileLength, architecture, subarch) )
9543cb2f 913 return Parser::parse(fileContent, fileLength, path, modTime, ordinal, architecture, subarch, logAllFiles, verboseOptimizationHints);
a645023d
A
914 else
915 return NULL;
916}
917
918//
919// used by "ld -v" to report version of libLTO.dylib being used
920//
921const char* version()
922{
ebf6f434 923 Mutex lock;
a645023d
A
924 return ::lto_get_version();
925}
926
927
928//
929// used by ld for error reporting
930//
931bool libLTOisLoaded()
932{
ebf6f434 933 Mutex lock;
a645023d
A
934 return (::lto_get_version() != NULL);
935}
936
937//
938// used by ld for error reporting
939//
940const char* archName(const uint8_t* fileContent, uint64_t fileLength)
941{
ebf6f434 942 Mutex lock;
a645023d
A
943 return Parser::fileKind(fileContent, fileLength);
944}
945
946//
947// used by ld for doing link time optimization
948//
949bool optimize( const std::vector<const ld::Atom*>& allAtoms,
950 ld::Internal& state,
a645023d
A
951 const OptimizeOptions& options,
952 ld::File::AtomHandler& handler,
953 std::vector<const ld::Atom*>& newAtoms,
954 std::vector<const char*>& additionalUndefines)
955{
ebf6f434
A
956 Mutex lock;
957 return Parser::optimize(allAtoms, state, options, handler, newAtoms, additionalUndefines);
a645023d
A
958}
959
960
961
962}; // namespace lto
963
964
965#endif
966