bool DarwinLdDriver::linkMachO(int argc, const char *argv[], raw_ostream &diagnostics) { MachOLinkingContext ctx; if (!parse(argc, argv, ctx, diagnostics)) return false; if (ctx.doNothing()) return true; return link(ctx, diagnostics); }
bool DarwinLdDriver::linkMachO(int argc, const char *argv[], raw_ostream &diagnostics) { MachOLinkingContext ctx; if (!parse(argc, argv, ctx, diagnostics)) return false; if (ctx.doNothing()) return true; // Register possible input file parsers. ctx.registry().addSupportMachOObjects(ctx.archName()); ctx.registry().addSupportArchives(ctx.logInputFiles()); ctx.registry().addSupportNativeObjects(); ctx.registry().addSupportYamlFiles(); return link(ctx, diagnostics); }
void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx) { assert(ctx.needsGOTPass()); pm.add(std::unique_ptr<Pass>(new GOTPass(ctx))); }
void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx) { assert(ctx.needsGOTPass()); pm.add(llvm::make_unique<GOTPass>(ctx)); }
void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx) { assert(ctx.needsCompactUnwindPass()); pm.add(llvm::make_unique<CompactUnwindPass>(ctx)); }
bool DarwinLdDriver::parse(int argc, const char *argv[], MachOLinkingContext &ctx, raw_ostream &diagnostics) { // Parse command line options using DarwinLdOptions.td std::unique_ptr<llvm::opt::InputArgList> parsedArgs; DarwinLdOptTable table; unsigned missingIndex; unsigned missingCount; bool globalWholeArchive = false; parsedArgs.reset( table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount)); if (missingCount) { diagnostics << "error: missing arg value for '" << parsedArgs->getArgString(missingIndex) << "' expected " << missingCount << " argument(s).\n"; return false; } for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN), ie = parsedArgs->filtered_end(); it != ie; ++it) { diagnostics << "warning: ignoring unknown argument: " << (*it)->getAsString(*parsedArgs) << "\n"; } // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static ) if ( llvm::opt::Arg *kind = parsedArgs->getLastArg(OPT_dylib, OPT_relocatable, OPT_bundle, OPT_static, OPT_preload)) { switch (kind->getOption().getID()) { case OPT_dylib: ctx.setOutputFileType(llvm::MachO::MH_DYLIB); ctx.setGlobalsAreDeadStripRoots(true); break; case OPT_relocatable: ctx.setPrintRemainingUndefines(false); ctx.setAllowRemainingUndefines(true); ctx.setOutputFileType(llvm::MachO::MH_OBJECT); break; case OPT_bundle: ctx.setOutputFileType(llvm::MachO::MH_BUNDLE); break; case OPT_static: ctx.setOutputFileType(llvm::MachO::MH_EXECUTE); break; case OPT_preload: ctx.setOutputFileType(llvm::MachO::MH_PRELOAD); break; } } // Handle -e xxx if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry)) ctx.setEntrySymbolName(entry->getValue()); // Handle -o xxx if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_output)) ctx.setOutputPath(outpath->getValue()); // Handle -dead_strip if (parsedArgs->getLastArg(OPT_dead_strip)) ctx.setDeadStripping(true); // Handle -all_load if (parsedArgs->getLastArg(OPT_all_load)) globalWholeArchive = true; // Handle -install_name if (llvm::opt::Arg *installName = parsedArgs->getLastArg(OPT_install_name)) ctx.setInstallName(installName->getValue()); // Handle -mark_dead_strippable_dylib if (parsedArgs->getLastArg(OPT_mark_dead_strippable_dylib)) ctx.setDeadStrippableDylib(true); // Handle -compatibility_version and -current_version if (llvm::opt::Arg *vers = parsedArgs->getLastArg(OPT_compatibility_version)) { if (ctx.outputFileType() != llvm::MachO::MH_DYLIB) { diagnostics << "error: -compatibility_version can only be used with -dylib\n"; return false; } uint32_t parsedVers; if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) { diagnostics << "error: -compatibility_version value is malformed\n"; return false; } ctx.setCompatibilityVersion(parsedVers); } if (llvm::opt::Arg *vers = parsedArgs->getLastArg(OPT_current_version)) { if (ctx.outputFileType() != llvm::MachO::MH_DYLIB) { diagnostics << "-current_version can only be used with -dylib\n"; return false; } uint32_t parsedVers; if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) { diagnostics << "error: -current_version value is malformed\n"; return false; } ctx.setCurrentVersion(parsedVers); } // Handle -bundle_loader if (llvm::opt::Arg *loader = parsedArgs->getLastArg(OPT_bundle_loader)) ctx.setBundleLoader(loader->getValue()); // Handle -arch xxx if (llvm::opt::Arg *archStr = parsedArgs->getLastArg(OPT_arch)) { ctx.setArch(MachOLinkingContext::archFromName(archStr->getValue())); if (ctx.arch() == MachOLinkingContext::arch_unknown) { diagnostics << "error: unknown arch named '" << archStr->getValue() << "'\n"; return false; } } // Handle -macosx_version_min or -ios_version_min if (llvm::opt::Arg *minOS = parsedArgs->getLastArg( OPT_macosx_version_min, OPT_ios_version_min, OPT_ios_simulator_version_min)) { switch (minOS->getOption().getID()) { case OPT_macosx_version_min: if (ctx.setOS(MachOLinkingContext::OS::macOSX, minOS->getValue())) { diagnostics << "error: malformed macosx_version_min value\n"; return false; } break; case OPT_ios_version_min: if (ctx.setOS(MachOLinkingContext::OS::iOS, minOS->getValue())) { diagnostics << "error: malformed ios_version_min value\n"; return false; } break; case OPT_ios_simulator_version_min: if (ctx.setOS(MachOLinkingContext::OS::iOS_simulator, minOS->getValue())) { diagnostics << "error: malformed ios_simulator_version_min value\n"; return false; } break; } } else { // No min-os version on command line, check environment variables } // Handle -help if (parsedArgs->getLastArg(OPT_help)) { table.PrintHelp(llvm::outs(), argv[0], "LLVM Darwin Linker", false); // If only -help on command line, don't try to do any linking if (argc == 2) { ctx.setDoNothing(true); return true; } } // Handle -mllvm for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm), ie = parsedArgs->filtered_end(); it != ie; ++it) { ctx.appendLLVMOption((*it)->getValue()); } std::unique_ptr<InputGraph> inputGraph(new InputGraph()); // Handle input files for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT), ie = parsedArgs->filtered_end(); it != ie; ++it) { inputGraph->addInputElement(std::unique_ptr<InputElement>( new MachOFileNode(ctx, (*it)->getValue(), globalWholeArchive))); } if (!inputGraph->size()) { diagnostics << "No input files\n"; return false; } ctx.setInputGraph(std::move(inputGraph)); // Validate the combination of options used. return ctx.validate(diagnostics); }