// LoadObject - Read in and parse the bitcode file named by FN and return the // module it contains (wrapped in an auto_ptr), or auto_ptr<Module>() and set // Error if an error occurs. std::auto_ptr<Module> Linker::LoadObject(const sys::Path &FN) { std::string ParseErrorMessage; Module *Result = 0; const std::string &FNS = FN.toString(); std::auto_ptr<MemoryBuffer> Buffer(MemoryBuffer::getFileOrSTDIN(FNS.c_str())); if (Buffer.get()) Result = ParseBitcodeFile(Buffer.get(), &ParseErrorMessage); else ParseErrorMessage = "Error reading file '" + FNS + "'"; if (Result) return std::auto_ptr<Module>(Result); Error = "Bitcode file '" + FN.toString() + "' could not be loaded"; if (ParseErrorMessage.size()) Error += ": " + ParseErrorMessage; return std::auto_ptr<Module>(); }
/// LinkInFile - opens a bitcode file and links in all objects which /// provide symbols that are currently undefined. /// /// Inputs: /// File - The pathname of the bitcode file. /// /// Outputs: /// ErrorMessage - A C++ string detailing what error occurred, if any. /// /// Return Value: /// TRUE - An error occurred. /// FALSE - No errors. /// bool Linker::LinkInFile(const sys::Path &File, bool &is_native) { is_native = false; // Check for a file of name "-", which means "read standard input" if (File.toString() == "-") { std::auto_ptr<Module> M; if (MemoryBuffer *Buffer = MemoryBuffer::getSTDIN()) { M.reset(ParseBitcodeFile(Buffer, Context, &Error)); delete Buffer; if (M.get()) if (!LinkInModule(M.get(), &Error)) return false; } else Error = "standard input is empty"; return error("Cannot link stdin: " + Error); } // Make sure we can at least read the file if (!File.canRead()) return error("Cannot find linker input '" + File.toString() + "'"); // If its an archive, try to link it in std::string Magic; File.getMagicNumber(Magic, 64); switch (sys::IdentifyFileType(Magic.c_str(), 64)) { default: llvm_unreachable("Bad file type identification"); case sys::Unknown_FileType: return warning("Ignoring file '" + File.toString() + "' because does not contain bitcode."); case sys::Archive_FileType: // A user may specify an ar archive without -l, perhaps because it // is not installed as a library. Detect that and link the archive. verbose("Linking archive file '" + File.toString() + "'"); if (LinkInArchive(File, is_native)) return true; break; case sys::Bitcode_FileType: { verbose("Linking bitcode file '" + File.toString() + "'"); std::auto_ptr<Module> M(LoadObject(File)); if (M.get() == 0) return error("Cannot load file '" + File.toString() + "': " + Error); if (LinkInModule(M.get(), &Error)) return error("Cannot link file '" + File.toString() + "': " + Error); verbose("Linked in file '" + File.toString() + "'"); break; } case sys::ELF_Relocatable_FileType: case sys::ELF_SharedObject_FileType: case sys::Mach_O_Object_FileType: case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: case sys::COFF_FileType: is_native = true; break; } return false; }
/// LinkInArchive - opens an archive library and link in all objects which /// provide symbols that are currently undefined. /// /// Inputs: /// Filename - The pathname of the archive. /// /// Return Value: /// TRUE - An error occurred. /// FALSE - No errors. bool Linker::LinkInArchive(const sys::Path &Filename, bool &is_native) { // Make sure this is an archive file we're dealing with if (!Filename.isArchive()) return error("File '" + Filename.toString() + "' is not an archive."); // Open the archive file verbose("Linking archive file '" + Filename.toString() + "'"); // Find all of the symbols currently undefined in the bitcode program. // If all the symbols are defined, the program is complete, and there is // no reason to link in any archive files. std::set<std::string> UndefinedSymbols; GetAllUndefinedSymbols(Composite, UndefinedSymbols); if (UndefinedSymbols.empty()) { verbose("No symbols undefined, skipping library '" + Filename.toString() + "'"); return false; // No need to link anything in! } std::string ErrMsg; std::auto_ptr<Archive> AutoArch ( Archive::OpenAndLoadSymbols(Filename, Context, &ErrMsg)); Archive* arch = AutoArch.get(); if (!arch) return error("Cannot read archive '" + Filename.toString() + "': " + ErrMsg); if (!arch->isBitcodeArchive()) { is_native = true; return false; } is_native = false; // Save a set of symbols that are not defined by the archive. Since we're // entering a loop, there's no point searching for these multiple times. This // variable is used to "set_subtract" from the set of undefined symbols. std::set<std::string> NotDefinedByArchive; // Save the current set of undefined symbols, because we may have to make // multiple passes over the archive: std::set<std::string> CurrentlyUndefinedSymbols; do { CurrentlyUndefinedSymbols = UndefinedSymbols; // Find the modules we need to link into the target module std::set<ModuleProvider*> Modules; if (!arch->findModulesDefiningSymbols(UndefinedSymbols, Modules, &ErrMsg)) return error("Cannot find symbols in '" + Filename.toString() + "': " + ErrMsg); // If we didn't find any more modules to link this time, we are done // searching this archive. if (Modules.empty()) break; // Any symbols remaining in UndefinedSymbols after // findModulesDefiningSymbols are ones that the archive does not define. So // we add them to the NotDefinedByArchive variable now. NotDefinedByArchive.insert(UndefinedSymbols.begin(), UndefinedSymbols.end()); // Loop over all the ModuleProviders that we got back from the archive for (std::set<ModuleProvider*>::iterator I=Modules.begin(), E=Modules.end(); I != E; ++I) { // Get the module we must link in. std::string moduleErrorMsg; std::auto_ptr<Module> AutoModule((*I)->releaseModule( &moduleErrorMsg )); if (!moduleErrorMsg.empty()) return error("Could not load a module: " + moduleErrorMsg); Module* aModule = AutoModule.get(); if (aModule != NULL) { verbose(" Linking in module: " + aModule->getModuleIdentifier()); // Link it in if (LinkInModule(aModule, &moduleErrorMsg)) { return error("Cannot link in module '" + aModule->getModuleIdentifier() + "': " + moduleErrorMsg); } } } // Get the undefined symbols from the aggregate module. This recomputes the // symbols we still need after the new modules have been linked in. GetAllUndefinedSymbols(Composite, UndefinedSymbols); // At this point we have two sets of undefined symbols: UndefinedSymbols // which holds the undefined symbols from all the modules, and // NotDefinedByArchive which holds symbols we know the archive doesn't // define. There's no point searching for symbols that we won't find in the // archive so we subtract these sets. set_subtract(UndefinedSymbols, NotDefinedByArchive); // If there's no symbols left, no point in continuing to search the // archive. if (UndefinedSymbols.empty()) break; } while (CurrentlyUndefinedSymbols != UndefinedSymbols); return false; }