int llvm::libDriverMain(llvm::ArrayRef<const char*> ArgsArr) { SmallVector<const char *, 20> NewArgs(ArgsArr.begin(), ArgsArr.end()); BumpPtrAllocator Alloc; BumpPtrStringSaver Saver(Alloc); cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgs); ArgsArr = NewArgs; LibOptTable Table; unsigned MissingIndex; unsigned MissingCount; llvm::opt::InputArgList Args = Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount); if (MissingCount) { llvm::errs() << "missing arg value for \"" << Args.getArgString(MissingIndex) << "\", expected " << MissingCount << (MissingCount == 1 ? " argument.\n" : " arguments.\n"); return 1; } for (auto *Arg : Args.filtered(OPT_UNKNOWN)) llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n"; if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) { llvm::errs() << "no input files.\n"; return 1; } std::vector<StringRef> SearchPaths = getSearchPaths(&Args, Saver); std::vector<llvm::NewArchiveIterator> Members; for (auto *Arg : Args.filtered(OPT_INPUT)) { Optional<std::string> Path = findInputFile(Arg->getValue(), SearchPaths); if (!Path.hasValue()) { llvm::errs() << Arg->getValue() << ": no such file or directory\n"; return 1; } Members.emplace_back(Saver.save(*Path), llvm::sys::path::filename(Arg->getValue())); } std::pair<StringRef, std::error_code> Result = llvm::writeArchive(getOutputPath(&Args, Members[0]), Members, /*WriteSymtab=*/true, object::Archive::K_GNU, /*Deterministic*/ true, /*Thin*/ false); if (Result.second) { if (Result.first.empty()) Result.first = ArgsArr[0]; llvm::errs() << Result.first << ": " << Result.second.message() << "\n"; return 1; } return 0; }
bool CoreDriver::parse(llvm::ArrayRef<const char *> args, CoreLinkingContext &ctx, raw_ostream &diagnostics) { // Parse command line options using CoreOptions.td CoreOptTable table; unsigned missingIndex; unsigned missingCount; llvm::opt::InputArgList parsedArgs = table.ParseArgs(args.slice(1), missingIndex, missingCount); if (missingCount) { diagnostics << "error: missing arg value for '" << parsedArgs.getArgString(missingIndex) << "' expected " << missingCount << " argument(s).\n"; return false; } // Set default options ctx.setOutputPath("-"); ctx.setDeadStripping(false); ctx.setGlobalsAreDeadStripRoots(false); ctx.setPrintRemainingUndefines(false); ctx.setAllowRemainingUndefines(true); ctx.setSearchArchivesToOverrideTentativeDefinitions(false); // Process all the arguments and create input files. for (auto inputArg : parsedArgs) { switch (inputArg->getOption().getID()) { case OPT_mllvm: ctx.appendLLVMOption(inputArg->getValue()); break; case OPT_entry: ctx.setEntrySymbolName(inputArg->getValue()); break; case OPT_output: ctx.setOutputPath(inputArg->getValue()); break; case OPT_dead_strip: ctx.setDeadStripping(true); break; case OPT_keep_globals: ctx.setGlobalsAreDeadStripRoots(true); break; case OPT_undefines_are_errors: ctx.setPrintRemainingUndefines(true); ctx.setAllowRemainingUndefines(false); break; case OPT_commons_search_archives: ctx.setSearchArchivesToOverrideTentativeDefinitions(true); break; case OPT_add_pass: ctx.addPassNamed(inputArg->getValue()); break; case OPT_INPUT: { std::vector<std::unique_ptr<File>> files = loadFile(ctx, inputArg->getValue(), false); for (std::unique_ptr<File> &file : files) ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file))); break; } default: break; } } if (ctx.getNodes().empty()) { diagnostics << "No input files\n"; return false; } // Validate the combination of options used. return ctx.validate(diagnostics); }
void BuildSystemInvocation::parse(llvm::ArrayRef<std::string> args, llvm::SourceMgr& sourceMgr) { auto error = [&](const Twine &message) { sourceMgr.PrintMessage(llvm::SMLoc{}, llvm::SourceMgr::DK_Error, message); hadErrors = true; }; while (!args.empty()) { const auto& option = args.front(); args = args.slice(1); if (option == "-") { for (const auto& arg: args) { positionalArgs.push_back(arg); } break; } if (!option.empty() && option[0] != '-') { positionalArgs.push_back(option); continue; } if (option == "--help") { showUsage = true; break; } else if (option == "--version") { showVersion = true; break; } else if (option == "--no-db") { dbPath = ""; } else if (option == "--db") { if (args.empty()) { error("missing argument to '" + option + "'"); break; } dbPath = args[0]; args = args.slice(1); } else if (option == "-C" || option == "--chdir") { if (args.empty()) { error("missing argument to '" + option + "'"); break; } chdirPath = args[0]; args = args.slice(1); } else if (option == "-f") { if (args.empty()) { error("missing argument to '" + option + "'"); break; } buildFilePath = args[0]; args = args.slice(1); } else if (option == "--serial") { useSerialBuild = true; } else if (option == "-v" || option == "--verbose") { showVerboseStatus = true; } else if (option == "--trace") { if (args.empty()) { error("missing argument to '" + option + "'"); break; } traceFilePath = args[0]; args = args.slice(1); } else { error("invalid option '" + option + "'"); break; } } }
bool GnuLdDriver::parse(llvm::ArrayRef<const char *> args, std::unique_ptr<ELFLinkingContext> &context, raw_ostream &diag) { // Parse command line options using GnuLdOptions.td GnuLdOptTable table; unsigned missingIndex; unsigned missingCount; llvm::opt::InputArgList parsedArgs = table.ParseArgs(args.slice(1), missingIndex, missingCount); if (missingCount) { diag << "error: missing arg value for '" << parsedArgs.getArgString(missingIndex) << "' expected " << missingCount << " argument(s).\n"; return false; } // Handle --help if (parsedArgs.hasArg(OPT_help)) { table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false); return true; } // Use -target or use default target triple to instantiate LinkingContext llvm::Triple baseTriple; if (auto *arg = parsedArgs.getLastArg(OPT_target)) { baseTriple = llvm::Triple(arg->getValue()); } else { baseTriple = getDefaultTarget(args[0]); } llvm::Triple triple(baseTriple); if (!applyEmulation(triple, parsedArgs, diag)) return false; std::unique_ptr<ELFLinkingContext> ctx(createELFLinkingContext(triple)); if (!ctx) { diag << "unknown target triple\n"; return false; } // Copy mllvm for (auto *arg : parsedArgs.filtered(OPT_mllvm)) ctx->appendLLVMOption(arg->getValue()); // Ignore unknown arguments. for (auto unknownArg : parsedArgs.filtered(OPT_UNKNOWN)) diag << "warning: ignoring unknown argument: " << unknownArg->getValue() << "\n"; // Set sys root path. if (auto *arg = parsedArgs.getLastArg(OPT_sysroot)) ctx->setSysroot(arg->getValue()); // Handle --demangle option(For compatibility) if (parsedArgs.hasArg(OPT_demangle)) ctx->setDemangleSymbols(true); // Handle --no-demangle option. if (parsedArgs.hasArg(OPT_no_demangle)) ctx->setDemangleSymbols(false); // Figure out output kind (-r, -static, -shared) if (parsedArgs.hasArg(OPT_relocatable)) { ctx->setOutputELFType(llvm::ELF::ET_REL); ctx->setPrintRemainingUndefines(false); ctx->setAllowRemainingUndefines(true); } if (parsedArgs.hasArg(OPT_static)) { ctx->setOutputELFType(llvm::ELF::ET_EXEC); ctx->setIsStaticExecutable(true); } if (parsedArgs.hasArg(OPT_shared)) { ctx->setOutputELFType(llvm::ELF::ET_DYN); ctx->setAllowShlibUndefines(true); ctx->setUseShlibUndefines(false); ctx->setPrintRemainingUndefines(false); ctx->setAllowRemainingUndefines(true); } // Handle --stats. if (parsedArgs.hasArg(OPT_stats)) { ctx->setCollectStats(true); } // Figure out if the output type is nmagic/omagic if (auto *arg = parsedArgs.getLastArg(OPT_nmagic, OPT_omagic, OPT_no_omagic)) { switch (arg->getOption().getID()) { case OPT_nmagic: ctx->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC); ctx->setIsStaticExecutable(true); break; case OPT_omagic: ctx->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC); ctx->setIsStaticExecutable(true); break; case OPT_no_omagic: ctx->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT); ctx->setNoAllowDynamicLibraries(); break; } } if (parsedArgs.hasArg(OPT_discard_loc)) ctx->setDiscardLocals(true); if (parsedArgs.hasArg(OPT_discard_temp_loc)) ctx->setDiscardTempLocals(true); if (parsedArgs.hasArg(OPT_strip_all)) ctx->setStripSymbols(true); if (auto *arg = parsedArgs.getLastArg(OPT_soname)) ctx->setSharedObjectName(arg->getValue()); if (parsedArgs.hasArg(OPT_rosegment)) ctx->setCreateSeparateROSegment(); if (parsedArgs.hasArg(OPT_no_align_segments)) ctx->setAlignSegments(false); if (auto *arg = parsedArgs.getLastArg(OPT_image_base)) { uint64_t baseAddress = 0; StringRef inputValue = arg->getValue(); if (inputValue.getAsInteger(0, baseAddress) || !baseAddress) { diag << "invalid value for image base " << inputValue << "\n"; return false; } ctx->setBaseAddress(baseAddress); } if (parsedArgs.hasArg(OPT_merge_strings)) ctx->setMergeCommonStrings(true); if (parsedArgs.hasArg(OPT_t)) ctx->setLogInputFiles(true); if (parsedArgs.hasArg(OPT_use_shlib_undefs)) ctx->setUseShlibUndefines(true); if (auto val = getBool(parsedArgs, OPT_allow_shlib_undefs, OPT_no_allow_shlib_undefs)) ctx->setAllowShlibUndefines(*val); if (auto *arg = parsedArgs.getLastArg(OPT_e)) ctx->setEntrySymbolName(arg->getValue()); if (auto *arg = parsedArgs.getLastArg(OPT_output)) ctx->setOutputPath(arg->getValue()); if (parsedArgs.hasArg(OPT_noinhibit_exec)) ctx->setAllowRemainingUndefines(true); if (auto val = getBool(parsedArgs, OPT_export_dynamic, OPT_no_export_dynamic)) ctx->setExportDynamic(*val); if (parsedArgs.hasArg(OPT_allow_multiple_definition)) ctx->setAllowDuplicates(true); if (auto *arg = parsedArgs.getLastArg(OPT_dynamic_linker)) ctx->setInterpreter(arg->getValue()); if (auto *arg = parsedArgs.getLastArg(OPT_init)) ctx->setInitFunction(arg->getValue()); if (auto *arg = parsedArgs.getLastArg(OPT_fini)) ctx->setFiniFunction(arg->getValue()); if (auto *arg = parsedArgs.getLastArg(OPT_output_filetype)) ctx->setOutputFileType(arg->getValue()); // Process ELF/ARM specific options bool hasArmTarget1Rel = parsedArgs.hasArg(OPT_target1_rel); bool hasArmTarget1Abs = parsedArgs.hasArg(OPT_target1_abs); if (triple.getArch() == llvm::Triple::arm) { if (hasArmTarget1Rel && hasArmTarget1Abs) { diag << "error: options --target1-rel and --target1-abs" " can't be used together.\n"; return false; } else if (hasArmTarget1Rel || hasArmTarget1Abs) { ctx->setArmTarget1Rel(hasArmTarget1Rel && !hasArmTarget1Abs); } } else { for (const auto *arg : parsedArgs.filtered(OPT_grp_arm_targetopts)) { diag << "warning: ignoring unsupported ARM/ELF specific argument: " << arg->getSpelling() << "\n"; } } // Process MIPS specific options. if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el) { ctx->setMipsPcRelEhRel(parsedArgs.hasArg(OPT_pcrel_eh_reloc)); auto *hashArg = parsedArgs.getLastArg(OPT_hash_style); if (hashArg && hashArg->getValue() != StringRef("sysv")) { diag << "error: .gnu.hash is incompatible with the MIPS ABI\n"; return false; } } else { for (const auto *arg : parsedArgs.filtered(OPT_grp_mips_targetopts)) { diag << "warning: ignoring unsupported MIPS specific argument: " << arg->getSpelling() << "\n"; } } for (auto *arg : parsedArgs.filtered(OPT_L)) ctx->addSearchPath(arg->getValue()); // Add the default search directory specific to the target. if (!parsedArgs.hasArg(OPT_nostdlib)) addPlatformSearchDirs(*ctx, triple, baseTriple); for (auto *arg : parsedArgs.filtered(OPT_u)) ctx->addInitialUndefinedSymbol(arg->getValue()); for (auto *arg : parsedArgs.filtered(OPT_defsym)) { StringRef sym, target; uint64_t addr; if (parseDefsymAsAbsolute(arg->getValue(), sym, addr)) { ctx->addInitialAbsoluteSymbol(sym, addr); } else if (parseDefsymAsAlias(arg->getValue(), sym, target)) { ctx->addAlias(sym, target); } else { diag << "invalid --defsym: " << arg->getValue() << "\n"; return false; } } for (auto *arg : parsedArgs.filtered(OPT_z)) { StringRef opt = arg->getValue(); if (opt == "muldefs") ctx->setAllowDuplicates(true); else if (opt == "now") ctx->setDTFlag(ELFLinkingContext::DTFlag::DT_NOW); else if (opt == "origin") ctx->setDTFlag(ELFLinkingContext::DTFlag::DT_ORIGIN); else if (opt.startswith("max-page-size")) { // Parse -z max-page-size option. // The default page size is considered the minimum page size the user // can set, check the user input if its atleast the minimum page size // and does not exceed the maximum page size allowed for the target. uint64_t maxPageSize = 0; // Error if the page size user set is less than the maximum page size // and greather than the default page size and the user page size is a // modulo of the default page size. if ((!parseMaxPageSize(opt, maxPageSize)) || (maxPageSize < ctx->getPageSize()) || (maxPageSize % ctx->getPageSize())) { diag << "invalid option: " << opt << "\n"; return false; } ctx->setMaxPageSize(maxPageSize); } else { diag << "warning: ignoring unknown argument for -z: " << opt << "\n"; } } for (auto *arg : parsedArgs.filtered(OPT_rpath)) { SmallVector<StringRef, 2> rpaths; StringRef(arg->getValue()).split(rpaths, ":"); for (auto path : rpaths) ctx->addRpath(path); } for (auto *arg : parsedArgs.filtered(OPT_rpath_link)) { SmallVector<StringRef, 2> rpaths; StringRef(arg->getValue()).split(rpaths, ":"); for (auto path : rpaths) ctx->addRpathLink(path); } // Enable new dynamic tags. if (parsedArgs.hasArg(OPT_enable_newdtags)) ctx->setEnableNewDtags(true); // Support --wrap option. for (auto *arg : parsedArgs.filtered(OPT_wrap)) ctx->addWrapForSymbol(arg->getValue()); // Register possible input file parsers. ctx->registry().addSupportELFObjects(*ctx); ctx->registry().addSupportArchives(ctx->logInputFiles()); ctx->registry().addSupportYamlFiles(); if (ctx->allowLinkWithDynamicLibraries()) ctx->registry().addSupportELFDynamicSharedObjects(*ctx); std::stack<int> groupStack; int numfiles = 0; bool asNeeded = false; bool wholeArchive = false; // Process files for (auto arg : parsedArgs) { switch (arg->getOption().getID()) { case OPT_no_whole_archive: wholeArchive = false; break; case OPT_whole_archive: wholeArchive = true; break; case OPT_as_needed: asNeeded = true; break; case OPT_no_as_needed: asNeeded = false; break; case OPT_start_group: groupStack.push(numfiles); break; case OPT_end_group: { if (groupStack.empty()) { diag << "stray --end-group\n"; return false; } int startGroupPos = groupStack.top(); ctx->getNodes().push_back( llvm::make_unique<GroupEnd>(numfiles - startGroupPos)); groupStack.pop(); break; } case OPT_INPUT: case OPT_l: case OPT_T: { bool dashL = (arg->getOption().getID() == OPT_l); StringRef path = arg->getValue(); ErrorOr<StringRef> pathOrErr = findFile(*ctx, path, dashL); if (std::error_code ec = pathOrErr.getError()) { auto file = llvm::make_unique<ErrorFile>(path, ec); auto node = llvm::make_unique<FileNode>(std::move(file)); node->setAsNeeded(asNeeded); ctx->getNodes().push_back(std::move(node)); break; } StringRef realpath = pathOrErr.get(); bool isScript = (!path.endswith(".objtxt") && isLinkerScript(realpath, diag)); if (isScript) { if (ctx->logInputFiles()) diag << path << "\n"; ErrorOr<std::unique_ptr<MemoryBuffer>> mb = MemoryBuffer::getFileOrSTDIN(realpath); if (std::error_code ec = mb.getError()) { diag << "Cannot open " << path << ": " << ec.message() << "\n"; return false; } bool nostdlib = parsedArgs.hasArg(OPT_nostdlib); std::error_code ec = evalLinkerScript(*ctx, std::move(mb.get()), diag, nostdlib); if (ec) { diag << path << ": Error parsing linker script: " << ec.message() << "\n"; return false; } break; } std::vector<std::unique_ptr<File>> files = loadFile(*ctx, realpath, wholeArchive); for (std::unique_ptr<File> &file : files) { if (ctx->logInputFiles()) diag << file->path() << "\n"; auto node = llvm::make_unique<FileNode>(std::move(file)); node->setAsNeeded(asNeeded); ctx->getNodes().push_back(std::move(node)); } numfiles += files.size(); break; } } } if (ctx->getNodes().empty()) { diag << "No input files\n"; return false; } // Set default output file name if the output file was not specified. if (ctx->outputPath().empty()) { switch (ctx->outputFileType()) { case LinkingContext::OutputFileType::YAML: ctx->setOutputPath("-"); break; default: ctx->setOutputPath("a.out"); break; } } // Validate the combination of options used. if (!ctx->validate(diag)) return false; // Perform linker script semantic actions if (auto ec = ctx->linkerScriptSema().perform()) { diag << "Error in the linker script's semantics: " << ec.message() << "\n"; return false; } context.swap(ctx); return true; }
int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) { DllOptTable Table; unsigned MissingIndex; unsigned MissingCount; llvm::opt::InputArgList Args = Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount); if (MissingCount) { llvm::errs() << Args.getArgString(MissingIndex) << ": missing argument\n"; return 1; } // Handle when no input or output is specified if (Args.hasArgNoClaim(OPT_INPUT) || (!Args.hasArgNoClaim(OPT_d) && !Args.hasArgNoClaim(OPT_l))) { Table.PrintHelp(outs(), ArgsArr[0], "dlltool", false); llvm::outs() << "\nTARGETS: i386, i386:x86-64, arm\n"; return 1; } if (!Args.hasArgNoClaim(OPT_m) && Args.hasArgNoClaim(OPT_d)) { llvm::errs() << "error: no target machine specified\n" << "supported targets: i386, i386:x86-64, arm\n"; return 1; } for (auto *Arg : Args.filtered(OPT_UNKNOWN)) llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n"; if (!Args.hasArg(OPT_d)) { llvm::errs() << "no definition file specified\n"; return 1; } std::unique_ptr<MemoryBuffer> MB = openFile(Args.getLastArg(OPT_d)->getValue()); if (!MB) return 1; if (!MB->getBufferSize()) { llvm::errs() << "definition file empty\n"; return 1; } COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN; if (auto *Arg = Args.getLastArg(OPT_m)) Machine = getEmulation(Arg->getValue()); if (Machine == IMAGE_FILE_MACHINE_UNKNOWN) { llvm::errs() << "unknown target\n"; return 1; } Expected<COFFModuleDefinition> Def = parseCOFFModuleDefinition(*MB, Machine, true); if (!Def) { llvm::errs() << "error parsing definition\n" << errorToErrorCode(Def.takeError()).message(); return 1; } // Do this after the parser because parseCOFFModuleDefinition sets OutputFile. if (auto *Arg = Args.getLastArg(OPT_D)) Def->OutputFile = Arg->getValue(); if (Def->OutputFile.empty()) { llvm::errs() << "no output file specified\n"; return 1; } std::string Path = Args.getLastArgValue(OPT_l); if (Path.empty()) Path = getImplibPath(Def->OutputFile); if (Machine == IMAGE_FILE_MACHINE_I386 && Args.getLastArg(OPT_k)) { for (COFFShortExport& E : Def->Exports) { if (E.isWeak() || (!E.Name.empty() && E.Name[0] == '?')) continue; E.SymbolName = E.Name; // Trim off the trailing decoration. Symbols will always have a // starting prefix here (either _ for cdecl/stdcall, @ for fastcall // or ? for C++ functions). (Vectorcall functions also will end up having // a prefix here, even if they shouldn't.) E.Name = E.Name.substr(0, E.Name.find('@', 1)); // By making sure E.SymbolName != E.Name for decorated symbols, // writeImportLibrary writes these symbols with the type // IMPORT_NAME_UNDECORATE. } } if (writeImportLibrary(Def->OutputFile, Path, Def->Exports, Machine, true)) return 1; return 0; }