X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/9543cb2f21e50a417dc8cf37eb7173f353536979..599556ff3dd31aab68bb9685f1ed7fc4867803e7:/src/ld/parsers/lto_file.cpp?ds=sidebyside diff --git a/src/ld/parsers/lto_file.cpp b/src/ld/parsers/lto_file.cpp index 3fe21f6..f2cb8ca 100644 --- a/src/ld/parsers/lto_file.cpp +++ b/src/ld/parsers/lto_file.cpp @@ -74,7 +74,7 @@ public: // for adding references to symbols outside bitcode file void addReference(const char* nm) { _undefs.push_back(ld::Fixup(0, ld::Fixup::k1of1, - ld::Fixup::kindNone, false, nm)); } + ld::Fixup::kindNone, false, strdup(nm))); } private: ld::File& _file; @@ -108,6 +108,7 @@ public: virtual LinkerOptionsList* linkerOptions() const { return NULL; } + void release(); lto_module_t module() { return _module; } class InternalAtom& internalAtom() { return _internalAtom; } void setDebugInfo(ld::relocatable::File::DebugInfoKind k, @@ -228,6 +229,7 @@ private: virtual void doAtom(const class ld::Atom&); virtual void doFile(const class ld::File&) { } + const OptimizeOptions& _options; std::vector& _additionalUndefines; std::vector& _newAtoms; @@ -300,6 +302,7 @@ ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, cons objOpts.forceDwarfConversion = false; objOpts.neverConvertDwarf = false; objOpts.verboseOptimizationHints = options.verboseOptimizationHints; + objOpts.subType = 0; // mach-o parsing is done in-memory, but need path for debug notes @@ -330,6 +333,10 @@ 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 >= 9 + _module = ::lto_module_create_from_memory_with_path(content, contentLength, pth); + if ( _module == NULL ) +#endif _module = ::lto_module_create_from_memory(content, contentLength); if ( _module == NULL ) throwf("could not parse object file %s: '%s', using libLTO version '%s'", pth, ::lto_get_error_message(), ::lto_get_version()); @@ -412,9 +419,15 @@ File::File(const char* pth, time_t mTime, ld::File::Ordinal ordinal, const uint8 } File::~File() +{ + this->release(); +} + +void File::release() { if ( _module != NULL ) ::lto_module_dispose(_module); + _module = NULL; } bool File::forEachAtom(ld::File::AtomHandler& handler) const @@ -437,7 +450,7 @@ Atom::Atom(File& f, const char* nm, ld::Atom::Scope s, ld::Atom::Definition d, l ld::Atom::Alignment a, bool ah) : ld::Atom(f._section, d, c, s, ld::Atom::typeLTOtemporary, ld::Atom::symbolTableIn, false, false, false, a), - _file(f), _name(nm), _compiledAtom(NULL) + _file(f), _name(strdup(nm)), _compiledAtom(NULL) { if ( ah ) this->setAutoHide(); @@ -470,6 +483,11 @@ struct CommandLineOrderFileSorter void Parser::ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity, const char* message, void*) { 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: warning("%s", message); @@ -515,6 +533,8 @@ bool Parser::optimize( const std::vector& allAtoms, if ( logBitcodeFiles ) fprintf(stderr, "lto_codegen_add_module(%s)\n", f->path()); if ( ::lto_codegen_add_module(generator, f->module()) ) throwf("lto: could not merge in %s because '%s', using libLTO version '%s'", f->path(), ::lto_get_error_message(), ::lto_get_version()); + // linker should release module as soon as possible + f->release(); lastOrdinal = f->ordinal(); } @@ -559,7 +579,7 @@ bool Parser::optimize( const std::vector& allAtoms, } } } - else { + else if ( atom->scope() >= ld::Atom::scopeLinkageUnit ) { llvmAtoms[atom->name()] = (Atom*)atom; } } @@ -619,8 +639,19 @@ bool Parser::optimize( const std::vector& allAtoms, if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because referenced by a mach-o atom\n", name); ::lto_codegen_add_must_preserve_symbol(generator, name); } + else if ( options.relocatable && hasNonllvmAtoms ) { + // ld -r mode but merging in some mach-o files, so need to keep libLTO from optimizing away anything + if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because -r mode disable LTO dead stripping\n", name); + ::lto_codegen_add_must_preserve_symbol(generator, name); + } } + // tell code generator to preserve initial undefines + for( std::vector::const_iterator it=options.initialUndefines->begin(); it != options.initialUndefines->end(); ++it) { + if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because it is an initial undefine\n", *it); + ::lto_codegen_add_must_preserve_symbol(generator, *it); + } + // special case running ld -r on all bitcode files to produce another bitcode file (instead of mach-o) if ( options.relocatable && !hasNonllvmAtoms ) { if ( ! ::lto_codegen_write_merged_modules(generator, options.outputFilePath) ) { @@ -721,14 +752,14 @@ bool Parser::optimize( const std::vector& allAtoms, fprintf(stderr, "llvmAtoms:\n"); for (CStringToAtom::iterator it = llvmAtoms.begin(); it != llvmAtoms.end(); ++it) { const char* name = it->first; - //Atom* atom = it->second; - fprintf(stderr, "\t%s\n", name); + Atom* atom = it->second; + fprintf(stderr, "\t%p\t%s\n", atom, name); } fprintf(stderr, "deadllvmAtoms:\n"); for (CStringToAtom::iterator it = deadllvmAtoms.begin(); it != deadllvmAtoms.end(); ++it) { const char* name = it->first; - //Atom* atom = it->second; - fprintf(stderr, "\t%s\n", name); + Atom* atom = it->second; + fprintf(stderr, "\t%p\t%s\n", atom, name); } } AtomSyncer syncer(additionalUndefines, newAtoms, llvmAtoms, deadllvmAtoms, options); @@ -762,51 +793,50 @@ bool Parser::optimize( const std::vector& allAtoms, void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom) { + static const bool log = false; static const ld::Atom* lastProxiedAtom = NULL; static const ld::File* lastProxiedFile = NULL; // 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); - lastProxiedAtom = &machoAtom; - lastProxiedFile = pos->second->file(); - } - 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 or marked not-live - if ( _options.linkerDeadStripping ) { - // llvm seems to want this atom and -dead_strip is enabled, so it will be deleted if not needed, so add back - Atom* llvmAtom = _deadllvmAtoms[name]; - llvmAtom->setCompiledAtom(machoAtom); - _newAtoms.push_back(&machoAtom); - } - else { - // Don't pass it back as a new atom - } - } - else - { - // this is something new that lto conjured up, tell ld its new + CStringToAtom::iterator pos = _llvmAtoms.find(name); + if ( pos != _llvmAtoms.end() ) { + // turn Atom into a proxy for this mach-o atom + pos->second->setCompiledAtom(machoAtom); + lastProxiedAtom = &machoAtom; + lastProxiedFile = pos->second->file(); + if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p synced to lto atom %p (name=%s)\n", &machoAtom, pos->second, machoAtom.name()); + } + 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 or marked not-live + if ( _options.linkerDeadStripping ) { + // llvm seems to want this atom and -dead_strip is enabled, so it will be deleted if not needed, so add back + Atom* llvmAtom = _deadllvmAtoms[name]; + llvmAtom->setCompiledAtom(machoAtom); _newAtoms.push_back(&machoAtom); + if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p matches dead lto atom %p but adding back (name=%s)\n", &machoAtom, llvmAtom, machoAtom.name()); } + else { + // Don't pass it back as a new atom + if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p matches dead lto atom %p (name=%s)\n", &machoAtom, _deadllvmAtoms[name], machoAtom.name()); + } } - } - else { - // ld only knew about non-static atoms, so this one must be new - _newAtoms.push_back(&machoAtom); - // if new static atom in same section as previous non-static atom, assign to same file as previous - if ( (lastProxiedAtom != NULL) && (lastProxiedAtom->section() == machoAtom.section()) ) { - ld::Atom* ma = const_cast(&machoAtom); - ma->setFile(lastProxiedFile); + else + { + // this is something new that lto conjured up, tell ld its new + _newAtoms.push_back(&machoAtom); + // if new static atom in same section as previous non-static atom, assign to same file as previous + if ( (lastProxiedAtom != NULL) && (lastProxiedAtom->section() == machoAtom.section()) ) { + ld::Atom* ma = const_cast(&machoAtom); + ma->setFile(lastProxiedFile); + } + if (log) fprintf(stderr, "AtomSyncer, mach-o atom %p is totally new (name=%s)\n", &machoAtom, machoAtom.name()); } } // adjust fixups to go through proxy atoms - //fprintf(stderr, "adjusting fixups in atom: %s\n", machoAtom.name()); + if (log) fprintf(stderr, " adjusting fixups in atom: %s\n", machoAtom.name()); for (ld::Fixup::iterator fit=machoAtom.fixupsBegin(); fit != machoAtom.fixupsEnd(); ++fit) { switch ( fit->binding ) { case ld::Fixup::bindingNone: @@ -815,17 +845,19 @@ void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom) // don't know if this target has been seen by linker before or if it is new // be conservative and tell linker it is new _additionalUndefines.push_back(fit->u.name); - //fprintf(stderr, " by name ref to: %s\n", fit->u.name); + if (log) fprintf(stderr, " adding by-name symbol %s\n", fit->u.name); 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. - if ( fit->u.target->scope() != ld::Atom::scopeTranslationUnit ) { + { const char* targetName = fit->u.target->name(); - CStringToAtom::iterator pos = _llvmAtoms.find(targetName); - if ( pos != _llvmAtoms.end() ) { - fit->u.target = pos->second; + CStringToAtom::iterator post = _llvmAtoms.find(targetName); + if ( post != _llvmAtoms.end() ) { + const ld::Atom* t = post->second; + if (log) fprintf(stderr, " updating direct reference to %p to be ref to %p: %s\n", fit->u.target, t, targetName); + fit->u.target = t; } else { // Don't unbind follow-on reference into by-name reference