Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -349,6 +349,14 @@ return nullptr; } +static llvm::Optional +getBool(const llvm::opt::InputArgList &parsedArgs, + unsigned yesFlag, unsigned noFlag) { + if (auto *arg = parsedArgs.getLastArg(yesFlag, noFlag)) + return arg->getOption().getID() == yesFlag; + return llvm::None; +} + bool GnuLdDriver::parse(int argc, const char *argv[], std::unique_ptr &context, raw_ostream &diag) { @@ -368,17 +376,18 @@ } // Handle --help - if (parsedArgs->getLastArg(OPT_help)) { + if (parsedArgs->hasArg(OPT_help)) { table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false); return true; } // Use -target or use default target triple to instantiate LinkingContext llvm::Triple baseTriple; - if (llvm::opt::Arg *trip = parsedArgs->getLastArg(OPT_target)) - baseTriple = llvm::Triple(trip->getValue()); - else + if (auto *arg = parsedArgs->getLastArg(OPT_target)) { + baseTriple = llvm::Triple(arg->getValue()); + } else { baseTriple = getDefaultTarget(argv[0]); + } llvm::Triple triple(baseTriple); if (!applyEmulation(triple, *parsedArgs, diag)) @@ -391,11 +400,9 @@ return false; } - std::stack groupStack; - int numfiles = 0; - bool asNeeded = false; - bool wholeArchive = false; - bool hasNoStdLib = false; + // Copy mllvm + for (auto *arg : parsedArgs->filtered(OPT_mllvm)) + ctx->appendLLVMOption(arg->getValue()); // Ignore unknown arguments. for (auto unknownArg : parsedArgs->filtered(OPT_UNKNOWN)) @@ -403,30 +410,26 @@ << unknownArg->getValue() << "\n"; // Set sys root path. - if (llvm::opt::Arg *sysRootPath = parsedArgs->getLastArg(OPT_sysroot)) - ctx->setSysroot(sysRootPath->getValue()); - - // Add all search paths. - for (auto libDir : parsedArgs->filtered(OPT_L)) - ctx->addSearchPath(libDir->getValue()); + if (auto *arg = parsedArgs->getLastArg(OPT_sysroot)) + ctx->setSysroot(arg->getValue()); // Add the default search directory specific to the target. - if (!(hasNoStdLib = parsedArgs->hasArg(OPT_nostdlib))) + if (!parsedArgs->hasArg(OPT_nostdlib)) addPlatformSearchDirs(*ctx, triple, baseTriple); // Handle --demangle option(For compatibility) - if (parsedArgs->getLastArg(OPT_demangle)) + if (parsedArgs->hasArg(OPT_demangle)) ctx->setDemangleSymbols(true); // Handle --no-demangle option. - if (parsedArgs->getLastArg(OPT_no_demangle)) + if (parsedArgs->hasArg(OPT_no_demangle)) ctx->setDemangleSymbols(false); - // Figure out output kind ( -r, -static, -shared) - if (llvm::opt::Arg *kind = - parsedArgs->getLastArg(OPT_relocatable, OPT_static, OPT_shared, - OPT_nmagic, OPT_omagic, OPT_no_omagic)) { - switch (kind->getOption().getID()) { + // Figure out output kind (-r, -static, -shared) + if (auto *arg = parsedArgs->getLastArg( + OPT_relocatable, OPT_static, OPT_shared, + OPT_nmagic, OPT_omagic, OPT_no_omagic)) { + switch (arg->getOption().getID()) { case OPT_relocatable: ctx->setOutputELFType(llvm::ELF::ET_REL); ctx->setPrintRemainingUndefines(false); @@ -447,19 +450,17 @@ } // Figure out if the output type is nmagic/omagic - if (llvm::opt::Arg *kind = - parsedArgs->getLastArg(OPT_nmagic, OPT_omagic, OPT_no_omagic)) { - switch (kind->getOption().getID()) { + 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(); @@ -467,26 +468,127 @@ } } - for (auto inputArg : *parsedArgs) { - switch (inputArg->getOption().getID()) { - case OPT_merge_strings: - ctx->setMergeCommonStrings(true); - break; - case OPT_t: - ctx->setLogInputFiles(true); - break; - case OPT_use_shlib_undefs: - ctx->setUseShlibUndefines(true); - break; - case OPT_no_allow_shlib_undefs: - ctx->setAllowShlibUndefines(false); - break; - case OPT_allow_shlib_undefs: - ctx->setAllowShlibUndefines(true); - break; + 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 (parsedArgs->hasArg(OPT_export_dynamic)) + ctx->setExportDynamic(true); + + 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()); + + for (auto *arg : parsedArgs->filtered(OPT_L)) + ctx->addSearchPath(arg->getValue()); + + 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.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 ((!parseZOption(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 rpaths; + StringRef(arg->getValue()).split(rpaths, ":"); + for (auto path : rpaths) + ctx->addRpath(path); + } + + for (auto *arg : parsedArgs->filtered(OPT_rpath_link)) { + SmallVector rpaths; + StringRef(arg->getValue()).split(rpaths, ":"); + for (auto path : rpaths) + ctx->addRpathLink(path); + } + // Register possible input file parsers. ctx->registry().addSupportELFObjects( ctx->mergeCommonStrings(), @@ -498,52 +600,14 @@ ctx->registry().addSupportELFDynamicSharedObjects( ctx->useShlibUndefines(), ctx->targetHandler()); - // 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_e: - ctx->setEntrySymbolName(inputArg->getValue()); - break; - - case OPT_output: - ctx->setOutputPath(inputArg->getValue()); - break; - - case OPT_noinhibit_exec: - ctx->setAllowRemainingUndefines(true); - break; - - case OPT_export_dynamic: - ctx->setExportDynamic(true); - break; - - case OPT_allow_multiple_definition: - ctx->setAllowDuplicates(true); - break; - - case OPT_dynamic_linker: - ctx->setInterpreter(inputArg->getValue()); - break; - - case OPT_u: - ctx->addInitialUndefinedSymbol(inputArg->getValue()); - break; - - case OPT_init: - ctx->setInitFunction(inputArg->getValue()); - break; - - case OPT_fini: - ctx->setFiniFunction(inputArg->getValue()); - break; - - case OPT_output_filetype: - ctx->setOutputFileType(inputArg->getValue()); - break; + std::stack 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; @@ -560,20 +624,6 @@ asNeeded = false; break; - case OPT_defsym: { - StringRef sym, target; - uint64_t addr; - if (parseDefsymAsAbsolute(inputArg->getValue(), sym, addr)) { - ctx->addInitialAbsoluteSymbol(sym, addr); - } else if (parseDefsymAsAlias(inputArg->getValue(), sym, target)) { - ctx->addAlias(sym, target); - } else { - diag << "invalid --defsym: " << inputArg->getValue() << "\n"; - return false; - } - break; - } - case OPT_start_group: groupStack.push(numfiles); break; @@ -590,36 +640,10 @@ break; } - case OPT_z: { - StringRef extOpt = inputArg->getValue(); - if (extOpt == "muldefs") - ctx->setAllowDuplicates(true); - else if (extOpt.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 ((!parseZOption(extOpt, maxPageSize)) || - (maxPageSize < ctx->getPageSize()) || - (maxPageSize % ctx->getPageSize())) { - diag << "invalid option: " << extOpt << "\n"; - return false; - } - ctx->setMaxPageSize(maxPageSize); - } else - diag << "warning: ignoring unknown argument for -z: " << extOpt << "\n"; - break; - } - case OPT_INPUT: case OPT_l: { - bool dashL = (inputArg->getOption().getID() == OPT_l); - StringRef path = inputArg->getValue(); + bool dashL = (arg->getOption().getID() == OPT_l); + StringRef path = arg->getValue(); ErrorOr pathOrErr = findFile(*ctx, path, dashL); if (std::error_code ec = pathOrErr.getError()) { @@ -642,8 +666,9 @@ 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, hasNoStdLib); + evalLinkerScript(*ctx, std::move(mb.get()), diag, nostdlib); if (ec) { diag << path << ": Error parsing linker script: " << ec.message() << "\n"; @@ -663,55 +688,8 @@ numfiles += files.size(); break; } - - case OPT_rpath: { - SmallVector rpaths; - StringRef(inputArg->getValue()).split(rpaths, ":"); - for (auto path : rpaths) - ctx->addRpath(path); - break; - } - - case OPT_rpath_link: { - SmallVector rpaths; - StringRef(inputArg->getValue()).split(rpaths, ":"); - for (auto path : rpaths) - ctx->addRpathLink(path); - break; - } - - case OPT_strip_all: { - ctx->setStripSymbols(true); - break; - } - - case OPT_soname: - ctx->setSharedObjectName(inputArg->getValue()); - break; - - case OPT_rosegment: - ctx->setCreateSeparateROSegment(); - break; - - case OPT_no_align_segments: - ctx->setAlignSegments(false); - break; - - case OPT_image_base: { - uint64_t baseAddress = 0; - StringRef inputValue = inputArg->getValue(); - if ((inputValue.getAsInteger(0, baseAddress)) || !baseAddress) { - diag << "invalid value for image base " << inputValue << "\n"; - return false; - } - ctx->setBaseAddress(baseAddress); - break; } - - default: - break; - } // end switch on option ID - } // end for + } if (ctx->getNodes().empty()) { diag << "No input files\n";