X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/a645023da60d22e86be13f7b4d97adeff8bc6665..b1f7435d66a93f03b77932b3a9ad8a83ce5e1ebc:/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 6221c90..c9c4ed0 100644 --- a/src/ld/parsers/lto_file.cpp +++ b/src/ld/parsers/lto_file.cpp @@ -41,6 +41,9 @@ #include "macho_relocatable_file.h" #include "lto_file.h" +// #defines are a work around for +#define __STDC_LIMIT_MACROS 1 +#define __STDC_CONSTANT_MACROS 1 #include "llvm-c/lto.h" @@ -60,8 +63,6 @@ public: InternalAtom(class File& f); // overrides of ld::Atom virtual ld::File* file() const { return &_file; } - virtual bool translationUnitSource(const char** dir, const char** nm) const - { return false; } virtual const char* name() const { return "import-atom"; } virtual uint64_t size() const { return 0; } virtual uint64_t objectAddress() const { return 0; } @@ -87,8 +88,8 @@ private: class File : public ld::relocatable::File { public: - File(const char* path, time_t mTime, const uint8_t* content, - uint32_t contentLength, uint32_t ordinal, cpu_type_t arch); + File(const char* path, time_t mTime, ld::File::Ordinal ordinal, + const uint8_t* content, uint32_t contentLength, cpu_type_t arch); virtual ~File(); // overrides of ld::File @@ -98,7 +99,6 @@ public: virtual uint32_t cpuSubType() const { return _cpuSubType; } // overrides of ld::relocatable::File - virtual bool objcReplacementClasses() const { return false; } virtual DebugInfoKind debugInfo() const { return _debugInfo; } virtual const char* debugInfoPath() const { return _debugInfoPath; } virtual time_t debugInfoModificationTime() const @@ -144,12 +144,12 @@ class Atom : public ld::Atom { public: Atom(File& f, const char* name, ld::Atom::Scope s, - ld::Atom::Definition d, ld::Atom::Combine c, ld::Atom::Alignment a); + ld::Atom::Definition d, ld::Atom::Combine c, ld::Atom::Alignment a, bool ah); // overrides of ld::Atom virtual ld::File* file() const { return &_file; } - virtual bool translationUnitSource(const char** dir, const char** nm) const - { return (_compiledAtom ? _compiledAtom->translationUnitSource(dir, nm) : false); } + virtual const char* translationUnitSource() const + { return (_compiledAtom ? _compiledAtom->translationUnitSource() : NULL); } virtual const char* name() const { return _name; } virtual uint64_t size() const { return (_compiledAtom ? _compiledAtom->size() : 0); } virtual uint64_t objectAddress() const { return (_compiledAtom ? _compiledAtom->objectAddress() : 0); } @@ -196,11 +196,10 @@ public: static bool validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture, cpu_subtype_t subarch); static const char* fileKind(const uint8_t* fileContent, uint64_t fileLength); static File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, - time_t modTime, uint32_t ordinal, cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles); + time_t modTime, ld::File::Ordinal ordinal, cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles); static bool libLTOisLoaded() { return (::lto_get_version() != NULL); } static bool optimize( const std::vector& allAtoms, ld::Internal& state, - uint32_t nextInputOrdinal, const OptimizeOptions& options, ld::File::AtomHandler& handler, std::vector& newAtoms, @@ -210,7 +209,7 @@ public: private: static const char* tripletPrefixForArch(cpu_type_t arch); - static ld::relocatable::File* parseMachOFile(const uint8_t* p, size_t len, uint32_t nextInputOrdinal, const OptimizeOptions& options); + static ld::relocatable::File* parseMachOFile(const uint8_t* p, size_t len, const OptimizeOptions& options); class CStringEquals { @@ -243,21 +242,17 @@ std::vector Parser::_s_files; bool Parser::validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture, cpu_subtype_t subarch) { - switch (architecture) { - case CPU_TYPE_I386: - return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, "i386-"); - case CPU_TYPE_X86_64: - return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, "x86_64-"); - case CPU_TYPE_ARM: - switch ( subarch ) { - case CPU_SUBTYPE_ARM_V6: - return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, "armv6-"); - case CPU_SUBTYPE_ARM_V7: - return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, "thumbv7-"); + for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) { + if ( (architecture == t->cpuType) && (!(t->isSubType) || (subarch == t->cpuSubType)) ) { + bool result = ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, t->llvmTriplePrefix); + if ( !result ) { + // LTO only supports thumbv7 not armv7 + if ( t->llvmTriplePrefixAlt[0] != '\0' ) { + result = ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, t->llvmTriplePrefixAlt); + } } - break; - case CPU_TYPE_POWERPC: - return ::lto_module_is_object_file_in_memory_for_target(fileContent, fileLength, "powerpc-"); + return result; + } } return false; } @@ -265,30 +260,27 @@ bool Parser::validFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type const char* Parser::fileKind(const uint8_t* p, uint64_t fileLength) { if ( (p[0] == 0xDE) && (p[1] == 0xC0) && (p[2] == 0x17) && (p[3] == 0x0B) ) { - uint32_t arch = LittleEndian::get32(*((uint32_t*)(&p[16]))); - switch (arch) { - case CPU_TYPE_POWERPC: - return "ppc"; - case CPU_TYPE_I386: - return "i386"; - case CPU_TYPE_X86_64: - return "x86_64"; - case CPU_TYPE_ARM: - if ( ::lto_module_is_object_file_in_memory_for_target(p, fileLength, "armv6-") ) - return "armv6"; - if ( ::lto_module_is_object_file_in_memory_for_target(p, fileLength, "thumbv7-") ) - return "armv7"; - return "arm"; + cpu_type_t arch = LittleEndian::get32(*((uint32_t*)(&p[16]))); + for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) { + if ( arch == t->cpuType ) { + if ( t->isSubType ) { + if ( ::lto_module_is_object_file_in_memory_for_target(p, fileLength, t->llvmTriplePrefix) ) + return t->archName; + } + else { + return t->archName; + } + } } return "unknown bitcode architecture"; } return NULL; } -File* Parser::parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, - uint32_t ordinal, cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles) +File* Parser::parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime, ld::File::Ordinal ordinal, + cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles) { - File* f = new File(path, modTime, fileContent, fileLength, ordinal, architecture); + File* f = new File(path, modTime, ordinal, fileContent, fileLength, architecture); _s_files.push_back(f); if ( logAllFiles ) printf("%s\n", path); @@ -296,7 +288,7 @@ File* Parser::parse(const uint8_t* fileContent, uint64_t fileLength, const char* } -ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, uint32_t nextInputOrdinal, const OptimizeOptions& options) +ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, const OptimizeOptions& options) { mach_o::relocatable::ParserOptions objOpts; objOpts.architecture = options.arch; @@ -315,7 +307,7 @@ ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, uint modTime = statBuffer.st_mtime; } - ld::relocatable::File* result = mach_o::relocatable::parse(p, len, path, modTime, nextInputOrdinal, objOpts); + ld::relocatable::File* result = mach_o::relocatable::parse(p, len, path, modTime, ld::File::Ordinal::LTOOrdinal(), objOpts); if ( result != NULL ) return result; throw "LLVM LTO, file is not of required architecture"; @@ -323,8 +315,8 @@ ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, uint -File::File(const char* pth, time_t mTime, const uint8_t* content, uint32_t contentLength, uint32_t ord, cpu_type_t arch) - : ld::relocatable::File(pth,mTime,ord), _architecture(arch), _internalAtom(*this), +File::File(const char* pth, time_t mTime, ld::File::Ordinal ordinal, const uint8_t* content, uint32_t contentLength, cpu_type_t arch) + : ld::relocatable::File(pth,mTime,ordinal), _architecture(arch), _internalAtom(*this), _atomArray(NULL), _atomArrayCount(0), _module(NULL), _debugInfoPath(pth), _section("__TEXT_", "__tmp_lto", ld::Section::typeTempLTO), _fixupToInternal(0, ld::Fixup::k1of1, ld::Fixup::kindNone, &_internalAtom), @@ -376,6 +368,7 @@ File::File(const char* pth, time_t mTime, const uint8_t* content, uint32_t conte // make LLVM atoms for definitions and a reference for undefines if ( def != ld::Atom::definitionProxy ) { ld::Atom::Scope scope; + bool autohide = false; switch ( attr & LTO_SYMBOL_SCOPE_MASK) { case LTO_SYMBOL_SCOPE_INTERNAL: scope = ld::Atom::scopeTranslationUnit; @@ -386,6 +379,12 @@ File::File(const char* pth, time_t mTime, const uint8_t* content, uint32_t conte case LTO_SYMBOL_SCOPE_DEFAULT: scope = ld::Atom::scopeGlobal; break; +#if LTO_API_VERSION >= 4 + case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN: + scope = ld::Atom::scopeGlobal; + autohide = true; + break; +#endif default: throwf("unknown scope for symbol %s in bitcode file %s", name, pth); } @@ -394,8 +393,8 @@ File::File(const char* pth, time_t mTime, const uint8_t* content, uint32_t conte continue; uint8_t alignment = (attr & LTO_SYMBOL_ALIGNMENT_MASK); // make Atom using placement new operator - new (&_atomArray[_atomArrayCount++]) Atom(*this, name, scope, def, combine, alignment); - if ( scope == ld::Atom::scopeLinkageUnit ) + new (&_atomArray[_atomArrayCount++]) Atom(*this, name, scope, def, combine, alignment, autohide); + if ( scope != ld::Atom::scopeTranslationUnit ) _internalAtom.addReference(name); if ( log ) fprintf(stderr, "\t0x%08X %s\n", attr, name); } @@ -429,11 +428,14 @@ InternalAtom::InternalAtom(File& f) { } -Atom::Atom(File& f, const char* nm, ld::Atom::Scope s, ld::Atom::Definition d, ld::Atom::Combine c, ld::Atom::Alignment a) +Atom::Atom(File& f, const char* nm, ld::Atom::Scope s, ld::Atom::Definition d, ld::Atom::Combine c, + 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) { + if ( ah ) + this->setAutoHide(); } void Atom::setCompiledAtom(const ld::Atom& atom) @@ -451,7 +453,6 @@ void Atom::setCompiledAtom(const ld::Atom& atom) bool Parser::optimize( const std::vector& allAtoms, ld::Internal& state, - uint32_t nextInputOrdinal, const OptimizeOptions& options, ld::File::AtomHandler& handler, std::vector& newAtoms, @@ -570,7 +571,7 @@ bool Parser::optimize( const std::vector& allAtoms, // 1 - atom scope is global (and not linkage unit). // 2 - included in nonLLVMRefs set. // If a symbol is not listed in exportList then LTO is free to optimize it away. - if ( (atom->scope() == ld::Atom::scopeGlobal) ) { + if ( (atom->scope() == ld::Atom::scopeGlobal) && options.preserveAllGlobals ) { if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because global symbol\n", name); ::lto_codegen_add_must_preserve_symbol(generator, name); } @@ -673,7 +674,7 @@ bool Parser::optimize( const std::vector& allAtoms, } // parse generated mach-o file into a MachOReader - ld::relocatable::File* machoFile = parseMachOFile(machOFile, machOFileLen, nextInputOrdinal, options); + ld::relocatable::File* machoFile = parseMachOFile(machOFile, machOFileLen, options); // sync generated mach-o atoms with existing atoms ld knows about if ( logAtomsBeforeSync ) { @@ -799,12 +800,20 @@ void Parser::AtomSyncer::doAtom(const ld::Atom& machoAtom) } +class Mutex { + static pthread_mutex_t lto_lock; +public: + Mutex() { pthread_mutex_lock(<o_lock); } + ~Mutex() { pthread_mutex_unlock(<o_lock); } +}; +pthread_mutex_t Mutex::lto_lock = PTHREAD_MUTEX_INITIALIZER; // // Used by archive reader to see if member is an llvm bitcode file // bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t architecture, cpu_subtype_t subarch) { + Mutex lock; return Parser::validFile(fileContent, fileLength, architecture, subarch); } @@ -813,9 +822,10 @@ bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, cpu_type_t ar // main function used by linker to instantiate ld::Files // ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength, - const char* path, time_t modTime, uint32_t ordinal, + const char* path, time_t modTime, ld::File::Ordinal ordinal, cpu_type_t architecture, cpu_subtype_t subarch, bool logAllFiles) { + Mutex lock; if ( Parser::validFile(fileContent, fileLength, architecture, subarch) ) return Parser::parse(fileContent, fileLength, path, modTime, ordinal, architecture, subarch, logAllFiles); else @@ -827,6 +837,7 @@ ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength, // const char* version() { + Mutex lock; return ::lto_get_version(); } @@ -836,6 +847,7 @@ const char* version() // bool libLTOisLoaded() { + Mutex lock; return (::lto_get_version() != NULL); } @@ -844,6 +856,7 @@ bool libLTOisLoaded() // const char* archName(const uint8_t* fileContent, uint64_t fileLength) { + Mutex lock; return Parser::fileKind(fileContent, fileLength); } @@ -852,13 +865,13 @@ const char* archName(const uint8_t* fileContent, uint64_t fileLength) // bool optimize( const std::vector& allAtoms, ld::Internal& state, - uint32_t nextInputOrdinal, const OptimizeOptions& options, ld::File::AtomHandler& handler, std::vector& newAtoms, std::vector& additionalUndefines) { - return Parser::optimize(allAtoms, state, nextInputOrdinal, options, handler, newAtoms, additionalUndefines); + Mutex lock; + return Parser::optimize(allAtoms, state, options, handler, newAtoms, additionalUndefines); }