1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432 |
- //===- ConfigManager.cpp --------------------------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "ConfigManager.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/StringSet.h"
- #include "llvm/BinaryFormat/COFF.h"
- #include "llvm/Option/Arg.h"
- #include "llvm/Option/ArgList.h"
- #include "llvm/Support/CRC.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/Compression.h"
- #include "llvm/Support/Errc.h"
- #include "llvm/Support/Error.h"
- #include "llvm/Support/MemoryBuffer.h"
- #include "llvm/Support/StringSaver.h"
- #include <memory>
- using namespace llvm;
- using namespace llvm::objcopy;
- namespace {
- enum ObjcopyID {
- OBJCOPY_INVALID = 0, // This is not an option ID.
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- OBJCOPY_##ID,
- #include "ObjcopyOpts.inc"
- #undef OPTION
- };
- #define PREFIX(NAME, VALUE) const char *const OBJCOPY_##NAME[] = VALUE;
- #include "ObjcopyOpts.inc"
- #undef PREFIX
- const opt::OptTable::Info ObjcopyInfoTable[] = {
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- {OBJCOPY_##PREFIX, \
- NAME, \
- HELPTEXT, \
- METAVAR, \
- OBJCOPY_##ID, \
- opt::Option::KIND##Class, \
- PARAM, \
- FLAGS, \
- OBJCOPY_##GROUP, \
- OBJCOPY_##ALIAS, \
- ALIASARGS, \
- VALUES},
- #include "ObjcopyOpts.inc"
- #undef OPTION
- };
- class ObjcopyOptTable : public opt::OptTable {
- public:
- ObjcopyOptTable() : OptTable(ObjcopyInfoTable) {
- setGroupedShortOptions(true);
- }
- };
- enum InstallNameToolID {
- INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- INSTALL_NAME_TOOL_##ID,
- #include "InstallNameToolOpts.inc"
- #undef OPTION
- };
- #define PREFIX(NAME, VALUE) \
- const char *const INSTALL_NAME_TOOL_##NAME[] = VALUE;
- #include "InstallNameToolOpts.inc"
- #undef PREFIX
- const opt::OptTable::Info InstallNameToolInfoTable[] = {
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- {INSTALL_NAME_TOOL_##PREFIX, \
- NAME, \
- HELPTEXT, \
- METAVAR, \
- INSTALL_NAME_TOOL_##ID, \
- opt::Option::KIND##Class, \
- PARAM, \
- FLAGS, \
- INSTALL_NAME_TOOL_##GROUP, \
- INSTALL_NAME_TOOL_##ALIAS, \
- ALIASARGS, \
- VALUES},
- #include "InstallNameToolOpts.inc"
- #undef OPTION
- };
- class InstallNameToolOptTable : public opt::OptTable {
- public:
- InstallNameToolOptTable() : OptTable(InstallNameToolInfoTable) {}
- };
- enum BitcodeStripID {
- BITCODE_STRIP_INVALID = 0, // This is not an option ID.
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- BITCODE_STRIP_##ID,
- #include "BitcodeStripOpts.inc"
- #undef OPTION
- };
- #define PREFIX(NAME, VALUE) const char *const BITCODE_STRIP_##NAME[] = VALUE;
- #include "BitcodeStripOpts.inc"
- #undef PREFIX
- const opt::OptTable::Info BitcodeStripInfoTable[] = {
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- {BITCODE_STRIP_##PREFIX, \
- NAME, \
- HELPTEXT, \
- METAVAR, \
- BITCODE_STRIP_##ID, \
- opt::Option::KIND##Class, \
- PARAM, \
- FLAGS, \
- BITCODE_STRIP_##GROUP, \
- BITCODE_STRIP_##ALIAS, \
- ALIASARGS, \
- VALUES},
- #include "BitcodeStripOpts.inc"
- #undef OPTION
- };
- class BitcodeStripOptTable : public opt::OptTable {
- public:
- BitcodeStripOptTable() : OptTable(BitcodeStripInfoTable) {}
- };
- enum StripID {
- STRIP_INVALID = 0, // This is not an option ID.
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- STRIP_##ID,
- #include "StripOpts.inc"
- #undef OPTION
- };
- #define PREFIX(NAME, VALUE) const char *const STRIP_##NAME[] = VALUE;
- #include "StripOpts.inc"
- #undef PREFIX
- const opt::OptTable::Info StripInfoTable[] = {
- #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- {STRIP_##PREFIX, NAME, HELPTEXT, \
- METAVAR, STRIP_##ID, opt::Option::KIND##Class, \
- PARAM, FLAGS, STRIP_##GROUP, \
- STRIP_##ALIAS, ALIASARGS, VALUES},
- #include "StripOpts.inc"
- #undef OPTION
- };
- class StripOptTable : public opt::OptTable {
- public:
- StripOptTable() : OptTable(StripInfoTable) { setGroupedShortOptions(true); }
- };
- } // namespace
- static SectionFlag parseSectionRenameFlag(StringRef SectionName) {
- return llvm::StringSwitch<SectionFlag>(SectionName)
- .CaseLower("alloc", SectionFlag::SecAlloc)
- .CaseLower("load", SectionFlag::SecLoad)
- .CaseLower("noload", SectionFlag::SecNoload)
- .CaseLower("readonly", SectionFlag::SecReadonly)
- .CaseLower("debug", SectionFlag::SecDebug)
- .CaseLower("code", SectionFlag::SecCode)
- .CaseLower("data", SectionFlag::SecData)
- .CaseLower("rom", SectionFlag::SecRom)
- .CaseLower("merge", SectionFlag::SecMerge)
- .CaseLower("strings", SectionFlag::SecStrings)
- .CaseLower("contents", SectionFlag::SecContents)
- .CaseLower("share", SectionFlag::SecShare)
- .CaseLower("exclude", SectionFlag::SecExclude)
- .Default(SectionFlag::SecNone);
- }
- static Expected<SectionFlag>
- parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
- SectionFlag ParsedFlags = SectionFlag::SecNone;
- for (StringRef Flag : SectionFlags) {
- SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
- if (ParsedFlag == SectionFlag::SecNone)
- return createStringError(
- errc::invalid_argument,
- "unrecognized section flag '%s'. Flags supported for GNU "
- "compatibility: alloc, load, noload, readonly, exclude, debug, "
- "code, data, rom, share, contents, merge, strings",
- Flag.str().c_str());
- ParsedFlags |= ParsedFlag;
- }
- return ParsedFlags;
- }
- static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {
- if (!FlagValue.contains('='))
- return createStringError(errc::invalid_argument,
- "bad format for --rename-section: missing '='");
- // Initial split: ".foo" = ".bar,f1,f2,..."
- auto Old2New = FlagValue.split('=');
- SectionRename SR;
- SR.OriginalName = Old2New.first;
- // Flags split: ".bar" "f1" "f2" ...
- SmallVector<StringRef, 6> NameAndFlags;
- Old2New.second.split(NameAndFlags, ',');
- SR.NewName = NameAndFlags[0];
- if (NameAndFlags.size() > 1) {
- Expected<SectionFlag> ParsedFlagSet =
- parseSectionFlagSet(makeArrayRef(NameAndFlags).drop_front());
- if (!ParsedFlagSet)
- return ParsedFlagSet.takeError();
- SR.NewFlags = *ParsedFlagSet;
- }
- return SR;
- }
- static Expected<std::pair<StringRef, uint64_t>>
- parseSetSectionAlignment(StringRef FlagValue) {
- if (!FlagValue.contains('='))
- return createStringError(
- errc::invalid_argument,
- "bad format for --set-section-alignment: missing '='");
- auto Split = StringRef(FlagValue).split('=');
- if (Split.first.empty())
- return createStringError(
- errc::invalid_argument,
- "bad format for --set-section-alignment: missing section name");
- uint64_t NewAlign;
- if (Split.second.getAsInteger(0, NewAlign))
- return createStringError(
- errc::invalid_argument,
- "invalid alignment for --set-section-alignment: '%s'",
- Split.second.str().c_str());
- return std::make_pair(Split.first, NewAlign);
- }
- static Expected<SectionFlagsUpdate>
- parseSetSectionFlagValue(StringRef FlagValue) {
- if (!StringRef(FlagValue).contains('='))
- return createStringError(errc::invalid_argument,
- "bad format for --set-section-flags: missing '='");
- // Initial split: ".foo" = "f1,f2,..."
- auto Section2Flags = StringRef(FlagValue).split('=');
- SectionFlagsUpdate SFU;
- SFU.Name = Section2Flags.first;
- // Flags split: "f1" "f2" ...
- SmallVector<StringRef, 6> SectionFlags;
- Section2Flags.second.split(SectionFlags, ',');
- Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags);
- if (!ParsedFlagSet)
- return ParsedFlagSet.takeError();
- SFU.NewFlags = *ParsedFlagSet;
- return SFU;
- }
- namespace {
- struct TargetInfo {
- FileFormat Format;
- MachineInfo Machine;
- };
- } // namespace
- // FIXME: consolidate with the bfd parsing used by lld.
- static const StringMap<MachineInfo> TargetMap{
- // Name, {EMachine, 64bit, LittleEndian}
- // x86
- {"elf32-i386", {ELF::EM_386, false, true}},
- {"elf32-x86-64", {ELF::EM_X86_64, false, true}},
- {"elf64-x86-64", {ELF::EM_X86_64, true, true}},
- // Intel MCU
- {"elf32-iamcu", {ELF::EM_IAMCU, false, true}},
- // ARM
- {"elf32-littlearm", {ELF::EM_ARM, false, true}},
- // ARM AArch64
- {"elf64-aarch64", {ELF::EM_AARCH64, true, true}},
- {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}},
- // RISC-V
- {"elf32-littleriscv", {ELF::EM_RISCV, false, true}},
- {"elf64-littleriscv", {ELF::EM_RISCV, true, true}},
- // PowerPC
- {"elf32-powerpc", {ELF::EM_PPC, false, false}},
- {"elf32-powerpcle", {ELF::EM_PPC, false, true}},
- {"elf64-powerpc", {ELF::EM_PPC64, true, false}},
- {"elf64-powerpcle", {ELF::EM_PPC64, true, true}},
- // MIPS
- {"elf32-bigmips", {ELF::EM_MIPS, false, false}},
- {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}},
- {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}},
- {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}},
- {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}},
- {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}},
- {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}},
- // SPARC
- {"elf32-sparc", {ELF::EM_SPARC, false, false}},
- {"elf32-sparcel", {ELF::EM_SPARC, false, true}},
- {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}},
- };
- static Expected<TargetInfo>
- getOutputTargetInfoByTargetName(StringRef TargetName) {
- StringRef OriginalTargetName = TargetName;
- bool IsFreeBSD = TargetName.consume_back("-freebsd");
- auto Iter = TargetMap.find(TargetName);
- if (Iter == std::end(TargetMap))
- return createStringError(errc::invalid_argument,
- "invalid output format: '%s'",
- OriginalTargetName.str().c_str());
- MachineInfo MI = Iter->getValue();
- if (IsFreeBSD)
- MI.OSABI = ELF::ELFOSABI_FREEBSD;
- FileFormat Format;
- if (TargetName.startswith("elf"))
- Format = FileFormat::ELF;
- else
- // This should never happen because `TargetName` is valid (it certainly
- // exists in the TargetMap).
- llvm_unreachable("unknown target prefix");
- return {TargetInfo{Format, MI}};
- }
- static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
- StringRef Filename, MatchStyle MS,
- function_ref<Error(Error)> ErrorCallback) {
- StringSaver Saver(Alloc);
- SmallVector<StringRef, 16> Lines;
- auto BufOrErr = MemoryBuffer::getFile(Filename);
- if (!BufOrErr)
- return createFileError(Filename, BufOrErr.getError());
- BufOrErr.get()->getBuffer().split(Lines, '\n');
- for (StringRef Line : Lines) {
- // Ignore everything after '#', trim whitespace, and only add the symbol if
- // it's not empty.
- auto TrimmedLine = Line.split('#').first.trim();
- if (!TrimmedLine.empty())
- if (Error E = Symbols.addMatcher(NameOrPattern::create(
- Saver.save(TrimmedLine), MS, ErrorCallback)))
- return E;
- }
- return Error::success();
- }
- Expected<NameOrPattern>
- NameOrPattern::create(StringRef Pattern, MatchStyle MS,
- function_ref<Error(Error)> ErrorCallback) {
- switch (MS) {
- case MatchStyle::Literal:
- return NameOrPattern(Pattern);
- case MatchStyle::Wildcard: {
- SmallVector<char, 32> Data;
- bool IsPositiveMatch = true;
- if (Pattern[0] == '!') {
- IsPositiveMatch = false;
- Pattern = Pattern.drop_front();
- }
- Expected<GlobPattern> GlobOrErr = GlobPattern::create(Pattern);
- // If we couldn't create it as a glob, report the error, but try again with
- // a literal if the error reporting is non-fatal.
- if (!GlobOrErr) {
- if (Error E = ErrorCallback(GlobOrErr.takeError()))
- return std::move(E);
- return create(Pattern, MatchStyle::Literal, ErrorCallback);
- }
- return NameOrPattern(std::make_shared<GlobPattern>(*GlobOrErr),
- IsPositiveMatch);
- }
- case MatchStyle::Regex: {
- SmallVector<char, 32> Data;
- return NameOrPattern(std::make_shared<Regex>(
- ("^" + Pattern.ltrim('^').rtrim('$') + "$").toStringRef(Data)));
- }
- }
- llvm_unreachable("Unhandled llvm.objcopy.MatchStyle enum");
- }
- static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
- BumpPtrAllocator &Alloc,
- StringRef Filename) {
- StringSaver Saver(Alloc);
- SmallVector<StringRef, 16> Lines;
- auto BufOrErr = MemoryBuffer::getFile(Filename);
- if (!BufOrErr)
- return createFileError(Filename, BufOrErr.getError());
- BufOrErr.get()->getBuffer().split(Lines, '\n');
- size_t NumLines = Lines.size();
- for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) {
- StringRef TrimmedLine = Lines[LineNo].split('#').first.trim();
- if (TrimmedLine.empty())
- continue;
- std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' ');
- StringRef NewName = Pair.second.trim();
- if (NewName.empty())
- return createStringError(errc::invalid_argument,
- "%s:%zu: missing new symbol name",
- Filename.str().c_str(), LineNo + 1);
- SymbolsToRename.insert({Pair.first, NewName});
- }
- return Error::success();
- }
- template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
- T Result;
- if (Val.getAsInteger(0, Result))
- return errc::invalid_argument;
- return Result;
- }
- namespace {
- enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip };
- } // anonymous namespace
- static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
- ToolType Tool) {
- StringRef HelpText, ToolName;
- switch (Tool) {
- case ToolType::Objcopy:
- ToolName = "llvm-objcopy";
- HelpText = " [options] input [output]";
- break;
- case ToolType::Strip:
- ToolName = "llvm-strip";
- HelpText = " [options] inputs...";
- break;
- case ToolType::InstallNameTool:
- ToolName = "llvm-install-name-tool";
- HelpText = " [options] input";
- break;
- case ToolType::BitcodeStrip:
- ToolName = "llvm-bitcode-strip";
- HelpText = " [options] input";
- break;
- }
- OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
- (ToolName + " tool").str().c_str());
- // TODO: Replace this with libOption call once it adds extrahelp support.
- // The CommandLine library has a cl::extrahelp class to support this,
- // but libOption does not have that yet.
- OS << "\nPass @FILE as argument to read options from FILE.\n";
- }
- static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
- // Parse value given with --add-symbol option and create the
- // new symbol if possible. The value format for --add-symbol is:
- //
- // <name>=[<section>:]<value>[,<flags>]
- //
- // where:
- // <name> - symbol name, can be empty string
- // <section> - optional section name. If not given ABS symbol is created
- // <value> - symbol value, can be decimal or hexadecimal number prefixed
- // with 0x.
- // <flags> - optional flags affecting symbol type, binding or visibility.
- NewSymbolInfo SI;
- StringRef Value;
- std::tie(SI.SymbolName, Value) = FlagValue.split('=');
- if (Value.empty())
- return createStringError(
- errc::invalid_argument,
- "bad format for --add-symbol, missing '=' after '%s'",
- SI.SymbolName.str().c_str());
- if (Value.contains(':')) {
- std::tie(SI.SectionName, Value) = Value.split(':');
- if (SI.SectionName.empty() || Value.empty())
- return createStringError(
- errc::invalid_argument,
- "bad format for --add-symbol, missing section name or symbol value");
- }
- SmallVector<StringRef, 6> Flags;
- Value.split(Flags, ',');
- if (Flags[0].getAsInteger(0, SI.Value))
- return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
- Flags[0].str().c_str());
- using Functor = std::function<void()>;
- SmallVector<StringRef, 6> UnsupportedFlags;
- for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
- static_cast<Functor>(
- StringSwitch<Functor>(Flags[I])
- .CaseLower("global",
- [&] { SI.Flags.push_back(SymbolFlag::Global); })
- .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); })
- .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); })
- .CaseLower("default",
- [&] { SI.Flags.push_back(SymbolFlag::Default); })
- .CaseLower("hidden",
- [&] { SI.Flags.push_back(SymbolFlag::Hidden); })
- .CaseLower("protected",
- [&] { SI.Flags.push_back(SymbolFlag::Protected); })
- .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); })
- .CaseLower("section",
- [&] { SI.Flags.push_back(SymbolFlag::Section); })
- .CaseLower("object",
- [&] { SI.Flags.push_back(SymbolFlag::Object); })
- .CaseLower("function",
- [&] { SI.Flags.push_back(SymbolFlag::Function); })
- .CaseLower(
- "indirect-function",
- [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); })
- .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); })
- .CaseLower("constructor",
- [&] { SI.Flags.push_back(SymbolFlag::Constructor); })
- .CaseLower("warning",
- [&] { SI.Flags.push_back(SymbolFlag::Warning); })
- .CaseLower("indirect",
- [&] { SI.Flags.push_back(SymbolFlag::Indirect); })
- .CaseLower("synthetic",
- [&] { SI.Flags.push_back(SymbolFlag::Synthetic); })
- .CaseLower("unique-object",
- [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); })
- .StartsWithLower("before=",
- [&] {
- StringRef SymNamePart =
- Flags[I].split('=').second;
- if (!SymNamePart.empty())
- SI.BeforeSyms.push_back(SymNamePart);
- })
- .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
- if (!UnsupportedFlags.empty())
- return createStringError(errc::invalid_argument,
- "unsupported flag%s for --add-symbol: '%s'",
- UnsupportedFlags.size() > 1 ? "s" : "",
- join(UnsupportedFlags, "', '").c_str());
- return SI;
- }
- Expected<const ELFConfig &> ConfigManager::getELFConfig() const {
- return ELF;
- }
- Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
- if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
- !Common.AllocSectionsPrefix.empty() || !Common.DumpSection.empty() ||
- !Common.KeepSection.empty() || !Common.SymbolsToGlobalize.empty() ||
- !Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() ||
- !Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
- !Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
- Common.ExtractDWO || Common.PreserveDates || Common.StripDWO ||
- Common.StripNonAlloc || Common.StripSections || Common.Weaken ||
- Common.DecompressDebugSections ||
- Common.DiscardMode == DiscardType::Locals ||
- !Common.SymbolsToAdd.empty()) {
- return createStringError(llvm::errc::invalid_argument,
- "option not supported by llvm-objcopy for COFF");
- }
- return COFF;
- }
- Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
- if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
- !Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() ||
- !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
- !Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
- !Common.SymbolsToKeepGlobal.empty() || !Common.SectionsToRename.empty() ||
- !Common.UnneededSymbolsToRemove.empty() ||
- !Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
- Common.ExtractDWO || Common.PreserveDates || Common.StripAllGNU ||
- Common.StripDWO || Common.StripNonAlloc || Common.StripSections ||
- Common.Weaken || Common.DecompressDebugSections || Common.StripUnneeded ||
- Common.DiscardMode == DiscardType::Locals ||
- !Common.SymbolsToAdd.empty()) {
- return createStringError(llvm::errc::invalid_argument,
- "option not supported by llvm-objcopy for MachO");
- }
- return MachO;
- }
- Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
- if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
- !Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
- !Common.AllocSectionsPrefix.empty() ||
- Common.DiscardMode != DiscardType::None || !Common.SymbolsToAdd.empty() ||
- !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToLocalize.empty() ||
- !Common.SymbolsToKeep.empty() || !Common.SymbolsToRemove.empty() ||
- !Common.UnneededSymbolsToRemove.empty() ||
- !Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
- !Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
- !Common.SetSectionFlags.empty() || !Common.SymbolsToRename.empty()) {
- return createStringError(
- llvm::errc::invalid_argument,
- "only flags for section dumping, removal, and addition are supported");
- }
- return Wasm;
- }
- // ParseObjcopyOptions returns the config and sets the input arguments. If a
- // help flag is set then ParseObjcopyOptions will print the help messege and
- // exit.
- Expected<DriverConfig>
- objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
- function_ref<Error(Error)> ErrorCallback) {
- DriverConfig DC;
- ObjcopyOptTable T;
- const char *const *DashDash =
- std::find_if(RawArgsArr.begin(), RawArgsArr.end(),
- [](StringRef Str) { return Str == "--"; });
- ArrayRef<const char *> ArgsArr = makeArrayRef(RawArgsArr.begin(), DashDash);
- if (DashDash != RawArgsArr.end())
- DashDash = std::next(DashDash);
- unsigned MissingArgumentIndex, MissingArgumentCount;
- llvm::opt::InputArgList InputArgs =
- T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
- if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
- printHelp(T, errs(), ToolType::Objcopy);
- exit(1);
- }
- if (InputArgs.hasArg(OBJCOPY_help)) {
- printHelp(T, outs(), ToolType::Objcopy);
- exit(0);
- }
- if (InputArgs.hasArg(OBJCOPY_version)) {
- outs() << "llvm-objcopy, compatible with GNU objcopy\n";
- cl::PrintVersionMessage();
- exit(0);
- }
- SmallVector<const char *, 2> Positional;
- for (auto Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
- return createStringError(errc::invalid_argument, "unknown argument '%s'",
- Arg->getAsString(InputArgs).c_str());
- for (auto Arg : InputArgs.filtered(OBJCOPY_INPUT))
- Positional.push_back(Arg->getValue());
- std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
- if (Positional.empty())
- return createStringError(errc::invalid_argument, "no input file specified");
- if (Positional.size() > 2)
- return createStringError(errc::invalid_argument,
- "too many positional arguments");
- ConfigManager ConfigMgr;
- CommonConfig &Config = ConfigMgr.Common;
- COFFConfig &COFFConfig = ConfigMgr.COFF;
- ELFConfig &ELFConfig = ConfigMgr.ELF;
- MachOConfig &MachOConfig = ConfigMgr.MachO;
- Config.InputFilename = Positional[0];
- Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
- if (InputArgs.hasArg(OBJCOPY_target) &&
- (InputArgs.hasArg(OBJCOPY_input_target) ||
- InputArgs.hasArg(OBJCOPY_output_target)))
- return createStringError(
- errc::invalid_argument,
- "--target cannot be used with --input-target or --output-target");
- if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
- return createStringError(errc::invalid_argument,
- "--regex and --wildcard are incompatible");
- MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
- ? MatchStyle::Regex
- : MatchStyle::Wildcard;
- MatchStyle SymbolMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
- ? MatchStyle::Regex
- : InputArgs.hasArg(OBJCOPY_wildcard)
- ? MatchStyle::Wildcard
- : MatchStyle::Literal;
- StringRef InputFormat, OutputFormat;
- if (InputArgs.hasArg(OBJCOPY_target)) {
- InputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
- OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
- } else {
- InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
- OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
- }
- // FIXME: Currently, we ignore the target for non-binary/ihex formats
- // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the
- // format by llvm::object::createBinary regardless of the option value.
- Config.InputFormat = StringSwitch<FileFormat>(InputFormat)
- .Case("binary", FileFormat::Binary)
- .Case("ihex", FileFormat::IHex)
- .Default(FileFormat::Unspecified);
- if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) {
- const uint8_t Invalid = 0xff;
- StringRef VisibilityStr =
- InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
- ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr)
- .Case("default", ELF::STV_DEFAULT)
- .Case("hidden", ELF::STV_HIDDEN)
- .Case("internal", ELF::STV_INTERNAL)
- .Case("protected", ELF::STV_PROTECTED)
- .Default(Invalid);
- if (ELFConfig.NewSymbolVisibility == Invalid)
- return createStringError(errc::invalid_argument,
- "'%s' is not a valid symbol visibility",
- VisibilityStr.str().c_str());
- }
- for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) {
- StringRef Subsystem, Version;
- std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':');
- COFFConfig.Subsystem =
- StringSwitch<unsigned>(Subsystem.lower())
- .Case("boot_application",
- COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
- .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
- .Case("efi_application", COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION)
- .Case("efi_boot_service_driver",
- COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
- .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM)
- .Case("efi_runtime_driver",
- COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
- .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE)
- .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI)
- .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
- .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN);
- if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN)
- return createStringError(errc::invalid_argument,
- "'%s' is not a valid subsystem",
- Subsystem.str().c_str());
- if (!Version.empty()) {
- StringRef Major, Minor;
- std::tie(Major, Minor) = Version.split('.');
- unsigned Number;
- if (Major.getAsInteger(10, Number))
- return createStringError(errc::invalid_argument,
- "'%s' is not a valid subsystem major version",
- Major.str().c_str());
- COFFConfig.MajorSubsystemVersion = Number;
- Number = 0;
- if (!Minor.empty() && Minor.getAsInteger(10, Number))
- return createStringError(errc::invalid_argument,
- "'%s' is not a valid subsystem minor version",
- Minor.str().c_str());
- COFFConfig.MinorSubsystemVersion = Number;
- }
- }
- Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
- .Case("binary", FileFormat::Binary)
- .Case("ihex", FileFormat::IHex)
- .Default(FileFormat::Unspecified);
- if (Config.OutputFormat == FileFormat::Unspecified) {
- if (OutputFormat.empty()) {
- Config.OutputFormat = Config.InputFormat;
- } else {
- Expected<TargetInfo> Target =
- getOutputTargetInfoByTargetName(OutputFormat);
- if (!Target)
- return Target.takeError();
- Config.OutputFormat = Target->Format;
- Config.OutputArch = Target->Machine;
- }
- }
- if (auto Arg = InputArgs.getLastArg(OBJCOPY_compress_debug_sections,
- OBJCOPY_compress_debug_sections_eq)) {
- Config.CompressionType = DebugCompressionType::Z;
- if (Arg->getOption().getID() == OBJCOPY_compress_debug_sections_eq) {
- Config.CompressionType =
- StringSwitch<DebugCompressionType>(
- InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq))
- .Case("zlib-gnu", DebugCompressionType::GNU)
- .Case("zlib", DebugCompressionType::Z)
- .Default(DebugCompressionType::None);
- if (Config.CompressionType == DebugCompressionType::None)
- return createStringError(
- errc::invalid_argument,
- "invalid or unsupported --compress-debug-sections format: %s",
- InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq)
- .str()
- .c_str());
- }
- if (!zlib::isAvailable())
- return createStringError(
- errc::invalid_argument,
- "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress");
- }
- Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
- // The gnu_debuglink's target is expected to not change or else its CRC would
- // become invalidated and get rejected. We can avoid recalculating the
- // checksum for every target file inside an archive by precomputing the CRC
- // here. This prevents a significant amount of I/O.
- if (!Config.AddGnuDebugLink.empty()) {
- auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink);
- if (!DebugOrErr)
- return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());
- auto Debug = std::move(*DebugOrErr);
- Config.GnuDebugLinkCRC32 =
- llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
- }
- Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
- Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
- Config.AllocSectionsPrefix =
- InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
- if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
- Config.ExtractPartition = Arg->getValue();
- for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
- if (!StringRef(Arg->getValue()).contains('='))
- return createStringError(errc::invalid_argument,
- "bad format for --redefine-sym");
- auto Old2New = StringRef(Arg->getValue()).split('=');
- if (!Config.SymbolsToRename.insert(Old2New).second)
- return createStringError(errc::invalid_argument,
- "multiple redefinition of symbol '%s'",
- Old2New.first.str().c_str());
- }
- for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
- if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
- Arg->getValue()))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
- Expected<SectionRename> SR =
- parseRenameSectionValue(StringRef(Arg->getValue()));
- if (!SR)
- return SR.takeError();
- if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
- return createStringError(errc::invalid_argument,
- "multiple renames of section '%s'",
- SR->OriginalName.str().c_str());
- }
- for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
- Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
- parseSetSectionAlignment(Arg->getValue());
- if (!NameAndAlign)
- return NameAndAlign.takeError();
- Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
- }
- for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
- Expected<SectionFlagsUpdate> SFU =
- parseSetSectionFlagValue(Arg->getValue());
- if (!SFU)
- return SFU.takeError();
- if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
- return createStringError(
- errc::invalid_argument,
- "--set-section-flags set multiple times for section '%s'",
- SFU->Name.str().c_str());
- }
- // Prohibit combinations of --set-section-flags when the section name is used
- // by --rename-section, either as a source or a destination.
- for (const auto &E : Config.SectionsToRename) {
- const SectionRename &SR = E.second;
- if (Config.SetSectionFlags.count(SR.OriginalName))
- return createStringError(
- errc::invalid_argument,
- "--set-section-flags=%s conflicts with --rename-section=%s=%s",
- SR.OriginalName.str().c_str(), SR.OriginalName.str().c_str(),
- SR.NewName.str().c_str());
- if (Config.SetSectionFlags.count(SR.NewName))
- return createStringError(
- errc::invalid_argument,
- "--set-section-flags=%s conflicts with --rename-section=%s=%s",
- SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
- SR.NewName.str().c_str());
- }
- for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section))
- if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
- Arg->getValue(), SectionMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_keep_section))
- if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
- Arg->getValue(), SectionMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_only_section))
- if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
- Arg->getValue(), SectionMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_add_section)) {
- StringRef ArgValue(Arg->getValue());
- if (!ArgValue.contains('='))
- return createStringError(errc::invalid_argument,
- "bad format for --add-section: missing '='");
- if (ArgValue.split("=").second.empty())
- return createStringError(
- errc::invalid_argument,
- "bad format for --add-section: missing file name");
- Config.AddSection.push_back(ArgValue);
- }
- for (auto Arg : InputArgs.filtered(OBJCOPY_update_section)) {
- StringRef ArgValue(Arg->getValue());
- if (!ArgValue.contains('='))
- return createStringError(errc::invalid_argument,
- "bad format for --update-section: missing '='");
- if (ArgValue.split("=").second.empty())
- return createStringError(
- errc::invalid_argument,
- "bad format for --update-section: missing file name");
- Config.UpdateSection.push_back(ArgValue);
- }
- for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
- StringRef Value(Arg->getValue());
- if (Value.split('=').second.empty())
- return createStringError(
- errc::invalid_argument,
- "bad format for --dump-section, expected section=file");
- Config.DumpSection.push_back(Value);
- }
- Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
- Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
- Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
- Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
- Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
- Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
- Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
- Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
- Config.ExtractMainPartition =
- InputArgs.hasArg(OBJCOPY_extract_main_partition);
- ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
- Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
- if (InputArgs.hasArg(OBJCOPY_discard_all, OBJCOPY_discard_locals))
- Config.DiscardMode =
- InputArgs.hasFlag(OBJCOPY_discard_all, OBJCOPY_discard_locals)
- ? DiscardType::All
- : DiscardType::Locals;
- Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
- ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
- MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
- Config.DecompressDebugSections =
- InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
- if (Config.DiscardMode == DiscardType::All) {
- Config.StripDebug = true;
- ELFConfig.KeepFileSymbols = true;
- }
- for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
- if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
- if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
- Arg->getValue(), SymbolMatchStyle,
- ErrorCallback))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
- if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
- if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
- Arg->getValue(), SymbolMatchStyle,
- ErrorCallback))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
- if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
- if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
- Arg->getValue(), SymbolMatchStyle,
- ErrorCallback))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
- if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
- if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
- Arg->getValue(), SymbolMatchStyle,
- ErrorCallback))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
- if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
- if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
- Arg->getValue(), SymbolMatchStyle,
- ErrorCallback))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
- if (Error E =
- Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
- if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
- Arg->getValue(), SymbolMatchStyle,
- ErrorCallback))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
- if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
- if (Error E =
- addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
- SymbolMatchStyle, ErrorCallback))
- return std::move(E);
- for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
- Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
- if (!SymInfo)
- return SymInfo.takeError();
- Config.SymbolsToAdd.push_back(*SymInfo);
- }
- ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
- Config.DeterministicArchives = InputArgs.hasFlag(
- OBJCOPY_enable_deterministic_archives,
- OBJCOPY_disable_deterministic_archives, /*default=*/true);
- Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
- if (Config.PreserveDates &&
- (Config.OutputFilename == "-" || Config.InputFilename == "-"))
- return createStringError(errc::invalid_argument,
- "--preserve-dates requires a file");
- for (auto Arg : InputArgs)
- if (Arg->getOption().matches(OBJCOPY_set_start)) {
- auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
- if (!EAddr)
- return createStringError(
- EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
- ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
- } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
- auto EIncr = getAsInteger<int64_t>(Arg->getValue());
- if (!EIncr)
- return createStringError(EIncr.getError(),
- "bad entry point increment: '%s'",
- Arg->getValue());
- auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr)
- : [](uint64_t A) { return A; };
- ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
- return Expr(EAddr) + *EIncr;
- };
- }
- if (Config.DecompressDebugSections &&
- Config.CompressionType != DebugCompressionType::None) {
- return createStringError(
- errc::invalid_argument,
- "cannot specify both --compress-debug-sections and "
- "--decompress-debug-sections");
- }
- if (Config.DecompressDebugSections && !zlib::isAvailable())
- return createStringError(
- errc::invalid_argument,
- "LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress");
- if (Config.ExtractPartition && Config.ExtractMainPartition)
- return createStringError(errc::invalid_argument,
- "cannot specify --extract-partition together with "
- "--extract-main-partition");
- DC.CopyConfigs.push_back(std::move(ConfigMgr));
- return std::move(DC);
- }
- // ParseInstallNameToolOptions returns the config and sets the input arguments.
- // If a help flag is set then ParseInstallNameToolOptions will print the help
- // messege and exit.
- Expected<DriverConfig>
- objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
- DriverConfig DC;
- ConfigManager ConfigMgr;
- CommonConfig &Config = ConfigMgr.Common;
- MachOConfig &MachOConfig = ConfigMgr.MachO;
- InstallNameToolOptTable T;
- unsigned MissingArgumentIndex, MissingArgumentCount;
- llvm::opt::InputArgList InputArgs =
- T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
- if (MissingArgumentCount)
- return createStringError(
- errc::invalid_argument,
- "missing argument to " +
- StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
- " option");
- if (InputArgs.size() == 0) {
- printHelp(T, errs(), ToolType::InstallNameTool);
- exit(1);
- }
- if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
- printHelp(T, outs(), ToolType::InstallNameTool);
- exit(0);
- }
- if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
- outs() << "llvm-install-name-tool, compatible with cctools "
- "install_name_tool\n";
- cl::PrintVersionMessage();
- exit(0);
- }
- for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
- MachOConfig.RPathToAdd.push_back(Arg->getValue());
- for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
- MachOConfig.RPathToPrepend.push_back(Arg->getValue());
- for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
- StringRef RPath = Arg->getValue();
- // Cannot add and delete the same rpath at the same time.
- if (is_contained(MachOConfig.RPathToAdd, RPath))
- return createStringError(
- errc::invalid_argument,
- "cannot specify both -add_rpath '%s' and -delete_rpath '%s'",
- RPath.str().c_str(), RPath.str().c_str());
- if (is_contained(MachOConfig.RPathToPrepend, RPath))
- return createStringError(
- errc::invalid_argument,
- "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'",
- RPath.str().c_str(), RPath.str().c_str());
- MachOConfig.RPathsToRemove.insert(RPath);
- }
- for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) {
- StringRef Old = Arg->getValue(0);
- StringRef New = Arg->getValue(1);
- auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; };
- // Cannot specify duplicate -rpath entries
- auto It1 = find_if(
- MachOConfig.RPathsToUpdate,
- [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) {
- return Match(OldNew.getFirst()) || Match(OldNew.getSecond());
- });
- if (It1 != MachOConfig.RPathsToUpdate.end())
- return createStringError(errc::invalid_argument,
- "cannot specify both -rpath '" +
- It1->getFirst() + "' '" + It1->getSecond() +
- "' and -rpath '" + Old + "' '" + New + "'");
- // Cannot specify the same rpath under both -delete_rpath and -rpath
- auto It2 = find_if(MachOConfig.RPathsToRemove, Match);
- if (It2 != MachOConfig.RPathsToRemove.end())
- return createStringError(errc::invalid_argument,
- "cannot specify both -delete_rpath '" + *It2 +
- "' and -rpath '" + Old + "' '" + New + "'");
- // Cannot specify the same rpath under both -add_rpath and -rpath
- auto It3 = find_if(MachOConfig.RPathToAdd, Match);
- if (It3 != MachOConfig.RPathToAdd.end())
- return createStringError(errc::invalid_argument,
- "cannot specify both -add_rpath '" + *It3 +
- "' and -rpath '" + Old + "' '" + New + "'");
- // Cannot specify the same rpath under both -prepend_rpath and -rpath.
- auto It4 = find_if(MachOConfig.RPathToPrepend, Match);
- if (It4 != MachOConfig.RPathToPrepend.end())
- return createStringError(errc::invalid_argument,
- "cannot specify both -prepend_rpath '" + *It4 +
- "' and -rpath '" + Old + "' '" + New + "'");
- MachOConfig.RPathsToUpdate.insert({Old, New});
- }
- if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) {
- MachOConfig.SharedLibId = Arg->getValue();
- if (MachOConfig.SharedLibId->empty())
- return createStringError(errc::invalid_argument,
- "cannot specify an empty id");
- }
- for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change))
- MachOConfig.InstallNamesToUpdate.insert(
- {Arg->getValue(0), Arg->getValue(1)});
- MachOConfig.RemoveAllRpaths =
- InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);
- SmallVector<StringRef, 2> Positional;
- for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
- return createStringError(errc::invalid_argument, "unknown argument '%s'",
- Arg->getAsString(InputArgs).c_str());
- for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
- Positional.push_back(Arg->getValue());
- if (Positional.empty())
- return createStringError(errc::invalid_argument, "no input file specified");
- if (Positional.size() > 1)
- return createStringError(
- errc::invalid_argument,
- "llvm-install-name-tool expects a single input file");
- Config.InputFilename = Positional[0];
- Config.OutputFilename = Positional[0];
- DC.CopyConfigs.push_back(std::move(ConfigMgr));
- return std::move(DC);
- }
- Expected<DriverConfig>
- objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr) {
- DriverConfig DC;
- ConfigManager ConfigMgr;
- CommonConfig &Config = ConfigMgr.Common;
- BitcodeStripOptTable T;
- unsigned MissingArgumentIndex, MissingArgumentCount;
- opt::InputArgList InputArgs =
- T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
- if (InputArgs.size() == 0) {
- printHelp(T, errs(), ToolType::BitcodeStrip);
- exit(1);
- }
- if (InputArgs.hasArg(BITCODE_STRIP_help)) {
- printHelp(T, outs(), ToolType::BitcodeStrip);
- exit(0);
- }
- if (InputArgs.hasArg(BITCODE_STRIP_version)) {
- outs() << "llvm-bitcode-strip, compatible with cctools "
- "bitcode_strip\n";
- cl::PrintVersionMessage();
- exit(0);
- }
- for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN))
- return createStringError(errc::invalid_argument, "unknown argument '%s'",
- Arg->getAsString(InputArgs).c_str());
- SmallVector<StringRef, 2> Positional;
- for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
- Positional.push_back(Arg->getValue());
- if (Positional.size() > 1)
- return createStringError(errc::invalid_argument,
- "llvm-bitcode-strip expects a single input file");
- assert(!Positional.empty());
- Config.InputFilename = Positional[0];
- Config.OutputFilename = Positional[0];
- DC.CopyConfigs.push_back(std::move(ConfigMgr));
- return std::move(DC);
- }
- // ParseStripOptions returns the config and sets the input arguments. If a
- // help flag is set then ParseStripOptions will print the help messege and
- // exit.
- Expected<DriverConfig>
- objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
- function_ref<Error(Error)> ErrorCallback) {
- const char *const *DashDash =
- std::find_if(RawArgsArr.begin(), RawArgsArr.end(),
- [](StringRef Str) { return Str == "--"; });
- ArrayRef<const char *> ArgsArr = makeArrayRef(RawArgsArr.begin(), DashDash);
- if (DashDash != RawArgsArr.end())
- DashDash = std::next(DashDash);
- StripOptTable T;
- unsigned MissingArgumentIndex, MissingArgumentCount;
- llvm::opt::InputArgList InputArgs =
- T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
- if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
- printHelp(T, errs(), ToolType::Strip);
- exit(1);
- }
- if (InputArgs.hasArg(STRIP_help)) {
- printHelp(T, outs(), ToolType::Strip);
- exit(0);
- }
- if (InputArgs.hasArg(STRIP_version)) {
- outs() << "llvm-strip, compatible with GNU strip\n";
- cl::PrintVersionMessage();
- exit(0);
- }
- SmallVector<StringRef, 2> Positional;
- for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN))
- return createStringError(errc::invalid_argument, "unknown argument '%s'",
- Arg->getAsString(InputArgs).c_str());
- for (auto Arg : InputArgs.filtered(STRIP_INPUT))
- Positional.push_back(Arg->getValue());
- std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
- if (Positional.empty())
- return createStringError(errc::invalid_argument, "no input file specified");
- if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
- return createStringError(
- errc::invalid_argument,
- "multiple input files cannot be used in combination with -o");
- ConfigManager ConfigMgr;
- CommonConfig &Config = ConfigMgr.Common;
- ELFConfig &ELFConfig = ConfigMgr.ELF;
- MachOConfig &MachOConfig = ConfigMgr.MachO;
- if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
- return createStringError(errc::invalid_argument,
- "--regex and --wildcard are incompatible");
- MatchStyle SectionMatchStyle =
- InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
- MatchStyle SymbolMatchStyle = InputArgs.hasArg(STRIP_regex)
- ? MatchStyle::Regex
- : InputArgs.hasArg(STRIP_wildcard)
- ? MatchStyle::Wildcard
- : MatchStyle::Literal;
- ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
- Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
- if (InputArgs.hasArg(STRIP_discard_all, STRIP_discard_locals))
- Config.DiscardMode =
- InputArgs.hasFlag(STRIP_discard_all, STRIP_discard_locals)
- ? DiscardType::All
- : DiscardType::Locals;
- Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
- Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
- if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
- Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
- Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
- MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
- Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
- ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
- MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
- for (auto Arg : InputArgs.filtered(STRIP_keep_section))
- if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
- Arg->getValue(), SectionMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(STRIP_remove_section))
- if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
- Arg->getValue(), SectionMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(STRIP_strip_symbol))
- if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- for (auto Arg : InputArgs.filtered(STRIP_keep_symbol))
- if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
- Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
- return std::move(E);
- if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
- !Config.StripUnneeded && Config.DiscardMode == DiscardType::None &&
- !Config.StripAllGNU && Config.SymbolsToRemove.empty())
- Config.StripAll = true;
- if (Config.DiscardMode == DiscardType::All) {
- Config.StripDebug = true;
- ELFConfig.KeepFileSymbols = true;
- }
- Config.DeterministicArchives =
- InputArgs.hasFlag(STRIP_enable_deterministic_archives,
- STRIP_disable_deterministic_archives, /*default=*/true);
- Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
- Config.InputFormat = FileFormat::Unspecified;
- Config.OutputFormat = FileFormat::Unspecified;
- DriverConfig DC;
- if (Positional.size() == 1) {
- Config.InputFilename = Positional[0];
- Config.OutputFilename =
- InputArgs.getLastArgValue(STRIP_output, Positional[0]);
- DC.CopyConfigs.push_back(std::move(ConfigMgr));
- } else {
- StringMap<unsigned> InputFiles;
- for (StringRef Filename : Positional) {
- if (InputFiles[Filename]++ == 1) {
- if (Filename == "-")
- return createStringError(
- errc::invalid_argument,
- "cannot specify '-' as an input file more than once");
- if (Error E = ErrorCallback(createStringError(
- errc::invalid_argument, "'%s' was already specified",
- Filename.str().c_str())))
- return std::move(E);
- }
- Config.InputFilename = Filename;
- Config.OutputFilename = Filename;
- DC.CopyConfigs.push_back(ConfigMgr);
- }
- }
- if (Config.PreserveDates && (is_contained(Positional, "-") ||
- InputArgs.getLastArgValue(STRIP_output) == "-"))
- return createStringError(errc::invalid_argument,
- "--preserve-dates requires a file");
- return std::move(DC);
- }
|