X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/fb9a160cc46cd88a41dda5ab61012c5572e56f33..7f09b9353af9897bf18933788d6a59c152c29edd:/src/ld/passes/bitcode_bundle.cpp diff --git a/src/ld/passes/bitcode_bundle.cpp b/src/ld/passes/bitcode_bundle.cpp index 2ad5a3e..527869a 100644 --- a/src/ld/passes/bitcode_bundle.cpp +++ b/src/ld/passes/bitcode_bundle.cpp @@ -268,6 +268,9 @@ BitcodeTempFile::~BitcodeTempFile() BitcodeObfuscator::BitcodeObfuscator() { +#if LTO_API_VERSION < 11 + throwf("compile-time libLTO (%d) didn't support -bitcode_hide_symbols", LTO_API_VERSION); +#else // check if apple internal libLTO is used if ( ::lto_get_version() == NULL ) throwf("libLTO is not loaded"); @@ -282,11 +285,13 @@ BitcodeObfuscator::BitcodeObfuscator() _lto_get_asm_symbol_num == NULL || _lto_get_asm_symbol_name == NULL || ::lto_api_version() < 14 ) throwf("loaded libLTO doesn't support -bitcode_hide_symbols: %s", ::lto_get_version()); _obfuscator = ::lto_codegen_create_in_local_context(); -#if LTO_API_VERSION >= 14 + #if LTO_API_VERSION >= 14 lto_codegen_set_should_internalize(_obfuscator, false); + #endif #endif } + BitcodeObfuscator::~BitcodeObfuscator() { ::lto_codegen_dispose(_obfuscator); @@ -302,7 +307,8 @@ void BitcodeObfuscator::bitcodeHideSymbols(ld::Bitcode* bc, const char* filePath #if LTO_API_VERSION >= 13 && LTO_APPLE_INTERNAL lto_module_t module = ::lto_module_create_in_codegen_context(bc->getContent(), bc->getSize(), filePath, _obfuscator); if ( module == NULL ) - throwf("object contains invalid bitcode: %s", filePath); + throwf("could not reparse object file %s in bitcode bundle: '%s', using libLTO version '%s'", + filePath, ::lto_get_error_message(), ::lto_get_version()); ::lto_codegen_set_module(_obfuscator, module); (*_lto_hide_symbols)(_obfuscator); #if LTO_API_VERSION >= 15 @@ -397,6 +403,8 @@ void BundleHandler::init() // read the xar file _xar = xar_open(oldXARPath.c_str(), READ); + if ( _xar == NULL ) + throwf("malformed bundle format"); // Init the vector of handler xar_iter_t iter = xar_iter_new(); @@ -431,8 +439,10 @@ void BundleHandler::copyXARProp(xar_file_t src, xar_file_t dst) const char* key = xar_prop_first(src, p); for (int x = 0; x < i; x++) key = xar_prop_next(p); - if ( !key ) + if ( !key ) { + xar_iter_free(p); break; + } const char* val = NULL; xar_prop_get(src, key, &val); if ( // Info from bitcode files @@ -471,7 +481,14 @@ void BitcodeHandler::populateMustPreserveSymbols(BitcodeObfuscator* obfuscator) initFile(); // init LTOModule and add asm labels +#if LTO_API_VERSION < 11 lto_module_t module = lto_module_create_from_memory(_file_buffer, _file_size); +#else + lto_module_t module = lto_module_create_in_local_context(_file_buffer, _file_size, "bitcode bundle temp file"); +#endif + if ( module == NULL ) + throwf("could not reparse object file in bitcode bundle: '%s', using libLTO version '%s'", + ::lto_get_error_message(), ::lto_get_version()); obfuscator->addAsmSymbolsToMustPreserve(module); lto_module_dispose(module); } @@ -617,14 +634,16 @@ void BitcodeBundle::doPass() // 3. symbols must not be stripped // 4. all the globals if the globals are dead_strip root (ex. dylibs) // 5. there is an exported symbol list suggests the symbol should be exported - // 6. the special symbols supplied by linker + // 6. weak external symbols (not auto-hide) + // 7. the special symbols supplied by linker for ( auto § : _state.sections ) { for ( auto &atom : sect->atoms ) { if ( atom == _state.entryPoint || atom->definition() == ld::Atom::definitionProxy || atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip || ( _options.allGlobalsAreDeadStripRoots() && atom->scope() == ld::Atom::scopeGlobal ) || - ( _options.hasExportRestrictList() && _options.shouldExport(atom->name()) ) ) + ( _options.hasExportRestrictList() && _options.shouldExport(atom->name()) ) || + ( atom->combine() == ld::Atom::combineByName && atom->scope() == ld::Atom::scopeGlobal && !atom->autoHide() ) ) obfuscator->addMustPreserveSymbols(atom->name()); } } @@ -638,10 +657,17 @@ void BitcodeBundle::doPass() bh->populateMustPreserveSymbols(obfuscator); handlerMap.emplace(std::string(f->path()), bh); } else if ( ld::LLVMBitcode* bitcode = dynamic_cast(f->getBitcode()) ) { - BitcodeHandler* bitcodeHandler = new BitcodeHandler((char*)bitcode->getContent(), bitcode->getSize()); - bitcodeHandler->populateMustPreserveSymbols(obfuscator); + BitcodeHandler bitcodeHandler((char*)bitcode->getContent(), bitcode->getSize()); + bitcodeHandler.populateMustPreserveSymbols(obfuscator); } } + // add must preserve symbols from lto input. + for ( auto &f : _state.ltoBitcodePath ) { + BitcodeTempFile ltoTemp(f.c_str(), false); // Keep the temp file because it needs to be read in later in the pass. + BitcodeHandler bitcodeHandler((char*)ltoTemp.getContent(), ltoTemp.getSize()); + bitcodeHandler.populateMustPreserveSymbols(obfuscator); + } + // special symbols supplied by linker obfuscator->addMustPreserveSymbols("___dso_handle"); obfuscator->addMustPreserveSymbols("__mh_execute_header"); @@ -650,6 +676,11 @@ void BitcodeBundle::doPass() obfuscator->addMustPreserveSymbols("__mh_dylinker_header"); obfuscator->addMustPreserveSymbols("__mh_object_header"); obfuscator->addMustPreserveSymbols("__mh_preload_header"); + + // add all the Proxy Atom linker ever created and all the undefs that are possibily dead-stripped. + for (auto sym : _state.allUndefProxies) + obfuscator->addMustPreserveSymbols(sym); + _state.allUndefProxies.clear(); } // Open XAR output @@ -738,26 +769,30 @@ void BitcodeBundle::doPass() } } - // Write merged LTO bitcode + // Write merged LTO bitcode files if ( !_state.ltoBitcodePath.empty() ) { - xar_file_t ltoFile = NULL; - BitcodeTempFile* ltoTemp = new BitcodeTempFile(_state.ltoBitcodePath.c_str(), !_options.saveTempFiles()); - if ( _options.hideSymbols() ) { + int count = 0; + for (auto &path : _state.ltoBitcodePath) { + std::string xar_name = "lto.o." + std::to_string(count++); + xar_file_t ltoFile = NULL; + BitcodeTempFile* ltoTemp = new BitcodeTempFile(path.c_str(), !_options.saveTempFiles()); + if ( _options.hideSymbols() ) { ld::Bitcode ltoBitcode(ltoTemp->getContent(), ltoTemp->getSize()); char ltoTempFile[PATH_MAX]; sprintf(ltoTempFile, "%s/lto.bc", tempdir); - obfuscator->bitcodeHideSymbols(<oBitcode, _state.ltoBitcodePath.c_str(), ltoTempFile); + obfuscator->bitcodeHideSymbols(<oBitcode, path.c_str(), ltoTempFile); BitcodeTempFile* ltoStrip = new BitcodeTempFile(ltoTempFile, !_options.saveTempFiles()); - ltoFile = xar_add_frombuffer(x, NULL, "lto.o", (char*)ltoStrip->getContent(), ltoStrip->getSize()); + ltoFile = xar_add_frombuffer(x, NULL, xar_name.c_str(), (char*)ltoStrip->getContent(), ltoStrip->getSize()); delete ltoStrip; - } else { - ltoFile = xar_add_frombuffer(x, NULL, "lto.o", (char*)ltoTemp->getContent(), ltoTemp->getSize()); + } else { + ltoFile = xar_add_frombuffer(x, NULL, xar_name.c_str(), (char*)ltoTemp->getContent(), ltoTemp->getSize()); + } + if ( ltoFile == NULL ) + throwf("could not add lto file %s to bitcode bundle", path.c_str()); + if ( xar_prop_set(ltoFile, "file-type", "LTO") != 0 ) + throwf("could not set bitcode property for %s in bitcode bundle", path.c_str()); + delete ltoTemp; } - if ( ltoFile == NULL ) - throwf("could not add lto file %s to bitcode bundle", _state.ltoBitcodePath.c_str()); - if ( xar_prop_set(ltoFile, "file-type", "LTO") != 0 ) - throwf("could not set bitcode property for %s in bitcode bundle", _state.ltoBitcodePath.c_str()); - delete ltoTemp; } // Common LinkOptions