CopyConfig.cpp 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. //===- CopyConfig.cpp -----------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "CopyConfig.h"
  9. #include "llvm/ADT/Optional.h"
  10. #include "llvm/ADT/SmallVector.h"
  11. #include "llvm/ADT/StringRef.h"
  12. #include "llvm/ADT/StringSet.h"
  13. #include "llvm/Option/Arg.h"
  14. #include "llvm/Option/ArgList.h"
  15. #include "llvm/Support/CRC.h"
  16. #include "llvm/Support/CommandLine.h"
  17. #include "llvm/Support/Compression.h"
  18. #include "llvm/Support/Errc.h"
  19. #include "llvm/Support/MemoryBuffer.h"
  20. #include "llvm/Support/StringSaver.h"
  21. #include <memory>
  22. namespace llvm {
  23. namespace objcopy {
  24. namespace {
  25. enum ObjcopyID {
  26. OBJCOPY_INVALID = 0, // This is not an option ID.
  27. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  28. HELPTEXT, METAVAR, VALUES) \
  29. OBJCOPY_##ID,
  30. #include "ObjcopyOpts.inc"
  31. #undef OPTION
  32. };
  33. #define PREFIX(NAME, VALUE) const char *const OBJCOPY_##NAME[] = VALUE;
  34. #include "ObjcopyOpts.inc"
  35. #undef PREFIX
  36. static const opt::OptTable::Info ObjcopyInfoTable[] = {
  37. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  38. HELPTEXT, METAVAR, VALUES) \
  39. {OBJCOPY_##PREFIX, \
  40. NAME, \
  41. HELPTEXT, \
  42. METAVAR, \
  43. OBJCOPY_##ID, \
  44. opt::Option::KIND##Class, \
  45. PARAM, \
  46. FLAGS, \
  47. OBJCOPY_##GROUP, \
  48. OBJCOPY_##ALIAS, \
  49. ALIASARGS, \
  50. VALUES},
  51. #include "ObjcopyOpts.inc"
  52. #undef OPTION
  53. };
  54. class ObjcopyOptTable : public opt::OptTable {
  55. public:
  56. ObjcopyOptTable() : OptTable(ObjcopyInfoTable) {}
  57. };
  58. enum InstallNameToolID {
  59. INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
  60. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  61. HELPTEXT, METAVAR, VALUES) \
  62. INSTALL_NAME_TOOL_##ID,
  63. #include "InstallNameToolOpts.inc"
  64. #undef OPTION
  65. };
  66. #define PREFIX(NAME, VALUE) \
  67. const char *const INSTALL_NAME_TOOL_##NAME[] = VALUE;
  68. #include "InstallNameToolOpts.inc"
  69. #undef PREFIX
  70. static const opt::OptTable::Info InstallNameToolInfoTable[] = {
  71. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  72. HELPTEXT, METAVAR, VALUES) \
  73. {INSTALL_NAME_TOOL_##PREFIX, \
  74. NAME, \
  75. HELPTEXT, \
  76. METAVAR, \
  77. INSTALL_NAME_TOOL_##ID, \
  78. opt::Option::KIND##Class, \
  79. PARAM, \
  80. FLAGS, \
  81. INSTALL_NAME_TOOL_##GROUP, \
  82. INSTALL_NAME_TOOL_##ALIAS, \
  83. ALIASARGS, \
  84. VALUES},
  85. #include "InstallNameToolOpts.inc"
  86. #undef OPTION
  87. };
  88. class InstallNameToolOptTable : public opt::OptTable {
  89. public:
  90. InstallNameToolOptTable() : OptTable(InstallNameToolInfoTable) {}
  91. };
  92. enum BitcodeStripID {
  93. BITCODE_STRIP_INVALID = 0, // This is not an option ID.
  94. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  95. HELPTEXT, METAVAR, VALUES) \
  96. BITCODE_STRIP_##ID,
  97. #include "BitcodeStripOpts.inc"
  98. #undef OPTION
  99. };
  100. #define PREFIX(NAME, VALUE) const char *const BITCODE_STRIP_##NAME[] = VALUE;
  101. #include "BitcodeStripOpts.inc"
  102. #undef PREFIX
  103. static const opt::OptTable::Info BitcodeStripInfoTable[] = {
  104. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  105. HELPTEXT, METAVAR, VALUES) \
  106. {BITCODE_STRIP_##PREFIX, \
  107. NAME, \
  108. HELPTEXT, \
  109. METAVAR, \
  110. BITCODE_STRIP_##ID, \
  111. opt::Option::KIND##Class, \
  112. PARAM, \
  113. FLAGS, \
  114. BITCODE_STRIP_##GROUP, \
  115. BITCODE_STRIP_##ALIAS, \
  116. ALIASARGS, \
  117. VALUES},
  118. #include "BitcodeStripOpts.inc"
  119. #undef OPTION
  120. };
  121. class BitcodeStripOptTable : public opt::OptTable {
  122. public:
  123. BitcodeStripOptTable() : OptTable(BitcodeStripInfoTable) {}
  124. };
  125. enum StripID {
  126. STRIP_INVALID = 0, // This is not an option ID.
  127. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  128. HELPTEXT, METAVAR, VALUES) \
  129. STRIP_##ID,
  130. #include "StripOpts.inc"
  131. #undef OPTION
  132. };
  133. #define PREFIX(NAME, VALUE) const char *const STRIP_##NAME[] = VALUE;
  134. #include "StripOpts.inc"
  135. #undef PREFIX
  136. static const opt::OptTable::Info StripInfoTable[] = {
  137. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  138. HELPTEXT, METAVAR, VALUES) \
  139. {STRIP_##PREFIX, NAME, HELPTEXT, \
  140. METAVAR, STRIP_##ID, opt::Option::KIND##Class, \
  141. PARAM, FLAGS, STRIP_##GROUP, \
  142. STRIP_##ALIAS, ALIASARGS, VALUES},
  143. #include "StripOpts.inc"
  144. #undef OPTION
  145. };
  146. class StripOptTable : public opt::OptTable {
  147. public:
  148. StripOptTable() : OptTable(StripInfoTable) {}
  149. };
  150. } // namespace
  151. static SectionFlag parseSectionRenameFlag(StringRef SectionName) {
  152. return llvm::StringSwitch<SectionFlag>(SectionName)
  153. .CaseLower("alloc", SectionFlag::SecAlloc)
  154. .CaseLower("load", SectionFlag::SecLoad)
  155. .CaseLower("noload", SectionFlag::SecNoload)
  156. .CaseLower("readonly", SectionFlag::SecReadonly)
  157. .CaseLower("debug", SectionFlag::SecDebug)
  158. .CaseLower("code", SectionFlag::SecCode)
  159. .CaseLower("data", SectionFlag::SecData)
  160. .CaseLower("rom", SectionFlag::SecRom)
  161. .CaseLower("merge", SectionFlag::SecMerge)
  162. .CaseLower("strings", SectionFlag::SecStrings)
  163. .CaseLower("contents", SectionFlag::SecContents)
  164. .CaseLower("share", SectionFlag::SecShare)
  165. .CaseLower("exclude", SectionFlag::SecExclude)
  166. .Default(SectionFlag::SecNone);
  167. }
  168. static Expected<SectionFlag>
  169. parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
  170. SectionFlag ParsedFlags = SectionFlag::SecNone;
  171. for (StringRef Flag : SectionFlags) {
  172. SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
  173. if (ParsedFlag == SectionFlag::SecNone)
  174. return createStringError(
  175. errc::invalid_argument,
  176. "unrecognized section flag '%s'. Flags supported for GNU "
  177. "compatibility: alloc, load, noload, readonly, exclude, debug, "
  178. "code, data, rom, share, contents, merge, strings",
  179. Flag.str().c_str());
  180. ParsedFlags |= ParsedFlag;
  181. }
  182. return ParsedFlags;
  183. }
  184. static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {
  185. if (!FlagValue.contains('='))
  186. return createStringError(errc::invalid_argument,
  187. "bad format for --rename-section: missing '='");
  188. // Initial split: ".foo" = ".bar,f1,f2,..."
  189. auto Old2New = FlagValue.split('=');
  190. SectionRename SR;
  191. SR.OriginalName = Old2New.first;
  192. // Flags split: ".bar" "f1" "f2" ...
  193. SmallVector<StringRef, 6> NameAndFlags;
  194. Old2New.second.split(NameAndFlags, ',');
  195. SR.NewName = NameAndFlags[0];
  196. if (NameAndFlags.size() > 1) {
  197. Expected<SectionFlag> ParsedFlagSet =
  198. parseSectionFlagSet(makeArrayRef(NameAndFlags).drop_front());
  199. if (!ParsedFlagSet)
  200. return ParsedFlagSet.takeError();
  201. SR.NewFlags = *ParsedFlagSet;
  202. }
  203. return SR;
  204. }
  205. static Expected<std::pair<StringRef, uint64_t>>
  206. parseSetSectionAlignment(StringRef FlagValue) {
  207. if (!FlagValue.contains('='))
  208. return createStringError(
  209. errc::invalid_argument,
  210. "bad format for --set-section-alignment: missing '='");
  211. auto Split = StringRef(FlagValue).split('=');
  212. if (Split.first.empty())
  213. return createStringError(
  214. errc::invalid_argument,
  215. "bad format for --set-section-alignment: missing section name");
  216. uint64_t NewAlign;
  217. if (Split.second.getAsInteger(0, NewAlign))
  218. return createStringError(errc::invalid_argument,
  219. "invalid alignment for --set-section-alignment: '%s'",
  220. Split.second.str().c_str());
  221. return std::make_pair(Split.first, NewAlign);
  222. }
  223. static Expected<SectionFlagsUpdate>
  224. parseSetSectionFlagValue(StringRef FlagValue) {
  225. if (!StringRef(FlagValue).contains('='))
  226. return createStringError(errc::invalid_argument,
  227. "bad format for --set-section-flags: missing '='");
  228. // Initial split: ".foo" = "f1,f2,..."
  229. auto Section2Flags = StringRef(FlagValue).split('=');
  230. SectionFlagsUpdate SFU;
  231. SFU.Name = Section2Flags.first;
  232. // Flags split: "f1" "f2" ...
  233. SmallVector<StringRef, 6> SectionFlags;
  234. Section2Flags.second.split(SectionFlags, ',');
  235. Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags);
  236. if (!ParsedFlagSet)
  237. return ParsedFlagSet.takeError();
  238. SFU.NewFlags = *ParsedFlagSet;
  239. return SFU;
  240. }
  241. struct TargetInfo {
  242. FileFormat Format;
  243. MachineInfo Machine;
  244. };
  245. // FIXME: consolidate with the bfd parsing used by lld.
  246. static const StringMap<MachineInfo> TargetMap{
  247. // Name, {EMachine, 64bit, LittleEndian}
  248. // x86
  249. {"elf32-i386", {ELF::EM_386, false, true}},
  250. {"elf32-x86-64", {ELF::EM_X86_64, false, true}},
  251. {"elf64-x86-64", {ELF::EM_X86_64, true, true}},
  252. // Intel MCU
  253. {"elf32-iamcu", {ELF::EM_IAMCU, false, true}},
  254. // ARM
  255. {"elf32-littlearm", {ELF::EM_ARM, false, true}},
  256. // ARM AArch64
  257. {"elf64-aarch64", {ELF::EM_AARCH64, true, true}},
  258. {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}},
  259. // RISC-V
  260. {"elf32-littleriscv", {ELF::EM_RISCV, false, true}},
  261. {"elf64-littleriscv", {ELF::EM_RISCV, true, true}},
  262. // PowerPC
  263. {"elf32-powerpc", {ELF::EM_PPC, false, false}},
  264. {"elf32-powerpcle", {ELF::EM_PPC, false, true}},
  265. {"elf64-powerpc", {ELF::EM_PPC64, true, false}},
  266. {"elf64-powerpcle", {ELF::EM_PPC64, true, true}},
  267. // MIPS
  268. {"elf32-bigmips", {ELF::EM_MIPS, false, false}},
  269. {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}},
  270. {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}},
  271. {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}},
  272. {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}},
  273. {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}},
  274. {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}},
  275. // SPARC
  276. {"elf32-sparc", {ELF::EM_SPARC, false, false}},
  277. {"elf32-sparcel", {ELF::EM_SPARC, false, true}},
  278. {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}},
  279. };
  280. static Expected<TargetInfo>
  281. getOutputTargetInfoByTargetName(StringRef TargetName) {
  282. StringRef OriginalTargetName = TargetName;
  283. bool IsFreeBSD = TargetName.consume_back("-freebsd");
  284. auto Iter = TargetMap.find(TargetName);
  285. if (Iter == std::end(TargetMap))
  286. return createStringError(errc::invalid_argument,
  287. "invalid output format: '%s'",
  288. OriginalTargetName.str().c_str());
  289. MachineInfo MI = Iter->getValue();
  290. if (IsFreeBSD)
  291. MI.OSABI = ELF::ELFOSABI_FREEBSD;
  292. FileFormat Format;
  293. if (TargetName.startswith("elf"))
  294. Format = FileFormat::ELF;
  295. else
  296. // This should never happen because `TargetName` is valid (it certainly
  297. // exists in the TargetMap).
  298. llvm_unreachable("unknown target prefix");
  299. return {TargetInfo{Format, MI}};
  300. }
  301. static Error
  302. addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
  303. StringRef Filename, MatchStyle MS,
  304. llvm::function_ref<Error(Error)> ErrorCallback) {
  305. StringSaver Saver(Alloc);
  306. SmallVector<StringRef, 16> Lines;
  307. auto BufOrErr = MemoryBuffer::getFile(Filename);
  308. if (!BufOrErr)
  309. return createFileError(Filename, BufOrErr.getError());
  310. BufOrErr.get()->getBuffer().split(Lines, '\n');
  311. for (StringRef Line : Lines) {
  312. // Ignore everything after '#', trim whitespace, and only add the symbol if
  313. // it's not empty.
  314. auto TrimmedLine = Line.split('#').first.trim();
  315. if (!TrimmedLine.empty())
  316. if (Error E = Symbols.addMatcher(NameOrPattern::create(
  317. Saver.save(TrimmedLine), MS, ErrorCallback)))
  318. return E;
  319. }
  320. return Error::success();
  321. }
  322. Expected<NameOrPattern>
  323. NameOrPattern::create(StringRef Pattern, MatchStyle MS,
  324. llvm::function_ref<Error(Error)> ErrorCallback) {
  325. switch (MS) {
  326. case MatchStyle::Literal:
  327. return NameOrPattern(Pattern);
  328. case MatchStyle::Wildcard: {
  329. SmallVector<char, 32> Data;
  330. bool IsPositiveMatch = true;
  331. if (Pattern[0] == '!') {
  332. IsPositiveMatch = false;
  333. Pattern = Pattern.drop_front();
  334. }
  335. Expected<GlobPattern> GlobOrErr = GlobPattern::create(Pattern);
  336. // If we couldn't create it as a glob, report the error, but try again with
  337. // a literal if the error reporting is non-fatal.
  338. if (!GlobOrErr) {
  339. if (Error E = ErrorCallback(GlobOrErr.takeError()))
  340. return std::move(E);
  341. return create(Pattern, MatchStyle::Literal, ErrorCallback);
  342. }
  343. return NameOrPattern(std::make_shared<GlobPattern>(*GlobOrErr),
  344. IsPositiveMatch);
  345. }
  346. case MatchStyle::Regex: {
  347. SmallVector<char, 32> Data;
  348. return NameOrPattern(std::make_shared<Regex>(
  349. ("^" + Pattern.ltrim('^').rtrim('$') + "$").toStringRef(Data)));
  350. }
  351. }
  352. llvm_unreachable("Unhandled llvm.objcopy.MatchStyle enum");
  353. }
  354. static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
  355. BumpPtrAllocator &Alloc,
  356. StringRef Filename) {
  357. StringSaver Saver(Alloc);
  358. SmallVector<StringRef, 16> Lines;
  359. auto BufOrErr = MemoryBuffer::getFile(Filename);
  360. if (!BufOrErr)
  361. return createFileError(Filename, BufOrErr.getError());
  362. BufOrErr.get()->getBuffer().split(Lines, '\n');
  363. size_t NumLines = Lines.size();
  364. for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) {
  365. StringRef TrimmedLine = Lines[LineNo].split('#').first.trim();
  366. if (TrimmedLine.empty())
  367. continue;
  368. std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' ');
  369. StringRef NewName = Pair.second.trim();
  370. if (NewName.empty())
  371. return createStringError(errc::invalid_argument,
  372. "%s:%zu: missing new symbol name",
  373. Filename.str().c_str(), LineNo + 1);
  374. SymbolsToRename.insert({Pair.first, NewName});
  375. }
  376. return Error::success();
  377. }
  378. template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
  379. T Result;
  380. if (Val.getAsInteger(0, Result))
  381. return errc::invalid_argument;
  382. return Result;
  383. }
  384. namespace {
  385. enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip };
  386. } // anonymous namespace
  387. static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
  388. ToolType Tool) {
  389. StringRef HelpText, ToolName;
  390. switch (Tool) {
  391. case ToolType::Objcopy:
  392. ToolName = "llvm-objcopy";
  393. HelpText = " [options] input [output]";
  394. break;
  395. case ToolType::Strip:
  396. ToolName = "llvm-strip";
  397. HelpText = " [options] inputs...";
  398. break;
  399. case ToolType::InstallNameTool:
  400. ToolName = "llvm-install-name-tool";
  401. HelpText = " [options] input";
  402. break;
  403. case ToolType::BitcodeStrip:
  404. ToolName = "llvm-bitcode-strip";
  405. HelpText = " [options] input";
  406. break;
  407. }
  408. OptTable.PrintHelp(OS, (ToolName + HelpText).str().c_str(),
  409. (ToolName + " tool").str().c_str());
  410. // TODO: Replace this with libOption call once it adds extrahelp support.
  411. // The CommandLine library has a cl::extrahelp class to support this,
  412. // but libOption does not have that yet.
  413. OS << "\nPass @FILE as argument to read options from FILE.\n";
  414. }
  415. // ParseObjcopyOptions returns the config and sets the input arguments. If a
  416. // help flag is set then ParseObjcopyOptions will print the help messege and
  417. // exit.
  418. Expected<DriverConfig>
  419. parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
  420. llvm::function_ref<Error(Error)> ErrorCallback) {
  421. DriverConfig DC;
  422. ObjcopyOptTable T;
  423. unsigned MissingArgumentIndex, MissingArgumentCount;
  424. llvm::opt::InputArgList InputArgs =
  425. T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
  426. if (InputArgs.size() == 0) {
  427. printHelp(T, errs(), ToolType::Objcopy);
  428. exit(1);
  429. }
  430. if (InputArgs.hasArg(OBJCOPY_help)) {
  431. printHelp(T, outs(), ToolType::Objcopy);
  432. exit(0);
  433. }
  434. if (InputArgs.hasArg(OBJCOPY_version)) {
  435. outs() << "llvm-objcopy, compatible with GNU objcopy\n";
  436. cl::PrintVersionMessage();
  437. exit(0);
  438. }
  439. SmallVector<const char *, 2> Positional;
  440. for (auto Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
  441. return createStringError(errc::invalid_argument, "unknown argument '%s'",
  442. Arg->getAsString(InputArgs).c_str());
  443. for (auto Arg : InputArgs.filtered(OBJCOPY_INPUT))
  444. Positional.push_back(Arg->getValue());
  445. if (Positional.empty())
  446. return createStringError(errc::invalid_argument, "no input file specified");
  447. if (Positional.size() > 2)
  448. return createStringError(errc::invalid_argument,
  449. "too many positional arguments");
  450. CopyConfig Config;
  451. Config.InputFilename = Positional[0];
  452. Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
  453. if (InputArgs.hasArg(OBJCOPY_target) &&
  454. (InputArgs.hasArg(OBJCOPY_input_target) ||
  455. InputArgs.hasArg(OBJCOPY_output_target)))
  456. return createStringError(
  457. errc::invalid_argument,
  458. "--target cannot be used with --input-target or --output-target");
  459. if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
  460. return createStringError(errc::invalid_argument,
  461. "--regex and --wildcard are incompatible");
  462. MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
  463. ? MatchStyle::Regex
  464. : MatchStyle::Wildcard;
  465. MatchStyle SymbolMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
  466. ? MatchStyle::Regex
  467. : InputArgs.hasArg(OBJCOPY_wildcard)
  468. ? MatchStyle::Wildcard
  469. : MatchStyle::Literal;
  470. StringRef InputFormat, OutputFormat;
  471. if (InputArgs.hasArg(OBJCOPY_target)) {
  472. InputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
  473. OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
  474. } else {
  475. InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
  476. OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
  477. }
  478. // FIXME: Currently, we ignore the target for non-binary/ihex formats
  479. // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the
  480. // format by llvm::object::createBinary regardless of the option value.
  481. Config.InputFormat = StringSwitch<FileFormat>(InputFormat)
  482. .Case("binary", FileFormat::Binary)
  483. .Case("ihex", FileFormat::IHex)
  484. .Default(FileFormat::Unspecified);
  485. if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility))
  486. Config.NewSymbolVisibility =
  487. InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
  488. Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
  489. .Case("binary", FileFormat::Binary)
  490. .Case("ihex", FileFormat::IHex)
  491. .Default(FileFormat::Unspecified);
  492. if (Config.OutputFormat == FileFormat::Unspecified) {
  493. if (OutputFormat.empty()) {
  494. Config.OutputFormat = Config.InputFormat;
  495. } else {
  496. Expected<TargetInfo> Target =
  497. getOutputTargetInfoByTargetName(OutputFormat);
  498. if (!Target)
  499. return Target.takeError();
  500. Config.OutputFormat = Target->Format;
  501. Config.OutputArch = Target->Machine;
  502. }
  503. }
  504. if (auto Arg = InputArgs.getLastArg(OBJCOPY_compress_debug_sections,
  505. OBJCOPY_compress_debug_sections_eq)) {
  506. Config.CompressionType = DebugCompressionType::Z;
  507. if (Arg->getOption().getID() == OBJCOPY_compress_debug_sections_eq) {
  508. Config.CompressionType =
  509. StringSwitch<DebugCompressionType>(
  510. InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq))
  511. .Case("zlib-gnu", DebugCompressionType::GNU)
  512. .Case("zlib", DebugCompressionType::Z)
  513. .Default(DebugCompressionType::None);
  514. if (Config.CompressionType == DebugCompressionType::None)
  515. return createStringError(
  516. errc::invalid_argument,
  517. "invalid or unsupported --compress-debug-sections format: %s",
  518. InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq)
  519. .str()
  520. .c_str());
  521. }
  522. if (!zlib::isAvailable())
  523. return createStringError(
  524. errc::invalid_argument,
  525. "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress");
  526. }
  527. Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
  528. // The gnu_debuglink's target is expected to not change or else its CRC would
  529. // become invalidated and get rejected. We can avoid recalculating the
  530. // checksum for every target file inside an archive by precomputing the CRC
  531. // here. This prevents a significant amount of I/O.
  532. if (!Config.AddGnuDebugLink.empty()) {
  533. auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink);
  534. if (!DebugOrErr)
  535. return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());
  536. auto Debug = std::move(*DebugOrErr);
  537. Config.GnuDebugLinkCRC32 =
  538. llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
  539. }
  540. Config.BuildIdLinkDir = InputArgs.getLastArgValue(OBJCOPY_build_id_link_dir);
  541. if (InputArgs.hasArg(OBJCOPY_build_id_link_input))
  542. Config.BuildIdLinkInput =
  543. InputArgs.getLastArgValue(OBJCOPY_build_id_link_input);
  544. if (InputArgs.hasArg(OBJCOPY_build_id_link_output))
  545. Config.BuildIdLinkOutput =
  546. InputArgs.getLastArgValue(OBJCOPY_build_id_link_output);
  547. Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
  548. Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
  549. Config.AllocSectionsPrefix =
  550. InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
  551. if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
  552. Config.ExtractPartition = Arg->getValue();
  553. for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
  554. if (!StringRef(Arg->getValue()).contains('='))
  555. return createStringError(errc::invalid_argument,
  556. "bad format for --redefine-sym");
  557. auto Old2New = StringRef(Arg->getValue()).split('=');
  558. if (!Config.SymbolsToRename.insert(Old2New).second)
  559. return createStringError(errc::invalid_argument,
  560. "multiple redefinition of symbol '%s'",
  561. Old2New.first.str().c_str());
  562. }
  563. for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
  564. if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
  565. Arg->getValue()))
  566. return std::move(E);
  567. for (auto Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
  568. Expected<SectionRename> SR =
  569. parseRenameSectionValue(StringRef(Arg->getValue()));
  570. if (!SR)
  571. return SR.takeError();
  572. if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
  573. return createStringError(errc::invalid_argument,
  574. "multiple renames of section '%s'",
  575. SR->OriginalName.str().c_str());
  576. }
  577. for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
  578. Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
  579. parseSetSectionAlignment(Arg->getValue());
  580. if (!NameAndAlign)
  581. return NameAndAlign.takeError();
  582. Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
  583. }
  584. for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
  585. Expected<SectionFlagsUpdate> SFU =
  586. parseSetSectionFlagValue(Arg->getValue());
  587. if (!SFU)
  588. return SFU.takeError();
  589. if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
  590. return createStringError(
  591. errc::invalid_argument,
  592. "--set-section-flags set multiple times for section '%s'",
  593. SFU->Name.str().c_str());
  594. }
  595. // Prohibit combinations of --set-section-flags when the section name is used
  596. // by --rename-section, either as a source or a destination.
  597. for (const auto &E : Config.SectionsToRename) {
  598. const SectionRename &SR = E.second;
  599. if (Config.SetSectionFlags.count(SR.OriginalName))
  600. return createStringError(
  601. errc::invalid_argument,
  602. "--set-section-flags=%s conflicts with --rename-section=%s=%s",
  603. SR.OriginalName.str().c_str(), SR.OriginalName.str().c_str(),
  604. SR.NewName.str().c_str());
  605. if (Config.SetSectionFlags.count(SR.NewName))
  606. return createStringError(
  607. errc::invalid_argument,
  608. "--set-section-flags=%s conflicts with --rename-section=%s=%s",
  609. SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
  610. SR.NewName.str().c_str());
  611. }
  612. for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section))
  613. if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
  614. Arg->getValue(), SectionMatchStyle, ErrorCallback)))
  615. return std::move(E);
  616. for (auto Arg : InputArgs.filtered(OBJCOPY_keep_section))
  617. if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
  618. Arg->getValue(), SectionMatchStyle, ErrorCallback)))
  619. return std::move(E);
  620. for (auto Arg : InputArgs.filtered(OBJCOPY_only_section))
  621. if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
  622. Arg->getValue(), SectionMatchStyle, ErrorCallback)))
  623. return std::move(E);
  624. for (auto Arg : InputArgs.filtered(OBJCOPY_add_section)) {
  625. StringRef ArgValue(Arg->getValue());
  626. if (!ArgValue.contains('='))
  627. return createStringError(errc::invalid_argument,
  628. "bad format for --add-section: missing '='");
  629. if (ArgValue.split("=").second.empty())
  630. return createStringError(
  631. errc::invalid_argument,
  632. "bad format for --add-section: missing file name");
  633. Config.AddSection.push_back(ArgValue);
  634. }
  635. for (auto Arg : InputArgs.filtered(OBJCOPY_dump_section))
  636. Config.DumpSection.push_back(Arg->getValue());
  637. Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
  638. Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
  639. Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
  640. Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
  641. Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
  642. Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
  643. Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
  644. Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
  645. Config.ExtractMainPartition =
  646. InputArgs.hasArg(OBJCOPY_extract_main_partition);
  647. Config.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
  648. Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
  649. if (InputArgs.hasArg(OBJCOPY_discard_all, OBJCOPY_discard_locals))
  650. Config.DiscardMode =
  651. InputArgs.hasFlag(OBJCOPY_discard_all, OBJCOPY_discard_locals)
  652. ? DiscardType::All
  653. : DiscardType::Locals;
  654. Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
  655. Config.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
  656. Config.DecompressDebugSections =
  657. InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
  658. if (Config.DiscardMode == DiscardType::All) {
  659. Config.StripDebug = true;
  660. Config.KeepFileSymbols = true;
  661. }
  662. for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
  663. if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
  664. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  665. return std::move(E);
  666. for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
  667. if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
  668. Arg->getValue(), SymbolMatchStyle,
  669. ErrorCallback))
  670. return std::move(E);
  671. for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
  672. if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
  673. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  674. return std::move(E);
  675. for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
  676. if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
  677. Arg->getValue(), SymbolMatchStyle,
  678. ErrorCallback))
  679. return std::move(E);
  680. for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
  681. if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
  682. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  683. return std::move(E);
  684. for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
  685. if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
  686. Arg->getValue(), SymbolMatchStyle,
  687. ErrorCallback))
  688. return std::move(E);
  689. for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
  690. if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
  691. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  692. return std::move(E);
  693. for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
  694. if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
  695. Arg->getValue(), SymbolMatchStyle,
  696. ErrorCallback))
  697. return std::move(E);
  698. for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
  699. if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
  700. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  701. return std::move(E);
  702. for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
  703. if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
  704. Arg->getValue(), SymbolMatchStyle,
  705. ErrorCallback))
  706. return std::move(E);
  707. for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
  708. if (Error E =
  709. Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
  710. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  711. return std::move(E);
  712. for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
  713. if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
  714. Arg->getValue(), SymbolMatchStyle,
  715. ErrorCallback))
  716. return std::move(E);
  717. for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
  718. if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
  719. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  720. return std::move(E);
  721. for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
  722. if (Error E =
  723. addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
  724. SymbolMatchStyle, ErrorCallback))
  725. return std::move(E);
  726. for (auto Arg : InputArgs.filtered(OBJCOPY_add_symbol))
  727. Config.SymbolsToAdd.push_back(Arg->getValue());
  728. Config.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
  729. Config.DeterministicArchives = InputArgs.hasFlag(
  730. OBJCOPY_enable_deterministic_archives,
  731. OBJCOPY_disable_deterministic_archives, /*default=*/true);
  732. Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
  733. if (Config.PreserveDates &&
  734. (Config.OutputFilename == "-" || Config.InputFilename == "-"))
  735. return createStringError(errc::invalid_argument,
  736. "--preserve-dates requires a file");
  737. for (auto Arg : InputArgs)
  738. if (Arg->getOption().matches(OBJCOPY_set_start)) {
  739. auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
  740. if (!EAddr)
  741. return createStringError(
  742. EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
  743. Config.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
  744. } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
  745. auto EIncr = getAsInteger<int64_t>(Arg->getValue());
  746. if (!EIncr)
  747. return createStringError(EIncr.getError(),
  748. "bad entry point increment: '%s'",
  749. Arg->getValue());
  750. auto Expr = Config.EntryExpr ? std::move(Config.EntryExpr)
  751. : [](uint64_t A) { return A; };
  752. Config.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
  753. return Expr(EAddr) + *EIncr;
  754. };
  755. }
  756. if (Config.DecompressDebugSections &&
  757. Config.CompressionType != DebugCompressionType::None) {
  758. return createStringError(
  759. errc::invalid_argument,
  760. "cannot specify both --compress-debug-sections and "
  761. "--decompress-debug-sections");
  762. }
  763. if (Config.DecompressDebugSections && !zlib::isAvailable())
  764. return createStringError(
  765. errc::invalid_argument,
  766. "LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress");
  767. if (Config.ExtractPartition && Config.ExtractMainPartition)
  768. return createStringError(errc::invalid_argument,
  769. "cannot specify --extract-partition together with "
  770. "--extract-main-partition");
  771. DC.CopyConfigs.push_back(std::move(Config));
  772. return std::move(DC);
  773. }
  774. // ParseInstallNameToolOptions returns the config and sets the input arguments.
  775. // If a help flag is set then ParseInstallNameToolOptions will print the help
  776. // messege and exit.
  777. Expected<DriverConfig>
  778. parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
  779. DriverConfig DC;
  780. CopyConfig Config;
  781. InstallNameToolOptTable T;
  782. unsigned MissingArgumentIndex, MissingArgumentCount;
  783. llvm::opt::InputArgList InputArgs =
  784. T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
  785. if (MissingArgumentCount)
  786. return createStringError(
  787. errc::invalid_argument,
  788. "missing argument to " +
  789. StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
  790. " option");
  791. if (InputArgs.size() == 0) {
  792. printHelp(T, errs(), ToolType::InstallNameTool);
  793. exit(1);
  794. }
  795. if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
  796. printHelp(T, outs(), ToolType::InstallNameTool);
  797. exit(0);
  798. }
  799. if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
  800. outs() << "llvm-install-name-tool, compatible with cctools "
  801. "install_name_tool\n";
  802. cl::PrintVersionMessage();
  803. exit(0);
  804. }
  805. for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
  806. Config.RPathToAdd.push_back(Arg->getValue());
  807. for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
  808. Config.RPathToPrepend.push_back(Arg->getValue());
  809. for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
  810. StringRef RPath = Arg->getValue();
  811. // Cannot add and delete the same rpath at the same time.
  812. if (is_contained(Config.RPathToAdd, RPath))
  813. return createStringError(
  814. errc::invalid_argument,
  815. "cannot specify both -add_rpath '%s' and -delete_rpath '%s'",
  816. RPath.str().c_str(), RPath.str().c_str());
  817. if (is_contained(Config.RPathToPrepend, RPath))
  818. return createStringError(
  819. errc::invalid_argument,
  820. "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'",
  821. RPath.str().c_str(), RPath.str().c_str());
  822. Config.RPathsToRemove.insert(RPath);
  823. }
  824. for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) {
  825. StringRef Old = Arg->getValue(0);
  826. StringRef New = Arg->getValue(1);
  827. auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; };
  828. // Cannot specify duplicate -rpath entries
  829. auto It1 = find_if(
  830. Config.RPathsToUpdate,
  831. [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) {
  832. return Match(OldNew.getFirst()) || Match(OldNew.getSecond());
  833. });
  834. if (It1 != Config.RPathsToUpdate.end())
  835. return createStringError(errc::invalid_argument,
  836. "cannot specify both -rpath '" +
  837. It1->getFirst() + "' '" + It1->getSecond() +
  838. "' and -rpath '" + Old + "' '" + New + "'");
  839. // Cannot specify the same rpath under both -delete_rpath and -rpath
  840. auto It2 = find_if(Config.RPathsToRemove, Match);
  841. if (It2 != Config.RPathsToRemove.end())
  842. return createStringError(errc::invalid_argument,
  843. "cannot specify both -delete_rpath '" + *It2 +
  844. "' and -rpath '" + Old + "' '" + New + "'");
  845. // Cannot specify the same rpath under both -add_rpath and -rpath
  846. auto It3 = find_if(Config.RPathToAdd, Match);
  847. if (It3 != Config.RPathToAdd.end())
  848. return createStringError(errc::invalid_argument,
  849. "cannot specify both -add_rpath '" + *It3 +
  850. "' and -rpath '" + Old + "' '" + New + "'");
  851. // Cannot specify the same rpath under both -prepend_rpath and -rpath.
  852. auto It4 = find_if(Config.RPathToPrepend, Match);
  853. if (It4 != Config.RPathToPrepend.end())
  854. return createStringError(errc::invalid_argument,
  855. "cannot specify both -prepend_rpath '" + *It4 +
  856. "' and -rpath '" + Old + "' '" + New + "'");
  857. Config.RPathsToUpdate.insert({Old, New});
  858. }
  859. if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) {
  860. Config.SharedLibId = Arg->getValue();
  861. if (Config.SharedLibId->empty())
  862. return createStringError(errc::invalid_argument,
  863. "cannot specify an empty id");
  864. }
  865. for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change))
  866. Config.InstallNamesToUpdate.insert({Arg->getValue(0), Arg->getValue(1)});
  867. Config.RemoveAllRpaths =
  868. InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);
  869. SmallVector<StringRef, 2> Positional;
  870. for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
  871. return createStringError(errc::invalid_argument, "unknown argument '%s'",
  872. Arg->getAsString(InputArgs).c_str());
  873. for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
  874. Positional.push_back(Arg->getValue());
  875. if (Positional.empty())
  876. return createStringError(errc::invalid_argument, "no input file specified");
  877. if (Positional.size() > 1)
  878. return createStringError(
  879. errc::invalid_argument,
  880. "llvm-install-name-tool expects a single input file");
  881. Config.InputFilename = Positional[0];
  882. Config.OutputFilename = Positional[0];
  883. DC.CopyConfigs.push_back(std::move(Config));
  884. return std::move(DC);
  885. }
  886. Expected<DriverConfig>
  887. parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr) {
  888. DriverConfig DC;
  889. CopyConfig Config;
  890. BitcodeStripOptTable T;
  891. unsigned MissingArgumentIndex, MissingArgumentCount;
  892. opt::InputArgList InputArgs =
  893. T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
  894. if (InputArgs.size() == 0) {
  895. printHelp(T, errs(), ToolType::BitcodeStrip);
  896. exit(1);
  897. }
  898. if (InputArgs.hasArg(BITCODE_STRIP_help)) {
  899. printHelp(T, outs(), ToolType::BitcodeStrip);
  900. exit(0);
  901. }
  902. if (InputArgs.hasArg(BITCODE_STRIP_version)) {
  903. outs() << "llvm-bitcode-strip, compatible with cctools "
  904. "bitcode_strip\n";
  905. cl::PrintVersionMessage();
  906. exit(0);
  907. }
  908. for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN))
  909. return createStringError(errc::invalid_argument, "unknown argument '%s'",
  910. Arg->getAsString(InputArgs).c_str());
  911. SmallVector<StringRef, 2> Positional;
  912. for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
  913. Positional.push_back(Arg->getValue());
  914. if (Positional.size() > 1)
  915. return createStringError(errc::invalid_argument,
  916. "llvm-bitcode-strip expects a single input file");
  917. assert(!Positional.empty());
  918. Config.InputFilename = Positional[0];
  919. Config.OutputFilename = Positional[0];
  920. DC.CopyConfigs.push_back(std::move(Config));
  921. return std::move(DC);
  922. }
  923. // ParseStripOptions returns the config and sets the input arguments. If a
  924. // help flag is set then ParseStripOptions will print the help messege and
  925. // exit.
  926. Expected<DriverConfig>
  927. parseStripOptions(ArrayRef<const char *> ArgsArr,
  928. llvm::function_ref<Error(Error)> ErrorCallback) {
  929. StripOptTable T;
  930. unsigned MissingArgumentIndex, MissingArgumentCount;
  931. llvm::opt::InputArgList InputArgs =
  932. T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
  933. if (InputArgs.size() == 0) {
  934. printHelp(T, errs(), ToolType::Strip);
  935. exit(1);
  936. }
  937. if (InputArgs.hasArg(STRIP_help)) {
  938. printHelp(T, outs(), ToolType::Strip);
  939. exit(0);
  940. }
  941. if (InputArgs.hasArg(STRIP_version)) {
  942. outs() << "llvm-strip, compatible with GNU strip\n";
  943. cl::PrintVersionMessage();
  944. exit(0);
  945. }
  946. SmallVector<StringRef, 2> Positional;
  947. for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN))
  948. return createStringError(errc::invalid_argument, "unknown argument '%s'",
  949. Arg->getAsString(InputArgs).c_str());
  950. for (auto Arg : InputArgs.filtered(STRIP_INPUT))
  951. Positional.push_back(Arg->getValue());
  952. if (Positional.empty())
  953. return createStringError(errc::invalid_argument, "no input file specified");
  954. if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
  955. return createStringError(
  956. errc::invalid_argument,
  957. "multiple input files cannot be used in combination with -o");
  958. CopyConfig Config;
  959. if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
  960. return createStringError(errc::invalid_argument,
  961. "--regex and --wildcard are incompatible");
  962. MatchStyle SectionMatchStyle =
  963. InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
  964. MatchStyle SymbolMatchStyle = InputArgs.hasArg(STRIP_regex)
  965. ? MatchStyle::Regex
  966. : InputArgs.hasArg(STRIP_wildcard)
  967. ? MatchStyle::Wildcard
  968. : MatchStyle::Literal;
  969. Config.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
  970. Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
  971. if (InputArgs.hasArg(STRIP_discard_all, STRIP_discard_locals))
  972. Config.DiscardMode =
  973. InputArgs.hasFlag(STRIP_discard_all, STRIP_discard_locals)
  974. ? DiscardType::All
  975. : DiscardType::Locals;
  976. Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
  977. Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
  978. if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
  979. Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
  980. Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
  981. Config.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
  982. Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
  983. Config.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
  984. for (auto Arg : InputArgs.filtered(STRIP_keep_section))
  985. if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
  986. Arg->getValue(), SectionMatchStyle, ErrorCallback)))
  987. return std::move(E);
  988. for (auto Arg : InputArgs.filtered(STRIP_remove_section))
  989. if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
  990. Arg->getValue(), SectionMatchStyle, ErrorCallback)))
  991. return std::move(E);
  992. for (auto Arg : InputArgs.filtered(STRIP_strip_symbol))
  993. if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
  994. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  995. return std::move(E);
  996. for (auto Arg : InputArgs.filtered(STRIP_keep_symbol))
  997. if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
  998. Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
  999. return std::move(E);
  1000. if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
  1001. !Config.StripUnneeded && Config.DiscardMode == DiscardType::None &&
  1002. !Config.StripAllGNU && Config.SymbolsToRemove.empty())
  1003. Config.StripAll = true;
  1004. if (Config.DiscardMode == DiscardType::All) {
  1005. Config.StripDebug = true;
  1006. Config.KeepFileSymbols = true;
  1007. }
  1008. Config.DeterministicArchives =
  1009. InputArgs.hasFlag(STRIP_enable_deterministic_archives,
  1010. STRIP_disable_deterministic_archives, /*default=*/true);
  1011. Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
  1012. Config.InputFormat = FileFormat::Unspecified;
  1013. Config.OutputFormat = FileFormat::Unspecified;
  1014. DriverConfig DC;
  1015. if (Positional.size() == 1) {
  1016. Config.InputFilename = Positional[0];
  1017. Config.OutputFilename =
  1018. InputArgs.getLastArgValue(STRIP_output, Positional[0]);
  1019. DC.CopyConfigs.push_back(std::move(Config));
  1020. } else {
  1021. StringMap<unsigned> InputFiles;
  1022. for (StringRef Filename : Positional) {
  1023. if (InputFiles[Filename]++ == 1) {
  1024. if (Filename == "-")
  1025. return createStringError(
  1026. errc::invalid_argument,
  1027. "cannot specify '-' as an input file more than once");
  1028. if (Error E = ErrorCallback(createStringError(
  1029. errc::invalid_argument, "'%s' was already specified",
  1030. Filename.str().c_str())))
  1031. return std::move(E);
  1032. }
  1033. Config.InputFilename = Filename;
  1034. Config.OutputFilename = Filename;
  1035. DC.CopyConfigs.push_back(Config);
  1036. }
  1037. }
  1038. if (Config.PreserveDates && (is_contained(Positional, "-") ||
  1039. InputArgs.getLastArgValue(STRIP_output) == "-"))
  1040. return createStringError(errc::invalid_argument,
  1041. "--preserve-dates requires a file");
  1042. return std::move(DC);
  1043. }
  1044. } // namespace objcopy
  1045. } // namespace llvm