xref: /llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp (revision 10772807ab72ce2b68d76816f8753219b2acbac3)
1f75da0c8SAlexey Lapshin //===- ObjcopyOptions.cpp -------------------------------------------------===//
2f75da0c8SAlexey Lapshin //
3f75da0c8SAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f75da0c8SAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information.
5f75da0c8SAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f75da0c8SAlexey Lapshin //
7f75da0c8SAlexey Lapshin //===----------------------------------------------------------------------===//
8f75da0c8SAlexey Lapshin 
9f75da0c8SAlexey Lapshin #include "ObjcopyOptions.h"
10f75da0c8SAlexey Lapshin #include "llvm/ADT/SmallVector.h"
11b0abd489SElliot Goodrich #include "llvm/ADT/StringExtras.h"
12f75da0c8SAlexey Lapshin #include "llvm/ADT/StringRef.h"
130d98582cSFangrui Song #include "llvm/ADT/StringSwitch.h"
14f75da0c8SAlexey Lapshin #include "llvm/BinaryFormat/COFF.h"
1594fba14fSRichard Howell #include "llvm/ObjCopy/CommonConfig.h"
16f75da0c8SAlexey Lapshin #include "llvm/ObjCopy/ConfigManager.h"
1759172194SRichard Howell #include "llvm/ObjCopy/MachO/MachOConfig.h"
18fa535452SKeith Smiley #include "llvm/Object/Binary.h"
19f75da0c8SAlexey Lapshin #include "llvm/Option/Arg.h"
20f75da0c8SAlexey Lapshin #include "llvm/Option/ArgList.h"
21f75da0c8SAlexey Lapshin #include "llvm/Support/CRC.h"
22f75da0c8SAlexey Lapshin #include "llvm/Support/CommandLine.h"
23f75da0c8SAlexey Lapshin #include "llvm/Support/Compression.h"
24f75da0c8SAlexey Lapshin #include "llvm/Support/Errc.h"
25f75da0c8SAlexey Lapshin #include "llvm/Support/Error.h"
26f75da0c8SAlexey Lapshin #include "llvm/Support/MemoryBuffer.h"
27f75da0c8SAlexey Lapshin 
28f75da0c8SAlexey Lapshin using namespace llvm;
29f75da0c8SAlexey Lapshin using namespace llvm::objcopy;
30fa535452SKeith Smiley using namespace llvm::object;
31dcb6d212SJustin Bogner using namespace llvm::opt;
32f75da0c8SAlexey Lapshin 
33f75da0c8SAlexey Lapshin namespace {
34f75da0c8SAlexey Lapshin enum ObjcopyID {
35f75da0c8SAlexey Lapshin   OBJCOPY_INVALID = 0, // This is not an option ID.
363f092f37SJan Svoboda #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
37f75da0c8SAlexey Lapshin #include "ObjcopyOpts.inc"
38f75da0c8SAlexey Lapshin #undef OPTION
39f75da0c8SAlexey Lapshin };
40f75da0c8SAlexey Lapshin 
41d9ab3e82Sserge-sans-paille namespace objcopy_opt {
42dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE
43f75da0c8SAlexey Lapshin #include "ObjcopyOpts.inc"
44dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE
45dd647e3eSChandler Carruth 
46dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE
47dd647e3eSChandler Carruth #include "ObjcopyOpts.inc"
48dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE
49f75da0c8SAlexey Lapshin 
5007d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info ObjcopyInfoTable[] = {
513f092f37SJan Svoboda #define OPTION(...)                                                            \
523f092f37SJan Svoboda   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
53f75da0c8SAlexey Lapshin #include "ObjcopyOpts.inc"
54f75da0c8SAlexey Lapshin #undef OPTION
55f75da0c8SAlexey Lapshin };
56d9ab3e82Sserge-sans-paille } // namespace objcopy_opt
57f75da0c8SAlexey Lapshin 
5807bb29d8Sserge-sans-paille class ObjcopyOptTable : public opt::GenericOptTable {
59f75da0c8SAlexey Lapshin public:
60dd647e3eSChandler Carruth   ObjcopyOptTable()
61dd647e3eSChandler Carruth       : opt::GenericOptTable(objcopy_opt::OptionStrTable,
62dd647e3eSChandler Carruth                              objcopy_opt::OptionPrefixesTable,
63dd647e3eSChandler Carruth                              objcopy_opt::ObjcopyInfoTable) {
64f75da0c8SAlexey Lapshin     setGroupedShortOptions(true);
652444b6f0SFangrui Song     setDashDashParsing(true);
66f75da0c8SAlexey Lapshin   }
67f75da0c8SAlexey Lapshin };
68f75da0c8SAlexey Lapshin 
69f75da0c8SAlexey Lapshin enum InstallNameToolID {
70f75da0c8SAlexey Lapshin   INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
713f092f37SJan Svoboda #define OPTION(...)                                                            \
723f092f37SJan Svoboda   LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
73f75da0c8SAlexey Lapshin #include "InstallNameToolOpts.inc"
74f75da0c8SAlexey Lapshin #undef OPTION
75f75da0c8SAlexey Lapshin };
76f75da0c8SAlexey Lapshin 
77d9ab3e82Sserge-sans-paille namespace install_name_tool {
78dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE
79f75da0c8SAlexey Lapshin #include "InstallNameToolOpts.inc"
80dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE
81dd647e3eSChandler Carruth 
82dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE
83dd647e3eSChandler Carruth #include "InstallNameToolOpts.inc"
84dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE
85f75da0c8SAlexey Lapshin 
8607d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = {
873f092f37SJan Svoboda #define OPTION(...)                                                            \
883f092f37SJan Svoboda   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
89f75da0c8SAlexey Lapshin #include "InstallNameToolOpts.inc"
90f75da0c8SAlexey Lapshin #undef OPTION
91f75da0c8SAlexey Lapshin };
92d9ab3e82Sserge-sans-paille } // namespace install_name_tool
93f75da0c8SAlexey Lapshin 
9407bb29d8Sserge-sans-paille class InstallNameToolOptTable : public opt::GenericOptTable {
95f75da0c8SAlexey Lapshin public:
96d9ab3e82Sserge-sans-paille   InstallNameToolOptTable()
97dd647e3eSChandler Carruth       : GenericOptTable(install_name_tool::OptionStrTable,
98dd647e3eSChandler Carruth                         install_name_tool::OptionPrefixesTable,
99dd647e3eSChandler Carruth                         install_name_tool::InstallNameToolInfoTable) {}
100f75da0c8SAlexey Lapshin };
101f75da0c8SAlexey Lapshin 
102f75da0c8SAlexey Lapshin enum BitcodeStripID {
103f75da0c8SAlexey Lapshin   BITCODE_STRIP_INVALID = 0, // This is not an option ID.
1043f092f37SJan Svoboda #define OPTION(...)                                                            \
1053f092f37SJan Svoboda   LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
106f75da0c8SAlexey Lapshin #include "BitcodeStripOpts.inc"
107f75da0c8SAlexey Lapshin #undef OPTION
108f75da0c8SAlexey Lapshin };
109f75da0c8SAlexey Lapshin 
110d9ab3e82Sserge-sans-paille namespace bitcode_strip {
111dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE
112f75da0c8SAlexey Lapshin #include "BitcodeStripOpts.inc"
113dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE
114dd647e3eSChandler Carruth 
115dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE
116dd647e3eSChandler Carruth #include "BitcodeStripOpts.inc"
117dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE
118f75da0c8SAlexey Lapshin 
11907d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = {
1203f092f37SJan Svoboda #define OPTION(...)                                                            \
1213f092f37SJan Svoboda   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
122f75da0c8SAlexey Lapshin #include "BitcodeStripOpts.inc"
123f75da0c8SAlexey Lapshin #undef OPTION
124f75da0c8SAlexey Lapshin };
125d9ab3e82Sserge-sans-paille } // namespace bitcode_strip
126f75da0c8SAlexey Lapshin 
12707bb29d8Sserge-sans-paille class BitcodeStripOptTable : public opt::GenericOptTable {
128f75da0c8SAlexey Lapshin public:
12907bb29d8Sserge-sans-paille   BitcodeStripOptTable()
130dd647e3eSChandler Carruth       : opt::GenericOptTable(bitcode_strip::OptionStrTable,
131dd647e3eSChandler Carruth                              bitcode_strip::OptionPrefixesTable,
132dd647e3eSChandler Carruth                              bitcode_strip::BitcodeStripInfoTable) {}
133f75da0c8SAlexey Lapshin };
134f75da0c8SAlexey Lapshin 
135f75da0c8SAlexey Lapshin enum StripID {
136f75da0c8SAlexey Lapshin   STRIP_INVALID = 0, // This is not an option ID.
1373f092f37SJan Svoboda #define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
138f75da0c8SAlexey Lapshin #include "StripOpts.inc"
139f75da0c8SAlexey Lapshin #undef OPTION
140f75da0c8SAlexey Lapshin };
141f75da0c8SAlexey Lapshin 
142d9ab3e82Sserge-sans-paille namespace strip {
143dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE
144f75da0c8SAlexey Lapshin #include "StripOpts.inc"
145dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE
146dd647e3eSChandler Carruth 
147dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE
148dd647e3eSChandler Carruth #include "StripOpts.inc"
149dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE
150f75da0c8SAlexey Lapshin 
15107d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info StripInfoTable[] = {
1523f092f37SJan Svoboda #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
153f75da0c8SAlexey Lapshin #include "StripOpts.inc"
154f75da0c8SAlexey Lapshin #undef OPTION
155f75da0c8SAlexey Lapshin };
156d9ab3e82Sserge-sans-paille } // namespace strip
157f75da0c8SAlexey Lapshin 
15807bb29d8Sserge-sans-paille class StripOptTable : public opt::GenericOptTable {
159f75da0c8SAlexey Lapshin public:
160dd647e3eSChandler Carruth   StripOptTable()
161dd647e3eSChandler Carruth       : GenericOptTable(strip::OptionStrTable, strip::OptionPrefixesTable,
162dd647e3eSChandler Carruth                         strip::StripInfoTable) {
163d9ab3e82Sserge-sans-paille     setGroupedShortOptions(true);
164d9ab3e82Sserge-sans-paille   }
165f75da0c8SAlexey Lapshin };
166f75da0c8SAlexey Lapshin 
167f75da0c8SAlexey Lapshin } // namespace
168f75da0c8SAlexey Lapshin 
169f75da0c8SAlexey Lapshin static SectionFlag parseSectionRenameFlag(StringRef SectionName) {
170f75da0c8SAlexey Lapshin   return llvm::StringSwitch<SectionFlag>(SectionName)
171f75da0c8SAlexey Lapshin       .CaseLower("alloc", SectionFlag::SecAlloc)
172f75da0c8SAlexey Lapshin       .CaseLower("load", SectionFlag::SecLoad)
173f75da0c8SAlexey Lapshin       .CaseLower("noload", SectionFlag::SecNoload)
174f75da0c8SAlexey Lapshin       .CaseLower("readonly", SectionFlag::SecReadonly)
175f75da0c8SAlexey Lapshin       .CaseLower("debug", SectionFlag::SecDebug)
176f75da0c8SAlexey Lapshin       .CaseLower("code", SectionFlag::SecCode)
177f75da0c8SAlexey Lapshin       .CaseLower("data", SectionFlag::SecData)
178f75da0c8SAlexey Lapshin       .CaseLower("rom", SectionFlag::SecRom)
179f75da0c8SAlexey Lapshin       .CaseLower("merge", SectionFlag::SecMerge)
180f75da0c8SAlexey Lapshin       .CaseLower("strings", SectionFlag::SecStrings)
181f75da0c8SAlexey Lapshin       .CaseLower("contents", SectionFlag::SecContents)
182f75da0c8SAlexey Lapshin       .CaseLower("share", SectionFlag::SecShare)
183f75da0c8SAlexey Lapshin       .CaseLower("exclude", SectionFlag::SecExclude)
1846f1395a1SThomas Köppe       .CaseLower("large", SectionFlag::SecLarge)
185f75da0c8SAlexey Lapshin       .Default(SectionFlag::SecNone);
186f75da0c8SAlexey Lapshin }
187f75da0c8SAlexey Lapshin 
188f75da0c8SAlexey Lapshin static Expected<SectionFlag>
189f75da0c8SAlexey Lapshin parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
190f75da0c8SAlexey Lapshin   SectionFlag ParsedFlags = SectionFlag::SecNone;
191f75da0c8SAlexey Lapshin   for (StringRef Flag : SectionFlags) {
192f75da0c8SAlexey Lapshin     SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
193f75da0c8SAlexey Lapshin     if (ParsedFlag == SectionFlag::SecNone)
194f75da0c8SAlexey Lapshin       return createStringError(
195f75da0c8SAlexey Lapshin           errc::invalid_argument,
196f75da0c8SAlexey Lapshin           "unrecognized section flag '%s'. Flags supported for GNU "
197f75da0c8SAlexey Lapshin           "compatibility: alloc, load, noload, readonly, exclude, debug, "
1986f1395a1SThomas Köppe           "code, data, rom, share, contents, merge, strings, large",
199f75da0c8SAlexey Lapshin           Flag.str().c_str());
200f75da0c8SAlexey Lapshin     ParsedFlags |= ParsedFlag;
201f75da0c8SAlexey Lapshin   }
202f75da0c8SAlexey Lapshin 
203f75da0c8SAlexey Lapshin   return ParsedFlags;
204f75da0c8SAlexey Lapshin }
205f75da0c8SAlexey Lapshin 
206f75da0c8SAlexey Lapshin static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {
207f75da0c8SAlexey Lapshin   if (!FlagValue.contains('='))
208f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
209f75da0c8SAlexey Lapshin                              "bad format for --rename-section: missing '='");
210f75da0c8SAlexey Lapshin 
211f75da0c8SAlexey Lapshin   // Initial split: ".foo" = ".bar,f1,f2,..."
212f75da0c8SAlexey Lapshin   auto Old2New = FlagValue.split('=');
213f75da0c8SAlexey Lapshin   SectionRename SR;
214f75da0c8SAlexey Lapshin   SR.OriginalName = Old2New.first;
215f75da0c8SAlexey Lapshin 
216f75da0c8SAlexey Lapshin   // Flags split: ".bar" "f1" "f2" ...
217f75da0c8SAlexey Lapshin   SmallVector<StringRef, 6> NameAndFlags;
218f75da0c8SAlexey Lapshin   Old2New.second.split(NameAndFlags, ',');
219f75da0c8SAlexey Lapshin   SR.NewName = NameAndFlags[0];
220f75da0c8SAlexey Lapshin 
221f75da0c8SAlexey Lapshin   if (NameAndFlags.size() > 1) {
222f75da0c8SAlexey Lapshin     Expected<SectionFlag> ParsedFlagSet =
22338818b60Sserge-sans-paille         parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front());
224f75da0c8SAlexey Lapshin     if (!ParsedFlagSet)
225f75da0c8SAlexey Lapshin       return ParsedFlagSet.takeError();
226f75da0c8SAlexey Lapshin     SR.NewFlags = *ParsedFlagSet;
227f75da0c8SAlexey Lapshin   }
228f75da0c8SAlexey Lapshin 
229f75da0c8SAlexey Lapshin   return SR;
230f75da0c8SAlexey Lapshin }
231f75da0c8SAlexey Lapshin 
232f75da0c8SAlexey Lapshin static Expected<std::pair<StringRef, uint64_t>>
233b28412d5SFangrui Song parseSetSectionAttribute(StringRef Option, StringRef FlagValue) {
234f75da0c8SAlexey Lapshin   if (!FlagValue.contains('='))
235b28412d5SFangrui Song     return make_error<StringError>("bad format for " + Option + ": missing '='",
236b28412d5SFangrui Song                                    errc::invalid_argument);
237f75da0c8SAlexey Lapshin   auto Split = StringRef(FlagValue).split('=');
238f75da0c8SAlexey Lapshin   if (Split.first.empty())
239b28412d5SFangrui Song     return make_error<StringError>("bad format for " + Option +
240b28412d5SFangrui Song                                        ": missing section name",
241b28412d5SFangrui Song                                    errc::invalid_argument);
242b28412d5SFangrui Song   uint64_t Value;
243b28412d5SFangrui Song   if (Split.second.getAsInteger(0, Value))
244b28412d5SFangrui Song     return make_error<StringError>("invalid value for " + Option + ": '" +
245b28412d5SFangrui Song                                        Split.second + "'",
246b28412d5SFangrui Song                                    errc::invalid_argument);
247b28412d5SFangrui Song   return std::make_pair(Split.first, Value);
248f75da0c8SAlexey Lapshin }
249f75da0c8SAlexey Lapshin 
250f75da0c8SAlexey Lapshin static Expected<SectionFlagsUpdate>
251f75da0c8SAlexey Lapshin parseSetSectionFlagValue(StringRef FlagValue) {
252f75da0c8SAlexey Lapshin   if (!StringRef(FlagValue).contains('='))
253f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
254f75da0c8SAlexey Lapshin                              "bad format for --set-section-flags: missing '='");
255f75da0c8SAlexey Lapshin 
256f75da0c8SAlexey Lapshin   // Initial split: ".foo" = "f1,f2,..."
257f75da0c8SAlexey Lapshin   auto Section2Flags = StringRef(FlagValue).split('=');
258f75da0c8SAlexey Lapshin   SectionFlagsUpdate SFU;
259f75da0c8SAlexey Lapshin   SFU.Name = Section2Flags.first;
260f75da0c8SAlexey Lapshin 
261f75da0c8SAlexey Lapshin   // Flags split: "f1" "f2" ...
262f75da0c8SAlexey Lapshin   SmallVector<StringRef, 6> SectionFlags;
263f75da0c8SAlexey Lapshin   Section2Flags.second.split(SectionFlags, ',');
264f75da0c8SAlexey Lapshin   Expected<SectionFlag> ParsedFlagSet = parseSectionFlagSet(SectionFlags);
265f75da0c8SAlexey Lapshin   if (!ParsedFlagSet)
266f75da0c8SAlexey Lapshin     return ParsedFlagSet.takeError();
267f75da0c8SAlexey Lapshin   SFU.NewFlags = *ParsedFlagSet;
268f75da0c8SAlexey Lapshin 
269f75da0c8SAlexey Lapshin   return SFU;
270f75da0c8SAlexey Lapshin }
271f75da0c8SAlexey Lapshin 
27207d8a457SIlia Kuklin static Expected<uint8_t> parseVisibilityType(StringRef VisType) {
27307d8a457SIlia Kuklin   const uint8_t Invalid = 0xff;
27407d8a457SIlia Kuklin   uint8_t type = StringSwitch<uint8_t>(VisType)
27507d8a457SIlia Kuklin                      .Case("default", ELF::STV_DEFAULT)
27607d8a457SIlia Kuklin                      .Case("hidden", ELF::STV_HIDDEN)
27707d8a457SIlia Kuklin                      .Case("internal", ELF::STV_INTERNAL)
27807d8a457SIlia Kuklin                      .Case("protected", ELF::STV_PROTECTED)
27907d8a457SIlia Kuklin                      .Default(Invalid);
28007d8a457SIlia Kuklin   if (type == Invalid)
28107d8a457SIlia Kuklin     return createStringError(errc::invalid_argument,
28207d8a457SIlia Kuklin                              "'%s' is not a valid symbol visibility",
28307d8a457SIlia Kuklin                              VisType.str().c_str());
28407d8a457SIlia Kuklin   return type;
28507d8a457SIlia Kuklin }
28607d8a457SIlia Kuklin 
287f75da0c8SAlexey Lapshin namespace {
288f75da0c8SAlexey Lapshin struct TargetInfo {
289f75da0c8SAlexey Lapshin   FileFormat Format;
290f75da0c8SAlexey Lapshin   MachineInfo Machine;
291f75da0c8SAlexey Lapshin };
292f75da0c8SAlexey Lapshin } // namespace
293f75da0c8SAlexey Lapshin 
294f75da0c8SAlexey Lapshin // FIXME: consolidate with the bfd parsing used by lld.
295f75da0c8SAlexey Lapshin static const StringMap<MachineInfo> TargetMap{
296f75da0c8SAlexey Lapshin     // Name, {EMachine, 64bit, LittleEndian}
297f75da0c8SAlexey Lapshin     // x86
298f75da0c8SAlexey Lapshin     {"elf32-i386", {ELF::EM_386, false, true}},
299f75da0c8SAlexey Lapshin     {"elf32-x86-64", {ELF::EM_X86_64, false, true}},
300f75da0c8SAlexey Lapshin     {"elf64-x86-64", {ELF::EM_X86_64, true, true}},
301f75da0c8SAlexey Lapshin     // Intel MCU
302f75da0c8SAlexey Lapshin     {"elf32-iamcu", {ELF::EM_IAMCU, false, true}},
303f75da0c8SAlexey Lapshin     // ARM
304f75da0c8SAlexey Lapshin     {"elf32-littlearm", {ELF::EM_ARM, false, true}},
305f75da0c8SAlexey Lapshin     // ARM AArch64
306f75da0c8SAlexey Lapshin     {"elf64-aarch64", {ELF::EM_AARCH64, true, true}},
307f75da0c8SAlexey Lapshin     {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}},
308f75da0c8SAlexey Lapshin     // RISC-V
309f75da0c8SAlexey Lapshin     {"elf32-littleriscv", {ELF::EM_RISCV, false, true}},
310f75da0c8SAlexey Lapshin     {"elf64-littleriscv", {ELF::EM_RISCV, true, true}},
311f75da0c8SAlexey Lapshin     // PowerPC
312f75da0c8SAlexey Lapshin     {"elf32-powerpc", {ELF::EM_PPC, false, false}},
313f75da0c8SAlexey Lapshin     {"elf32-powerpcle", {ELF::EM_PPC, false, true}},
314f75da0c8SAlexey Lapshin     {"elf64-powerpc", {ELF::EM_PPC64, true, false}},
315f75da0c8SAlexey Lapshin     {"elf64-powerpcle", {ELF::EM_PPC64, true, true}},
316f75da0c8SAlexey Lapshin     // MIPS
317f75da0c8SAlexey Lapshin     {"elf32-bigmips", {ELF::EM_MIPS, false, false}},
318f75da0c8SAlexey Lapshin     {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}},
319f75da0c8SAlexey Lapshin     {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}},
320f75da0c8SAlexey Lapshin     {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}},
321f75da0c8SAlexey Lapshin     {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}},
322f75da0c8SAlexey Lapshin     {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}},
323f75da0c8SAlexey Lapshin     {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}},
324f75da0c8SAlexey Lapshin     // SPARC
325f75da0c8SAlexey Lapshin     {"elf32-sparc", {ELF::EM_SPARC, false, false}},
326f75da0c8SAlexey Lapshin     {"elf32-sparcel", {ELF::EM_SPARC, false, true}},
327441afb39SWANG Xuerui     // Hexagon
328f75da0c8SAlexey Lapshin     {"elf32-hexagon", {ELF::EM_HEXAGON, false, true}},
329441afb39SWANG Xuerui     // LoongArch
330441afb39SWANG Xuerui     {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}},
331441afb39SWANG Xuerui     {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}},
3323c02cb74SUlrich Weigand     // SystemZ
3333c02cb74SUlrich Weigand     {"elf64-s390", {ELF::EM_S390, true, false}},
334f75da0c8SAlexey Lapshin };
335f75da0c8SAlexey Lapshin 
336f75da0c8SAlexey Lapshin static Expected<TargetInfo>
337f75da0c8SAlexey Lapshin getOutputTargetInfoByTargetName(StringRef TargetName) {
338f75da0c8SAlexey Lapshin   StringRef OriginalTargetName = TargetName;
339f75da0c8SAlexey Lapshin   bool IsFreeBSD = TargetName.consume_back("-freebsd");
340f75da0c8SAlexey Lapshin   auto Iter = TargetMap.find(TargetName);
341f75da0c8SAlexey Lapshin   if (Iter == std::end(TargetMap))
342f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
343f75da0c8SAlexey Lapshin                              "invalid output format: '%s'",
344f75da0c8SAlexey Lapshin                              OriginalTargetName.str().c_str());
345f75da0c8SAlexey Lapshin   MachineInfo MI = Iter->getValue();
346f75da0c8SAlexey Lapshin   if (IsFreeBSD)
347f75da0c8SAlexey Lapshin     MI.OSABI = ELF::ELFOSABI_FREEBSD;
348f75da0c8SAlexey Lapshin 
349f75da0c8SAlexey Lapshin   FileFormat Format;
350586ecdf2SKazu Hirata   if (TargetName.starts_with("elf"))
351f75da0c8SAlexey Lapshin     Format = FileFormat::ELF;
352f75da0c8SAlexey Lapshin   else
353f75da0c8SAlexey Lapshin     // This should never happen because `TargetName` is valid (it certainly
354f75da0c8SAlexey Lapshin     // exists in the TargetMap).
355f75da0c8SAlexey Lapshin     llvm_unreachable("unknown target prefix");
356f75da0c8SAlexey Lapshin 
357f75da0c8SAlexey Lapshin   return {TargetInfo{Format, MI}};
358f75da0c8SAlexey Lapshin }
359f75da0c8SAlexey Lapshin 
360f75da0c8SAlexey Lapshin static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
361f75da0c8SAlexey Lapshin                                 StringRef Filename, MatchStyle MS,
362f75da0c8SAlexey Lapshin                                 function_ref<Error(Error)> ErrorCallback) {
363f75da0c8SAlexey Lapshin   StringSaver Saver(Alloc);
364f75da0c8SAlexey Lapshin   SmallVector<StringRef, 16> Lines;
365f75da0c8SAlexey Lapshin   auto BufOrErr = MemoryBuffer::getFile(Filename);
366f75da0c8SAlexey Lapshin   if (!BufOrErr)
367f75da0c8SAlexey Lapshin     return createFileError(Filename, BufOrErr.getError());
368f75da0c8SAlexey Lapshin 
369f75da0c8SAlexey Lapshin   BufOrErr.get()->getBuffer().split(Lines, '\n');
370f75da0c8SAlexey Lapshin   for (StringRef Line : Lines) {
371f75da0c8SAlexey Lapshin     // Ignore everything after '#', trim whitespace, and only add the symbol if
372f75da0c8SAlexey Lapshin     // it's not empty.
373f75da0c8SAlexey Lapshin     auto TrimmedLine = Line.split('#').first.trim();
374f75da0c8SAlexey Lapshin     if (!TrimmedLine.empty())
375f75da0c8SAlexey Lapshin       if (Error E = Symbols.addMatcher(NameOrPattern::create(
376f75da0c8SAlexey Lapshin               Saver.save(TrimmedLine), MS, ErrorCallback)))
377f75da0c8SAlexey Lapshin         return E;
378f75da0c8SAlexey Lapshin   }
379f75da0c8SAlexey Lapshin 
380f75da0c8SAlexey Lapshin   return Error::success();
381f75da0c8SAlexey Lapshin }
382f75da0c8SAlexey Lapshin 
383f75da0c8SAlexey Lapshin static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
384f75da0c8SAlexey Lapshin                                         BumpPtrAllocator &Alloc,
385f75da0c8SAlexey Lapshin                                         StringRef Filename) {
386f75da0c8SAlexey Lapshin   StringSaver Saver(Alloc);
387f75da0c8SAlexey Lapshin   SmallVector<StringRef, 16> Lines;
388f75da0c8SAlexey Lapshin   auto BufOrErr = MemoryBuffer::getFile(Filename);
389f75da0c8SAlexey Lapshin   if (!BufOrErr)
390f75da0c8SAlexey Lapshin     return createFileError(Filename, BufOrErr.getError());
391f75da0c8SAlexey Lapshin 
392f75da0c8SAlexey Lapshin   BufOrErr.get()->getBuffer().split(Lines, '\n');
393f75da0c8SAlexey Lapshin   size_t NumLines = Lines.size();
394f75da0c8SAlexey Lapshin   for (size_t LineNo = 0; LineNo < NumLines; ++LineNo) {
395f75da0c8SAlexey Lapshin     StringRef TrimmedLine = Lines[LineNo].split('#').first.trim();
396f75da0c8SAlexey Lapshin     if (TrimmedLine.empty())
397f75da0c8SAlexey Lapshin       continue;
398f75da0c8SAlexey Lapshin 
399f75da0c8SAlexey Lapshin     std::pair<StringRef, StringRef> Pair = Saver.save(TrimmedLine).split(' ');
400f75da0c8SAlexey Lapshin     StringRef NewName = Pair.second.trim();
401f75da0c8SAlexey Lapshin     if (NewName.empty())
402f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
403f75da0c8SAlexey Lapshin                                "%s:%zu: missing new symbol name",
404f75da0c8SAlexey Lapshin                                Filename.str().c_str(), LineNo + 1);
405f75da0c8SAlexey Lapshin     SymbolsToRename.insert({Pair.first, NewName});
406f75da0c8SAlexey Lapshin   }
407f75da0c8SAlexey Lapshin   return Error::success();
408f75da0c8SAlexey Lapshin }
409f75da0c8SAlexey Lapshin 
410f75da0c8SAlexey Lapshin template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
411f75da0c8SAlexey Lapshin   T Result;
412f75da0c8SAlexey Lapshin   if (Val.getAsInteger(0, Result))
413f75da0c8SAlexey Lapshin     return errc::invalid_argument;
414f75da0c8SAlexey Lapshin   return Result;
415f75da0c8SAlexey Lapshin }
416f75da0c8SAlexey Lapshin 
417f75da0c8SAlexey Lapshin namespace {
418f75da0c8SAlexey Lapshin 
419f75da0c8SAlexey Lapshin enum class ToolType { Objcopy, Strip, InstallNameTool, BitcodeStrip };
420f75da0c8SAlexey Lapshin 
421f75da0c8SAlexey Lapshin } // anonymous namespace
422f75da0c8SAlexey Lapshin 
423f75da0c8SAlexey Lapshin static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
424f75da0c8SAlexey Lapshin                       ToolType Tool) {
425f75da0c8SAlexey Lapshin   StringRef HelpText, ToolName;
426f75da0c8SAlexey Lapshin   switch (Tool) {
427f75da0c8SAlexey Lapshin   case ToolType::Objcopy:
428f75da0c8SAlexey Lapshin     ToolName = "llvm-objcopy";
429f75da0c8SAlexey Lapshin     HelpText = " [options] input [output]";
430f75da0c8SAlexey Lapshin     break;
431f75da0c8SAlexey Lapshin   case ToolType::Strip:
432f75da0c8SAlexey Lapshin     ToolName = "llvm-strip";
433f75da0c8SAlexey Lapshin     HelpText = " [options] inputs...";
434f75da0c8SAlexey Lapshin     break;
435f75da0c8SAlexey Lapshin   case ToolType::InstallNameTool:
436f75da0c8SAlexey Lapshin     ToolName = "llvm-install-name-tool";
437f75da0c8SAlexey Lapshin     HelpText = " [options] input";
438f75da0c8SAlexey Lapshin     break;
439f75da0c8SAlexey Lapshin   case ToolType::BitcodeStrip:
440f75da0c8SAlexey Lapshin     ToolName = "llvm-bitcode-strip";
441f75da0c8SAlexey Lapshin     HelpText = " [options] input";
442f75da0c8SAlexey Lapshin     break;
443f75da0c8SAlexey Lapshin   }
444f75da0c8SAlexey Lapshin   OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
445f75da0c8SAlexey Lapshin                      (ToolName + " tool").str().c_str());
446f75da0c8SAlexey Lapshin   // TODO: Replace this with libOption call once it adds extrahelp support.
447f75da0c8SAlexey Lapshin   // The CommandLine library has a cl::extrahelp class to support this,
448f75da0c8SAlexey Lapshin   // but libOption does not have that yet.
449f75da0c8SAlexey Lapshin   OS << "\nPass @FILE as argument to read options from FILE.\n";
450f75da0c8SAlexey Lapshin }
451f75da0c8SAlexey Lapshin 
452f75da0c8SAlexey Lapshin static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
453f75da0c8SAlexey Lapshin   // Parse value given with --add-symbol option and create the
454f75da0c8SAlexey Lapshin   // new symbol if possible. The value format for --add-symbol is:
455f75da0c8SAlexey Lapshin   //
456f75da0c8SAlexey Lapshin   // <name>=[<section>:]<value>[,<flags>]
457f75da0c8SAlexey Lapshin   //
458f75da0c8SAlexey Lapshin   // where:
459f75da0c8SAlexey Lapshin   // <name> - symbol name, can be empty string
460f75da0c8SAlexey Lapshin   // <section> - optional section name. If not given ABS symbol is created
461f75da0c8SAlexey Lapshin   // <value> - symbol value, can be decimal or hexadecimal number prefixed
462f75da0c8SAlexey Lapshin   //           with 0x.
463f75da0c8SAlexey Lapshin   // <flags> - optional flags affecting symbol type, binding or visibility.
464f75da0c8SAlexey Lapshin   NewSymbolInfo SI;
465f75da0c8SAlexey Lapshin   StringRef Value;
466f75da0c8SAlexey Lapshin   std::tie(SI.SymbolName, Value) = FlagValue.split('=');
467f75da0c8SAlexey Lapshin   if (Value.empty())
468f75da0c8SAlexey Lapshin     return createStringError(
469f75da0c8SAlexey Lapshin         errc::invalid_argument,
470f75da0c8SAlexey Lapshin         "bad format for --add-symbol, missing '=' after '%s'",
471f75da0c8SAlexey Lapshin         SI.SymbolName.str().c_str());
472f75da0c8SAlexey Lapshin 
473f75da0c8SAlexey Lapshin   if (Value.contains(':')) {
474f75da0c8SAlexey Lapshin     std::tie(SI.SectionName, Value) = Value.split(':');
475f75da0c8SAlexey Lapshin     if (SI.SectionName.empty() || Value.empty())
476f75da0c8SAlexey Lapshin       return createStringError(
477f75da0c8SAlexey Lapshin           errc::invalid_argument,
478f75da0c8SAlexey Lapshin           "bad format for --add-symbol, missing section name or symbol value");
479f75da0c8SAlexey Lapshin   }
480f75da0c8SAlexey Lapshin 
481f75da0c8SAlexey Lapshin   SmallVector<StringRef, 6> Flags;
482f75da0c8SAlexey Lapshin   Value.split(Flags, ',');
483f75da0c8SAlexey Lapshin   if (Flags[0].getAsInteger(0, SI.Value))
484f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
485f75da0c8SAlexey Lapshin                              Flags[0].str().c_str());
486f75da0c8SAlexey Lapshin 
487f75da0c8SAlexey Lapshin   using Functor = std::function<void()>;
488f75da0c8SAlexey Lapshin   SmallVector<StringRef, 6> UnsupportedFlags;
489f75da0c8SAlexey Lapshin   for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
490f75da0c8SAlexey Lapshin     static_cast<Functor>(
491f75da0c8SAlexey Lapshin         StringSwitch<Functor>(Flags[I])
492f75da0c8SAlexey Lapshin             .CaseLower("global",
493f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Global); })
494f75da0c8SAlexey Lapshin             .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); })
495f75da0c8SAlexey Lapshin             .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); })
496f75da0c8SAlexey Lapshin             .CaseLower("default",
497f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Default); })
498f75da0c8SAlexey Lapshin             .CaseLower("hidden",
499f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Hidden); })
500f75da0c8SAlexey Lapshin             .CaseLower("protected",
501f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Protected); })
502f75da0c8SAlexey Lapshin             .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); })
503f75da0c8SAlexey Lapshin             .CaseLower("section",
504f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Section); })
505f75da0c8SAlexey Lapshin             .CaseLower("object",
506f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Object); })
507f75da0c8SAlexey Lapshin             .CaseLower("function",
508f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Function); })
509f75da0c8SAlexey Lapshin             .CaseLower(
510f75da0c8SAlexey Lapshin                 "indirect-function",
511f75da0c8SAlexey Lapshin                 [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); })
512f75da0c8SAlexey Lapshin             .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); })
513f75da0c8SAlexey Lapshin             .CaseLower("constructor",
514f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Constructor); })
515f75da0c8SAlexey Lapshin             .CaseLower("warning",
516f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Warning); })
517f75da0c8SAlexey Lapshin             .CaseLower("indirect",
518f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Indirect); })
519f75da0c8SAlexey Lapshin             .CaseLower("synthetic",
520f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::Synthetic); })
521f75da0c8SAlexey Lapshin             .CaseLower("unique-object",
522f75da0c8SAlexey Lapshin                        [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); })
523f75da0c8SAlexey Lapshin             .StartsWithLower("before=",
524f75da0c8SAlexey Lapshin                              [&] {
525f75da0c8SAlexey Lapshin                                StringRef SymNamePart =
526f75da0c8SAlexey Lapshin                                    Flags[I].split('=').second;
527f75da0c8SAlexey Lapshin 
528f75da0c8SAlexey Lapshin                                if (!SymNamePart.empty())
529f75da0c8SAlexey Lapshin                                  SI.BeforeSyms.push_back(SymNamePart);
530f75da0c8SAlexey Lapshin                              })
531f75da0c8SAlexey Lapshin             .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
532f75da0c8SAlexey Lapshin   if (!UnsupportedFlags.empty())
533f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
534f75da0c8SAlexey Lapshin                              "unsupported flag%s for --add-symbol: '%s'",
535f75da0c8SAlexey Lapshin                              UnsupportedFlags.size() > 1 ? "s" : "",
536f75da0c8SAlexey Lapshin                              join(UnsupportedFlags, "', '").c_str());
537f75da0c8SAlexey Lapshin 
538f75da0c8SAlexey Lapshin   return SI;
539f75da0c8SAlexey Lapshin }
540f75da0c8SAlexey Lapshin 
541*10772807SIgor Kudrin static Expected<RemoveNoteInfo> parseRemoveNoteInfo(StringRef FlagValue) {
542*10772807SIgor Kudrin   // Parse value given with --remove-note option. The format is:
543*10772807SIgor Kudrin   //
544*10772807SIgor Kudrin   // [name/]type_id
545*10772807SIgor Kudrin   //
546*10772807SIgor Kudrin   // where:
547*10772807SIgor Kudrin   // <name>    - optional note name. If not given, all notes with the specified
548*10772807SIgor Kudrin   //             <type_id> are removed.
549*10772807SIgor Kudrin   // <type_id> - note type value, can be decimal or hexadecimal number prefixed
550*10772807SIgor Kudrin   //             with 0x.
551*10772807SIgor Kudrin   RemoveNoteInfo NI;
552*10772807SIgor Kudrin   StringRef TypeIdStr;
553*10772807SIgor Kudrin   if (auto Idx = FlagValue.find('/'); Idx != StringRef::npos) {
554*10772807SIgor Kudrin     if (Idx == 0)
555*10772807SIgor Kudrin       return createStringError(
556*10772807SIgor Kudrin           errc::invalid_argument,
557*10772807SIgor Kudrin           "bad format for --remove-note, note name is empty");
558*10772807SIgor Kudrin     NI.Name = FlagValue.slice(0, Idx);
559*10772807SIgor Kudrin     TypeIdStr = FlagValue.substr(Idx + 1);
560*10772807SIgor Kudrin   } else {
561*10772807SIgor Kudrin     TypeIdStr = FlagValue;
562*10772807SIgor Kudrin   }
563*10772807SIgor Kudrin   if (TypeIdStr.empty())
564*10772807SIgor Kudrin     return createStringError(errc::invalid_argument,
565*10772807SIgor Kudrin                              "bad format for --remove-note, missing type_id");
566*10772807SIgor Kudrin   if (TypeIdStr.getAsInteger(0, NI.TypeId))
567*10772807SIgor Kudrin     return createStringError(errc::invalid_argument,
568*10772807SIgor Kudrin                              "bad note type_id for --remove-note: '%s'",
569*10772807SIgor Kudrin                              TypeIdStr.str().c_str());
570*10772807SIgor Kudrin   return NI;
571*10772807SIgor Kudrin }
572*10772807SIgor Kudrin 
573a6f3fedcSAlexey Lapshin // Parse input option \p ArgValue and load section data. This function
574a6f3fedcSAlexey Lapshin // extracts section name and name of the file keeping section data from
575a6f3fedcSAlexey Lapshin // ArgValue, loads data from the file, and stores section name and data
576a6f3fedcSAlexey Lapshin // into the vector of new sections \p NewSections.
577a6f3fedcSAlexey Lapshin static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
57853613044SFangrui Song                                 SmallVector<NewSectionInfo, 0> &NewSections) {
579a6f3fedcSAlexey Lapshin   if (!ArgValue.contains('='))
580a6f3fedcSAlexey Lapshin     return createStringError(errc::invalid_argument,
581a6f3fedcSAlexey Lapshin                              "bad format for " + OptionName + ": missing '='");
582a6f3fedcSAlexey Lapshin 
583a6f3fedcSAlexey Lapshin   std::pair<StringRef, StringRef> SecPair = ArgValue.split("=");
584a6f3fedcSAlexey Lapshin   if (SecPair.second.empty())
585a6f3fedcSAlexey Lapshin     return createStringError(errc::invalid_argument, "bad format for " +
586a6f3fedcSAlexey Lapshin                                                          OptionName +
587a6f3fedcSAlexey Lapshin                                                          ": missing file name");
588a6f3fedcSAlexey Lapshin 
589a6f3fedcSAlexey Lapshin   ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
590a6f3fedcSAlexey Lapshin       MemoryBuffer::getFile(SecPair.second);
591a6f3fedcSAlexey Lapshin   if (!BufOrErr)
592a6f3fedcSAlexey Lapshin     return createFileError(SecPair.second,
593a6f3fedcSAlexey Lapshin                            errorCodeToError(BufOrErr.getError()));
594a6f3fedcSAlexey Lapshin 
595a6f3fedcSAlexey Lapshin   NewSections.push_back({SecPair.first, std::move(*BufOrErr)});
596a6f3fedcSAlexey Lapshin   return Error::success();
597a6f3fedcSAlexey Lapshin }
598a6f3fedcSAlexey Lapshin 
59933200363SEleanor Bonnici static Expected<int64_t> parseChangeSectionLMA(StringRef ArgValue,
60033200363SEleanor Bonnici                                                StringRef OptionName) {
60133200363SEleanor Bonnici   StringRef StringValue;
60233200363SEleanor Bonnici   if (ArgValue.starts_with("*+")) {
60322e55ba3SKazu Hirata     StringValue = ArgValue.substr(2);
60433200363SEleanor Bonnici   } else if (ArgValue.starts_with("*-")) {
60522e55ba3SKazu Hirata     StringValue = ArgValue.substr(1);
60633200363SEleanor Bonnici   } else if (ArgValue.contains("=")) {
60733200363SEleanor Bonnici     return createStringError(errc::invalid_argument,
60833200363SEleanor Bonnici                              "bad format for " + OptionName +
60933200363SEleanor Bonnici                                  ": changing LMA to a specific value is not "
61033200363SEleanor Bonnici                                  "supported. Use *+val or *-val instead");
61133200363SEleanor Bonnici   } else if (ArgValue.contains("+") || ArgValue.contains("-")) {
61233200363SEleanor Bonnici     return createStringError(errc::invalid_argument,
61333200363SEleanor Bonnici                              "bad format for " + OptionName +
61433200363SEleanor Bonnici                                  ": changing a specific section LMA is not "
61533200363SEleanor Bonnici                                  "supported. Use *+val or *-val instead");
61633200363SEleanor Bonnici   }
61733200363SEleanor Bonnici   if (StringValue.empty())
61833200363SEleanor Bonnici     return createStringError(errc::invalid_argument,
61933200363SEleanor Bonnici                              "bad format for " + OptionName +
62033200363SEleanor Bonnici                                  ": missing LMA offset");
62133200363SEleanor Bonnici 
62233200363SEleanor Bonnici   auto LMAValue = getAsInteger<int64_t>(StringValue);
62333200363SEleanor Bonnici   if (!LMAValue)
62433200363SEleanor Bonnici     return createStringError(LMAValue.getError(),
62533200363SEleanor Bonnici                              "bad format for " + OptionName + ": value after " +
62633200363SEleanor Bonnici                                  ArgValue.slice(0, 2) + " is " + StringValue +
62733200363SEleanor Bonnici                                  " when it should be an integer");
62833200363SEleanor Bonnici   return *LMAValue;
62933200363SEleanor Bonnici }
63033200363SEleanor Bonnici 
6312b2f4ae0SEleanor Bonnici static Expected<SectionPatternAddressUpdate>
6322b2f4ae0SEleanor Bonnici parseChangeSectionAddr(StringRef ArgValue, StringRef OptionName,
6332b2f4ae0SEleanor Bonnici                        MatchStyle SectionMatchStyle,
6342b2f4ae0SEleanor Bonnici                        function_ref<Error(Error)> ErrorCallback) {
6352b2f4ae0SEleanor Bonnici   SectionPatternAddressUpdate PatternUpdate;
6362b2f4ae0SEleanor Bonnici 
6372b2f4ae0SEleanor Bonnici   size_t LastSymbolIndex = ArgValue.find_last_of("+-=");
6382b2f4ae0SEleanor Bonnici   if (LastSymbolIndex == StringRef::npos)
6392b2f4ae0SEleanor Bonnici     return createStringError(errc::invalid_argument,
6402b2f4ae0SEleanor Bonnici                              "bad format for " + OptionName +
6412b2f4ae0SEleanor Bonnici                                  ": argument value " + ArgValue +
6422b2f4ae0SEleanor Bonnici                                  " is invalid. See --help");
6432b2f4ae0SEleanor Bonnici   char UpdateSymbol = ArgValue[LastSymbolIndex];
6442b2f4ae0SEleanor Bonnici 
6452b2f4ae0SEleanor Bonnici   StringRef SectionPattern = ArgValue.slice(0, LastSymbolIndex);
6462b2f4ae0SEleanor Bonnici   if (SectionPattern.empty())
6472b2f4ae0SEleanor Bonnici     return createStringError(
6482b2f4ae0SEleanor Bonnici         errc::invalid_argument,
6492b2f4ae0SEleanor Bonnici         "bad format for " + OptionName +
6502b2f4ae0SEleanor Bonnici             ": missing section pattern to apply address change to");
6512b2f4ae0SEleanor Bonnici   if (Error E = PatternUpdate.SectionPattern.addMatcher(NameOrPattern::create(
6522b2f4ae0SEleanor Bonnici           SectionPattern, SectionMatchStyle, ErrorCallback)))
6532b2f4ae0SEleanor Bonnici     return std::move(E);
6542b2f4ae0SEleanor Bonnici 
65522e55ba3SKazu Hirata   StringRef Value = ArgValue.substr(LastSymbolIndex + 1);
6562b2f4ae0SEleanor Bonnici   if (Value.empty()) {
6572b2f4ae0SEleanor Bonnici     switch (UpdateSymbol) {
6582b2f4ae0SEleanor Bonnici     case '+':
6592b2f4ae0SEleanor Bonnici     case '-':
6602b2f4ae0SEleanor Bonnici       return createStringError(errc::invalid_argument,
6612b2f4ae0SEleanor Bonnici                                "bad format for " + OptionName +
6622b2f4ae0SEleanor Bonnici                                    ": missing value of offset after '" +
6632b2f4ae0SEleanor Bonnici                                    std::string({UpdateSymbol}) + "'");
6642b2f4ae0SEleanor Bonnici 
6652b2f4ae0SEleanor Bonnici     case '=':
6662b2f4ae0SEleanor Bonnici       return createStringError(errc::invalid_argument,
6672b2f4ae0SEleanor Bonnici                                "bad format for " + OptionName +
6682b2f4ae0SEleanor Bonnici                                    ": missing address value after '='");
6692b2f4ae0SEleanor Bonnici     }
6702b2f4ae0SEleanor Bonnici   }
6712b2f4ae0SEleanor Bonnici   auto AddrValue = getAsInteger<uint64_t>(Value);
6722b2f4ae0SEleanor Bonnici   if (!AddrValue)
6732b2f4ae0SEleanor Bonnici     return createStringError(AddrValue.getError(),
6742b2f4ae0SEleanor Bonnici                              "bad format for " + OptionName + ": value after " +
6752b2f4ae0SEleanor Bonnici                                  std::string({UpdateSymbol}) + " is " + Value +
6762b2f4ae0SEleanor Bonnici                                  " when it should be a 64-bit integer");
6772b2f4ae0SEleanor Bonnici 
6782b2f4ae0SEleanor Bonnici   switch (UpdateSymbol) {
6792b2f4ae0SEleanor Bonnici   case '+':
6802b2f4ae0SEleanor Bonnici     PatternUpdate.Update.Kind = AdjustKind::Add;
6812b2f4ae0SEleanor Bonnici     break;
6822b2f4ae0SEleanor Bonnici   case '-':
6832b2f4ae0SEleanor Bonnici     PatternUpdate.Update.Kind = AdjustKind::Subtract;
6842b2f4ae0SEleanor Bonnici     break;
6852b2f4ae0SEleanor Bonnici   case '=':
6862b2f4ae0SEleanor Bonnici     PatternUpdate.Update.Kind = AdjustKind::Set;
6872b2f4ae0SEleanor Bonnici   }
6882b2f4ae0SEleanor Bonnici 
6892b2f4ae0SEleanor Bonnici   PatternUpdate.Update.Value = *AddrValue;
6902b2f4ae0SEleanor Bonnici   return PatternUpdate;
6912b2f4ae0SEleanor Bonnici }
6922b2f4ae0SEleanor Bonnici 
693a91c77eeSNico Weber // parseObjcopyOptions returns the config and sets the input arguments. If a
694a91c77eeSNico Weber // help flag is set then parseObjcopyOptions will print the help messege and
695f75da0c8SAlexey Lapshin // exit.
696f75da0c8SAlexey Lapshin Expected<DriverConfig>
6972444b6f0SFangrui Song objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
698f75da0c8SAlexey Lapshin                              function_ref<Error(Error)> ErrorCallback) {
699f75da0c8SAlexey Lapshin   DriverConfig DC;
700f75da0c8SAlexey Lapshin   ObjcopyOptTable T;
701f75da0c8SAlexey Lapshin 
702f75da0c8SAlexey Lapshin   unsigned MissingArgumentIndex, MissingArgumentCount;
703f75da0c8SAlexey Lapshin   llvm::opt::InputArgList InputArgs =
704f75da0c8SAlexey Lapshin       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
705f75da0c8SAlexey Lapshin 
706183beb33SAlexey Karyakin   if (MissingArgumentCount)
707183beb33SAlexey Karyakin     return createStringError(
708183beb33SAlexey Karyakin         errc::invalid_argument,
709183beb33SAlexey Karyakin         "argument to '%s' is missing (expected %d value(s))",
710183beb33SAlexey Karyakin         InputArgs.getArgString(MissingArgumentIndex), MissingArgumentCount);
711183beb33SAlexey Karyakin 
7122444b6f0SFangrui Song   if (InputArgs.size() == 0) {
713f75da0c8SAlexey Lapshin     printHelp(T, errs(), ToolType::Objcopy);
714f75da0c8SAlexey Lapshin     exit(1);
715f75da0c8SAlexey Lapshin   }
716f75da0c8SAlexey Lapshin 
717f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(OBJCOPY_help)) {
718f75da0c8SAlexey Lapshin     printHelp(T, outs(), ToolType::Objcopy);
719f75da0c8SAlexey Lapshin     exit(0);
720f75da0c8SAlexey Lapshin   }
721f75da0c8SAlexey Lapshin 
722f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(OBJCOPY_version)) {
723f75da0c8SAlexey Lapshin     outs() << "llvm-objcopy, compatible with GNU objcopy\n";
724f75da0c8SAlexey Lapshin     cl::PrintVersionMessage();
725f75da0c8SAlexey Lapshin     exit(0);
726f75da0c8SAlexey Lapshin   }
727f75da0c8SAlexey Lapshin 
728f75da0c8SAlexey Lapshin   SmallVector<const char *, 2> Positional;
729f75da0c8SAlexey Lapshin 
73086e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
731f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument, "unknown argument '%s'",
732f75da0c8SAlexey Lapshin                              Arg->getAsString(InputArgs).c_str());
733f75da0c8SAlexey Lapshin 
73486e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
735f75da0c8SAlexey Lapshin     Positional.push_back(Arg->getValue());
736f75da0c8SAlexey Lapshin 
737f75da0c8SAlexey Lapshin   if (Positional.empty())
738f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument, "no input file specified");
739f75da0c8SAlexey Lapshin 
740f75da0c8SAlexey Lapshin   if (Positional.size() > 2)
741f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
742f75da0c8SAlexey Lapshin                              "too many positional arguments");
743f75da0c8SAlexey Lapshin 
744f75da0c8SAlexey Lapshin   ConfigManager ConfigMgr;
745f75da0c8SAlexey Lapshin   CommonConfig &Config = ConfigMgr.Common;
746f75da0c8SAlexey Lapshin   COFFConfig &COFFConfig = ConfigMgr.COFF;
747f75da0c8SAlexey Lapshin   ELFConfig &ELFConfig = ConfigMgr.ELF;
748f75da0c8SAlexey Lapshin   MachOConfig &MachOConfig = ConfigMgr.MachO;
749f75da0c8SAlexey Lapshin   Config.InputFilename = Positional[0];
750f75da0c8SAlexey Lapshin   Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
751f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(OBJCOPY_target) &&
752f75da0c8SAlexey Lapshin       (InputArgs.hasArg(OBJCOPY_input_target) ||
753f75da0c8SAlexey Lapshin        InputArgs.hasArg(OBJCOPY_output_target)))
754f75da0c8SAlexey Lapshin     return createStringError(
755f75da0c8SAlexey Lapshin         errc::invalid_argument,
756f75da0c8SAlexey Lapshin         "--target cannot be used with --input-target or --output-target");
757f75da0c8SAlexey Lapshin 
758f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
759f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
760f75da0c8SAlexey Lapshin                              "--regex and --wildcard are incompatible");
761f75da0c8SAlexey Lapshin 
762f75da0c8SAlexey Lapshin   MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
763f75da0c8SAlexey Lapshin                                      ? MatchStyle::Regex
764f75da0c8SAlexey Lapshin                                      : MatchStyle::Wildcard;
765f75da0c8SAlexey Lapshin   MatchStyle SymbolMatchStyle
766f75da0c8SAlexey Lapshin       = InputArgs.hasArg(OBJCOPY_regex)    ? MatchStyle::Regex
767f75da0c8SAlexey Lapshin       : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard
768f75da0c8SAlexey Lapshin                                            : MatchStyle::Literal;
769f75da0c8SAlexey Lapshin   StringRef InputFormat, OutputFormat;
770f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(OBJCOPY_target)) {
771f75da0c8SAlexey Lapshin     InputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
772f75da0c8SAlexey Lapshin     OutputFormat = InputArgs.getLastArgValue(OBJCOPY_target);
773f75da0c8SAlexey Lapshin   } else {
774f75da0c8SAlexey Lapshin     InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
775f75da0c8SAlexey Lapshin     OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
776f75da0c8SAlexey Lapshin   }
777f75da0c8SAlexey Lapshin 
778f75da0c8SAlexey Lapshin   // FIXME:  Currently, we ignore the target for non-binary/ihex formats
779f75da0c8SAlexey Lapshin   // explicitly specified by -I option (e.g. -Ielf32-x86-64) and guess the
780f75da0c8SAlexey Lapshin   // format by llvm::object::createBinary regardless of the option value.
781f75da0c8SAlexey Lapshin   Config.InputFormat = StringSwitch<FileFormat>(InputFormat)
782f75da0c8SAlexey Lapshin                            .Case("binary", FileFormat::Binary)
783f75da0c8SAlexey Lapshin                            .Case("ihex", FileFormat::IHex)
784f75da0c8SAlexey Lapshin                            .Default(FileFormat::Unspecified);
785f75da0c8SAlexey Lapshin 
786f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) {
787f75da0c8SAlexey Lapshin     const uint8_t Invalid = 0xff;
788f75da0c8SAlexey Lapshin     StringRef VisibilityStr =
789f75da0c8SAlexey Lapshin         InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
790f75da0c8SAlexey Lapshin 
791f75da0c8SAlexey Lapshin     ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr)
792f75da0c8SAlexey Lapshin                                         .Case("default", ELF::STV_DEFAULT)
793f75da0c8SAlexey Lapshin                                         .Case("hidden", ELF::STV_HIDDEN)
794f75da0c8SAlexey Lapshin                                         .Case("internal", ELF::STV_INTERNAL)
795f75da0c8SAlexey Lapshin                                         .Case("protected", ELF::STV_PROTECTED)
796f75da0c8SAlexey Lapshin                                         .Default(Invalid);
797f75da0c8SAlexey Lapshin 
798f75da0c8SAlexey Lapshin     if (ELFConfig.NewSymbolVisibility == Invalid)
799f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
800f75da0c8SAlexey Lapshin                                "'%s' is not a valid symbol visibility",
801f75da0c8SAlexey Lapshin                                VisibilityStr.str().c_str());
802f75da0c8SAlexey Lapshin   }
803f75da0c8SAlexey Lapshin 
804f75da0c8SAlexey Lapshin   for (const auto *Arg : InputArgs.filtered(OBJCOPY_subsystem)) {
805f75da0c8SAlexey Lapshin     StringRef Subsystem, Version;
806f75da0c8SAlexey Lapshin     std::tie(Subsystem, Version) = StringRef(Arg->getValue()).split(':');
807f75da0c8SAlexey Lapshin     COFFConfig.Subsystem =
808f75da0c8SAlexey Lapshin         StringSwitch<unsigned>(Subsystem.lower())
809f75da0c8SAlexey Lapshin             .Case("boot_application",
810f75da0c8SAlexey Lapshin                   COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
811f75da0c8SAlexey Lapshin             .Case("console", COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
8126aefa918SVictor Campos             .Cases("efi_application", "efi-app",
8136aefa918SVictor Campos                    COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION)
8146aefa918SVictor Campos             .Cases("efi_boot_service_driver", "efi-bsd",
815f75da0c8SAlexey Lapshin                    COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
816f75da0c8SAlexey Lapshin             .Case("efi_rom", COFF::IMAGE_SUBSYSTEM_EFI_ROM)
8176aefa918SVictor Campos             .Cases("efi_runtime_driver", "efi-rtd",
818f75da0c8SAlexey Lapshin                    COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
819f75da0c8SAlexey Lapshin             .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE)
820f75da0c8SAlexey Lapshin             .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI)
821f75da0c8SAlexey Lapshin             .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
822f75da0c8SAlexey Lapshin             .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN);
823f75da0c8SAlexey Lapshin     if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN)
824f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
825f75da0c8SAlexey Lapshin                                "'%s' is not a valid subsystem",
826f75da0c8SAlexey Lapshin                                Subsystem.str().c_str());
827f75da0c8SAlexey Lapshin     if (!Version.empty()) {
828f75da0c8SAlexey Lapshin       StringRef Major, Minor;
829f75da0c8SAlexey Lapshin       std::tie(Major, Minor) = Version.split('.');
830f75da0c8SAlexey Lapshin       unsigned Number;
831f75da0c8SAlexey Lapshin       if (Major.getAsInteger(10, Number))
832f75da0c8SAlexey Lapshin         return createStringError(errc::invalid_argument,
833f75da0c8SAlexey Lapshin                                  "'%s' is not a valid subsystem major version",
834f75da0c8SAlexey Lapshin                                  Major.str().c_str());
835f75da0c8SAlexey Lapshin       COFFConfig.MajorSubsystemVersion = Number;
836f75da0c8SAlexey Lapshin       Number = 0;
837f75da0c8SAlexey Lapshin       if (!Minor.empty() && Minor.getAsInteger(10, Number))
838f75da0c8SAlexey Lapshin         return createStringError(errc::invalid_argument,
839f75da0c8SAlexey Lapshin                                  "'%s' is not a valid subsystem minor version",
840f75da0c8SAlexey Lapshin                                  Minor.str().c_str());
841f75da0c8SAlexey Lapshin       COFFConfig.MinorSubsystemVersion = Number;
842f75da0c8SAlexey Lapshin     }
843f75da0c8SAlexey Lapshin   }
844f75da0c8SAlexey Lapshin 
845f75da0c8SAlexey Lapshin   Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
846f75da0c8SAlexey Lapshin                             .Case("binary", FileFormat::Binary)
847f75da0c8SAlexey Lapshin                             .Case("ihex", FileFormat::IHex)
8487ddc3205Squic-areg                             .Case("srec", FileFormat::SREC)
849f75da0c8SAlexey Lapshin                             .Default(FileFormat::Unspecified);
850f75da0c8SAlexey Lapshin   if (Config.OutputFormat == FileFormat::Unspecified) {
851f75da0c8SAlexey Lapshin     if (OutputFormat.empty()) {
852f75da0c8SAlexey Lapshin       Config.OutputFormat = Config.InputFormat;
853f75da0c8SAlexey Lapshin     } else {
854f75da0c8SAlexey Lapshin       Expected<TargetInfo> Target =
855f75da0c8SAlexey Lapshin           getOutputTargetInfoByTargetName(OutputFormat);
856f75da0c8SAlexey Lapshin       if (!Target)
857f75da0c8SAlexey Lapshin         return Target.takeError();
858f75da0c8SAlexey Lapshin       Config.OutputFormat = Target->Format;
859f75da0c8SAlexey Lapshin       Config.OutputArch = Target->Machine;
860f75da0c8SAlexey Lapshin     }
861f75da0c8SAlexey Lapshin   }
862f75da0c8SAlexey Lapshin 
863ef03f662SFangrui Song   if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) {
864ef03f662SFangrui Song     Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue())
865781dea02SFangrui Song                                  .Case("zlib", DebugCompressionType::Zlib)
866b6e1fd76SFangrui Song                                  .Case("zstd", DebugCompressionType::Zstd)
867f75da0c8SAlexey Lapshin                                  .Default(DebugCompressionType::None);
868b6e1fd76SFangrui Song     if (Config.CompressionType == DebugCompressionType::None) {
869f75da0c8SAlexey Lapshin       return createStringError(
870f75da0c8SAlexey Lapshin           errc::invalid_argument,
871f75da0c8SAlexey Lapshin           "invalid or unsupported --compress-debug-sections format: %s",
872ef03f662SFangrui Song           A->getValue());
873b6e1fd76SFangrui Song     }
874b6e1fd76SFangrui Song     if (const char *Reason = compression::getReasonIfUnsupported(
875b6e1fd76SFangrui Song             compression::formatFor(Config.CompressionType)))
876b6e1fd76SFangrui Song       return createStringError(errc::invalid_argument, Reason);
877f75da0c8SAlexey Lapshin   }
878f75da0c8SAlexey Lapshin 
87907942987SFangrui Song   for (const auto *A : InputArgs.filtered(OBJCOPY_compress_sections)) {
88007942987SFangrui Song     SmallVector<StringRef, 0> Fields;
88107942987SFangrui Song     StringRef(A->getValue()).split(Fields, '=');
88207942987SFangrui Song     if (Fields.size() != 2 || Fields[1].empty()) {
88307942987SFangrui Song       return createStringError(
88407942987SFangrui Song           errc::invalid_argument,
88507942987SFangrui Song           A->getSpelling() +
88607942987SFangrui Song               ": parse error, not 'section-glob=[none|zlib|zstd]'");
88707942987SFangrui Song     }
88807942987SFangrui Song 
88907942987SFangrui Song     auto Type = StringSwitch<DebugCompressionType>(Fields[1])
89007942987SFangrui Song                     .Case("zlib", DebugCompressionType::Zlib)
89107942987SFangrui Song                     .Case("zstd", DebugCompressionType::Zstd)
89207942987SFangrui Song                     .Default(DebugCompressionType::None);
89307942987SFangrui Song     if (Type == DebugCompressionType::None && Fields[1] != "none") {
89407942987SFangrui Song       return createStringError(
89507942987SFangrui Song           errc::invalid_argument,
89607942987SFangrui Song           "invalid or unsupported --compress-sections format: %s",
89707942987SFangrui Song           A->getValue());
89807942987SFangrui Song     }
89907942987SFangrui Song 
90007942987SFangrui Song     auto &P = Config.compressSections.emplace_back();
90107942987SFangrui Song     P.second = Type;
90207942987SFangrui Song     auto Matcher =
90307942987SFangrui Song         NameOrPattern::create(Fields[0], SectionMatchStyle, ErrorCallback);
90407942987SFangrui Song     // =none allows overriding a previous =zlib or =zstd. Reject negative
90507942987SFangrui Song     // patterns, which would be confusing.
90607942987SFangrui Song     if (Matcher && !Matcher->isPositiveMatch()) {
90707942987SFangrui Song       return createStringError(
90807942987SFangrui Song           errc::invalid_argument,
90907942987SFangrui Song           "--compress-sections: negative pattern is unsupported");
91007942987SFangrui Song     }
91107942987SFangrui Song     if (Error E = P.first.addMatcher(std::move(Matcher)))
91207942987SFangrui Song       return std::move(E);
91307942987SFangrui Song   }
91407942987SFangrui Song 
915f75da0c8SAlexey Lapshin   Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
916f75da0c8SAlexey Lapshin   // The gnu_debuglink's target is expected to not change or else its CRC would
917f75da0c8SAlexey Lapshin   // become invalidated and get rejected. We can avoid recalculating the
918f75da0c8SAlexey Lapshin   // checksum for every target file inside an archive by precomputing the CRC
919f75da0c8SAlexey Lapshin   // here. This prevents a significant amount of I/O.
920f75da0c8SAlexey Lapshin   if (!Config.AddGnuDebugLink.empty()) {
921f75da0c8SAlexey Lapshin     auto DebugOrErr = MemoryBuffer::getFile(Config.AddGnuDebugLink);
922f75da0c8SAlexey Lapshin     if (!DebugOrErr)
923f75da0c8SAlexey Lapshin       return createFileError(Config.AddGnuDebugLink, DebugOrErr.getError());
924f75da0c8SAlexey Lapshin     auto Debug = std::move(*DebugOrErr);
925f75da0c8SAlexey Lapshin     Config.GnuDebugLinkCRC32 =
926f75da0c8SAlexey Lapshin         llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
927f75da0c8SAlexey Lapshin   }
928f75da0c8SAlexey Lapshin   Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
9291b87ebceSYi Kong 
930f75da0c8SAlexey Lapshin   Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
9311b87ebceSYi Kong   Config.SymbolsPrefixRemove =
9321b87ebceSYi Kong       InputArgs.getLastArgValue(OBJCOPY_remove_symbol_prefix);
9331b87ebceSYi Kong 
934f75da0c8SAlexey Lapshin   Config.AllocSectionsPrefix =
935f75da0c8SAlexey Lapshin       InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
936f75da0c8SAlexey Lapshin   if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
937f75da0c8SAlexey Lapshin     Config.ExtractPartition = Arg->getValue();
938f75da0c8SAlexey Lapshin 
9394070dffdSquic-akaryaki   if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) {
9404070dffdSquic-akaryaki     if (Config.OutputFormat != FileFormat::Binary)
9414070dffdSquic-akaryaki       return createStringError(
9424070dffdSquic-akaryaki           errc::invalid_argument,
9434070dffdSquic-akaryaki           "'--gap-fill' is only supported for binary output");
9444070dffdSquic-akaryaki     ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue());
9454070dffdSquic-akaryaki     if (!Val)
9464070dffdSquic-akaryaki       return createStringError(Val.getError(), "--gap-fill: bad number: %s",
9474070dffdSquic-akaryaki                                A->getValue());
9484070dffdSquic-akaryaki     uint8_t ByteVal = Val.get();
9494070dffdSquic-akaryaki     if (ByteVal != Val.get())
9504070dffdSquic-akaryaki       return createStringError(std::errc::value_too_large,
9514070dffdSquic-akaryaki                                "gap-fill value %s is out of range (0 to 0xff)",
9524070dffdSquic-akaryaki                                A->getValue());
9534070dffdSquic-akaryaki     Config.GapFill = ByteVal;
9544070dffdSquic-akaryaki   }
9554070dffdSquic-akaryaki 
9564070dffdSquic-akaryaki   if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) {
9574070dffdSquic-akaryaki     if (Config.OutputFormat != FileFormat::Binary)
9584070dffdSquic-akaryaki       return createStringError(
9594070dffdSquic-akaryaki           errc::invalid_argument,
9604070dffdSquic-akaryaki           "'--pad-to' is only supported for binary output");
9614070dffdSquic-akaryaki     ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue());
9624070dffdSquic-akaryaki     if (!Addr)
9634070dffdSquic-akaryaki       return createStringError(Addr.getError(), "--pad-to: bad number: %s",
9644070dffdSquic-akaryaki                                A->getValue());
9654070dffdSquic-akaryaki     Config.PadTo = *Addr;
9664070dffdSquic-akaryaki   }
9674070dffdSquic-akaryaki 
96833200363SEleanor Bonnici   if (const auto *Arg = InputArgs.getLastArg(OBJCOPY_change_section_lma)) {
96933200363SEleanor Bonnici     Expected<int64_t> LMAValue =
97033200363SEleanor Bonnici         parseChangeSectionLMA(Arg->getValue(), Arg->getSpelling());
97133200363SEleanor Bonnici     if (!LMAValue)
97233200363SEleanor Bonnici       return LMAValue.takeError();
97333200363SEleanor Bonnici     Config.ChangeSectionLMAValAll = *LMAValue;
97433200363SEleanor Bonnici   }
97533200363SEleanor Bonnici 
9762b2f4ae0SEleanor Bonnici   for (auto *Arg : InputArgs.filtered(OBJCOPY_change_section_address)) {
9772b2f4ae0SEleanor Bonnici     Expected<SectionPatternAddressUpdate> AddressUpdate =
9782b2f4ae0SEleanor Bonnici         parseChangeSectionAddr(Arg->getValue(), Arg->getSpelling(),
9792b2f4ae0SEleanor Bonnici                                SectionMatchStyle, ErrorCallback);
9802b2f4ae0SEleanor Bonnici     if (!AddressUpdate)
9812b2f4ae0SEleanor Bonnici       return AddressUpdate.takeError();
9822b2f4ae0SEleanor Bonnici     Config.ChangeSectionAddress.push_back(*AddressUpdate);
9832b2f4ae0SEleanor Bonnici   }
9842b2f4ae0SEleanor Bonnici 
98586e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
986f75da0c8SAlexey Lapshin     if (!StringRef(Arg->getValue()).contains('='))
987f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
988f75da0c8SAlexey Lapshin                                "bad format for --redefine-sym");
989f75da0c8SAlexey Lapshin     auto Old2New = StringRef(Arg->getValue()).split('=');
990f75da0c8SAlexey Lapshin     if (!Config.SymbolsToRename.insert(Old2New).second)
991f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
992f75da0c8SAlexey Lapshin                                "multiple redefinition of symbol '%s'",
993f75da0c8SAlexey Lapshin                                Old2New.first.str().c_str());
994f75da0c8SAlexey Lapshin   }
995f75da0c8SAlexey Lapshin 
99686e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
997f75da0c8SAlexey Lapshin     if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
998f75da0c8SAlexey Lapshin                                              Arg->getValue()))
999f75da0c8SAlexey Lapshin       return std::move(E);
1000f75da0c8SAlexey Lapshin 
100186e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
1002f75da0c8SAlexey Lapshin     Expected<SectionRename> SR =
1003f75da0c8SAlexey Lapshin         parseRenameSectionValue(StringRef(Arg->getValue()));
1004f75da0c8SAlexey Lapshin     if (!SR)
1005f75da0c8SAlexey Lapshin       return SR.takeError();
1006f75da0c8SAlexey Lapshin     if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
1007f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
1008f75da0c8SAlexey Lapshin                                "multiple renames of section '%s'",
1009f75da0c8SAlexey Lapshin                                SR->OriginalName.str().c_str());
1010f75da0c8SAlexey Lapshin   }
101186e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
1012f75da0c8SAlexey Lapshin     Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
1013b28412d5SFangrui Song         parseSetSectionAttribute("--set-section-alignment", Arg->getValue());
1014f75da0c8SAlexey Lapshin     if (!NameAndAlign)
1015f75da0c8SAlexey Lapshin       return NameAndAlign.takeError();
1016f75da0c8SAlexey Lapshin     Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
1017f75da0c8SAlexey Lapshin   }
101886e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
1019f75da0c8SAlexey Lapshin     Expected<SectionFlagsUpdate> SFU =
1020f75da0c8SAlexey Lapshin         parseSetSectionFlagValue(Arg->getValue());
1021f75da0c8SAlexey Lapshin     if (!SFU)
1022f75da0c8SAlexey Lapshin       return SFU.takeError();
1023f75da0c8SAlexey Lapshin     if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
1024f75da0c8SAlexey Lapshin       return createStringError(
1025f75da0c8SAlexey Lapshin           errc::invalid_argument,
1026f75da0c8SAlexey Lapshin           "--set-section-flags set multiple times for section '%s'",
1027f75da0c8SAlexey Lapshin           SFU->Name.str().c_str());
1028f75da0c8SAlexey Lapshin   }
102986e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) {
1030b28412d5SFangrui Song     Expected<std::pair<StringRef, uint64_t>> NameAndType =
1031b28412d5SFangrui Song         parseSetSectionAttribute("--set-section-type", Arg->getValue());
1032b28412d5SFangrui Song     if (!NameAndType)
1033b28412d5SFangrui Song       return NameAndType.takeError();
1034b28412d5SFangrui Song     Config.SetSectionType[NameAndType->first] = NameAndType->second;
1035b28412d5SFangrui Song   }
1036b28412d5SFangrui Song   // Prohibit combinations of --set-section-{flags,type} when the section name
1037b28412d5SFangrui Song   // is used as the destination of a --rename-section.
1038f75da0c8SAlexey Lapshin   for (const auto &E : Config.SectionsToRename) {
1039f75da0c8SAlexey Lapshin     const SectionRename &SR = E.second;
1040b28412d5SFangrui Song     auto Err = [&](const char *Option) {
1041f75da0c8SAlexey Lapshin       return createStringError(
1042f75da0c8SAlexey Lapshin           errc::invalid_argument,
1043b28412d5SFangrui Song           "--set-section-%s=%s conflicts with --rename-section=%s=%s", Option,
1044f75da0c8SAlexey Lapshin           SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
1045f75da0c8SAlexey Lapshin           SR.NewName.str().c_str());
1046b28412d5SFangrui Song     };
1047b28412d5SFangrui Song     if (Config.SetSectionFlags.count(SR.NewName))
1048b28412d5SFangrui Song       return Err("flags");
1049b28412d5SFangrui Song     if (Config.SetSectionType.count(SR.NewName))
1050b28412d5SFangrui Song       return Err("type");
1051f75da0c8SAlexey Lapshin   }
1052f75da0c8SAlexey Lapshin 
105386e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section))
1054f75da0c8SAlexey Lapshin     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
1055f75da0c8SAlexey Lapshin             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1056f75da0c8SAlexey Lapshin       return std::move(E);
105786e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section))
1058f75da0c8SAlexey Lapshin     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
1059f75da0c8SAlexey Lapshin             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1060f75da0c8SAlexey Lapshin       return std::move(E);
106186e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section))
1062f75da0c8SAlexey Lapshin     if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
1063f75da0c8SAlexey Lapshin             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1064f75da0c8SAlexey Lapshin       return std::move(E);
106586e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) {
1066a6f3fedcSAlexey Lapshin     if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section",
1067a6f3fedcSAlexey Lapshin                                        Config.AddSection))
1068a6f3fedcSAlexey Lapshin       return std::move(Err);
1069f75da0c8SAlexey Lapshin   }
107086e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) {
1071a6f3fedcSAlexey Lapshin     if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section",
1072a6f3fedcSAlexey Lapshin                                        Config.UpdateSection))
1073a6f3fedcSAlexey Lapshin       return std::move(Err);
1074f75da0c8SAlexey Lapshin   }
1075f75da0c8SAlexey Lapshin   for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
1076f75da0c8SAlexey Lapshin     StringRef Value(Arg->getValue());
1077f75da0c8SAlexey Lapshin     if (Value.split('=').second.empty())
1078f75da0c8SAlexey Lapshin       return createStringError(
1079f75da0c8SAlexey Lapshin           errc::invalid_argument,
1080f75da0c8SAlexey Lapshin           "bad format for --dump-section, expected section=file");
1081f75da0c8SAlexey Lapshin     Config.DumpSection.push_back(Value);
1082f75da0c8SAlexey Lapshin   }
1083f75da0c8SAlexey Lapshin   Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
1084f75da0c8SAlexey Lapshin   Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
1085f75da0c8SAlexey Lapshin   Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
1086f75da0c8SAlexey Lapshin   Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
1087f75da0c8SAlexey Lapshin   Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
1088f75da0c8SAlexey Lapshin   Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
1089f75da0c8SAlexey Lapshin   Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
1090f75da0c8SAlexey Lapshin   Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
1091f75da0c8SAlexey Lapshin   Config.ExtractMainPartition =
1092f75da0c8SAlexey Lapshin       InputArgs.hasArg(OBJCOPY_extract_main_partition);
1093f75da0c8SAlexey Lapshin   ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
1094f75da0c8SAlexey Lapshin   Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
1095c37accf0SFangrui Song   if (auto *Arg =
1096c37accf0SFangrui Song           InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
1097c37accf0SFangrui Song     Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all)
1098f75da0c8SAlexey Lapshin                              ? DiscardType::All
1099f75da0c8SAlexey Lapshin                              : DiscardType::Locals;
1100c37accf0SFangrui Song   }
1101fb5a38bbSserge-sans-paille 
1102fb5a38bbSserge-sans-paille   ELFConfig.VerifyNoteSections = InputArgs.hasFlag(
1103fb5a38bbSserge-sans-paille       OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true);
1104fb5a38bbSserge-sans-paille 
1105f75da0c8SAlexey Lapshin   Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
1106f75da0c8SAlexey Lapshin   ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
1107f75da0c8SAlexey Lapshin   MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
1108f75da0c8SAlexey Lapshin   Config.DecompressDebugSections =
1109f75da0c8SAlexey Lapshin       InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
1110f75da0c8SAlexey Lapshin   if (Config.DiscardMode == DiscardType::All) {
1111f75da0c8SAlexey Lapshin     Config.StripDebug = true;
1112f75da0c8SAlexey Lapshin     ELFConfig.KeepFileSymbols = true;
1113f75da0c8SAlexey Lapshin   }
111486e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
1115f75da0c8SAlexey Lapshin     if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
1116f75da0c8SAlexey Lapshin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1117f75da0c8SAlexey Lapshin       return std::move(E);
111886e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
1119f75da0c8SAlexey Lapshin     if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
1120f75da0c8SAlexey Lapshin                                      Arg->getValue(), SymbolMatchStyle,
1121f75da0c8SAlexey Lapshin                                      ErrorCallback))
1122f75da0c8SAlexey Lapshin       return std::move(E);
112386e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
1124f75da0c8SAlexey Lapshin     if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
1125f75da0c8SAlexey Lapshin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1126f75da0c8SAlexey Lapshin       return std::move(E);
112786e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
1128f75da0c8SAlexey Lapshin     if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
1129f75da0c8SAlexey Lapshin                                      Arg->getValue(), SymbolMatchStyle,
1130f75da0c8SAlexey Lapshin                                      ErrorCallback))
1131f75da0c8SAlexey Lapshin       return std::move(E);
113286e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
1133f75da0c8SAlexey Lapshin     if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
1134f75da0c8SAlexey Lapshin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1135f75da0c8SAlexey Lapshin       return std::move(E);
113686e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
1137f75da0c8SAlexey Lapshin     if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
1138f75da0c8SAlexey Lapshin                                      Arg->getValue(), SymbolMatchStyle,
1139f75da0c8SAlexey Lapshin                                      ErrorCallback))
1140f75da0c8SAlexey Lapshin       return std::move(E);
114186e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
1142f75da0c8SAlexey Lapshin     if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
1143f75da0c8SAlexey Lapshin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1144f75da0c8SAlexey Lapshin       return std::move(E);
114586e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
1146f75da0c8SAlexey Lapshin     if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
1147f75da0c8SAlexey Lapshin                                      Arg->getValue(), SymbolMatchStyle,
1148f75da0c8SAlexey Lapshin                                      ErrorCallback))
1149f75da0c8SAlexey Lapshin       return std::move(E);
115086e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
1151f75da0c8SAlexey Lapshin     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
1152f75da0c8SAlexey Lapshin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1153f75da0c8SAlexey Lapshin       return std::move(E);
115486e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
1155f75da0c8SAlexey Lapshin     if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
1156f75da0c8SAlexey Lapshin                                      Arg->getValue(), SymbolMatchStyle,
1157f75da0c8SAlexey Lapshin                                      ErrorCallback))
1158f75da0c8SAlexey Lapshin       return std::move(E);
115986e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
1160f75da0c8SAlexey Lapshin     if (Error E =
1161f75da0c8SAlexey Lapshin             Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
1162f75da0c8SAlexey Lapshin                 Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1163f75da0c8SAlexey Lapshin       return std::move(E);
116486e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
1165f75da0c8SAlexey Lapshin     if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
1166f75da0c8SAlexey Lapshin                                      Arg->getValue(), SymbolMatchStyle,
1167f75da0c8SAlexey Lapshin                                      ErrorCallback))
1168f75da0c8SAlexey Lapshin       return std::move(E);
116986e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
1170f75da0c8SAlexey Lapshin     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
1171f75da0c8SAlexey Lapshin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1172f75da0c8SAlexey Lapshin       return std::move(E);
117386e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
1174f75da0c8SAlexey Lapshin     if (Error E =
1175f75da0c8SAlexey Lapshin             addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
1176f75da0c8SAlexey Lapshin                                SymbolMatchStyle, ErrorCallback))
1177f75da0c8SAlexey Lapshin       return std::move(E);
11784946cc37SIlia Kuklin   for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol))
11794946cc37SIlia Kuklin     if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create(
11804946cc37SIlia Kuklin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
11814946cc37SIlia Kuklin       return std::move(E);
11824946cc37SIlia Kuklin   for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols))
11834946cc37SIlia Kuklin     if (Error E =
11844946cc37SIlia Kuklin             addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(),
11854946cc37SIlia Kuklin                                SymbolMatchStyle, ErrorCallback))
11864946cc37SIlia Kuklin       return std::move(E);
1187f75da0c8SAlexey Lapshin   for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
1188f75da0c8SAlexey Lapshin     Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
1189f75da0c8SAlexey Lapshin     if (!SymInfo)
1190f75da0c8SAlexey Lapshin       return SymInfo.takeError();
1191f75da0c8SAlexey Lapshin 
1192f75da0c8SAlexey Lapshin     Config.SymbolsToAdd.push_back(*SymInfo);
1193f75da0c8SAlexey Lapshin   }
119407d8a457SIlia Kuklin   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbol_visibility)) {
119507d8a457SIlia Kuklin     if (!StringRef(Arg->getValue()).contains('='))
119607d8a457SIlia Kuklin       return createStringError(errc::invalid_argument,
119707d8a457SIlia Kuklin                                "bad format for --set-symbol-visibility");
119807d8a457SIlia Kuklin     auto [Sym, Visibility] = StringRef(Arg->getValue()).split('=');
119907d8a457SIlia Kuklin     Expected<uint8_t> Type = parseVisibilityType(Visibility);
120007d8a457SIlia Kuklin     if (!Type)
120107d8a457SIlia Kuklin       return Type.takeError();
120207d8a457SIlia Kuklin     ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type);
120307d8a457SIlia Kuklin     if (Error E = ELFConfig.SymbolsToSetVisibility.back().first.addMatcher(
120407d8a457SIlia Kuklin             NameOrPattern::create(Sym, SymbolMatchStyle, ErrorCallback)))
120507d8a457SIlia Kuklin       return std::move(E);
120607d8a457SIlia Kuklin   }
120707d8a457SIlia Kuklin   for (auto *Arg : InputArgs.filtered(OBJCOPY_set_symbols_visibility)) {
120807d8a457SIlia Kuklin     if (!StringRef(Arg->getValue()).contains('='))
120907d8a457SIlia Kuklin       return createStringError(errc::invalid_argument,
121007d8a457SIlia Kuklin                                "bad format for --set-symbols-visibility");
121107d8a457SIlia Kuklin     auto [File, Visibility] = StringRef(Arg->getValue()).split('=');
121207d8a457SIlia Kuklin     Expected<uint8_t> Type = parseVisibilityType(Visibility);
121307d8a457SIlia Kuklin     if (!Type)
121407d8a457SIlia Kuklin       return Type.takeError();
121507d8a457SIlia Kuklin     ELFConfig.SymbolsToSetVisibility.emplace_back(NameMatcher(), *Type);
121607d8a457SIlia Kuklin     if (Error E =
121707d8a457SIlia Kuklin             addSymbolsFromFile(ELFConfig.SymbolsToSetVisibility.back().first,
121807d8a457SIlia Kuklin                                DC.Alloc, File, SymbolMatchStyle, ErrorCallback))
121907d8a457SIlia Kuklin       return std::move(E);
122007d8a457SIlia Kuklin   }
1221f75da0c8SAlexey Lapshin 
1222f75da0c8SAlexey Lapshin   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
1223f75da0c8SAlexey Lapshin 
1224f75da0c8SAlexey Lapshin   Config.DeterministicArchives = InputArgs.hasFlag(
1225f75da0c8SAlexey Lapshin       OBJCOPY_enable_deterministic_archives,
1226f75da0c8SAlexey Lapshin       OBJCOPY_disable_deterministic_archives, /*default=*/true);
1227f75da0c8SAlexey Lapshin 
1228f75da0c8SAlexey Lapshin   Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
1229f75da0c8SAlexey Lapshin 
1230f75da0c8SAlexey Lapshin   if (Config.PreserveDates &&
1231f75da0c8SAlexey Lapshin       (Config.OutputFilename == "-" || Config.InputFilename == "-"))
1232f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
1233f75da0c8SAlexey Lapshin                              "--preserve-dates requires a file");
1234f75da0c8SAlexey Lapshin 
123586e8164aSKazu Hirata   for (auto *Arg : InputArgs)
1236f75da0c8SAlexey Lapshin     if (Arg->getOption().matches(OBJCOPY_set_start)) {
1237f75da0c8SAlexey Lapshin       auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
1238f75da0c8SAlexey Lapshin       if (!EAddr)
1239f75da0c8SAlexey Lapshin         return createStringError(
1240f75da0c8SAlexey Lapshin             EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
1241f75da0c8SAlexey Lapshin 
1242f75da0c8SAlexey Lapshin       ELFConfig.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
1243f75da0c8SAlexey Lapshin     } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
1244f75da0c8SAlexey Lapshin       auto EIncr = getAsInteger<int64_t>(Arg->getValue());
1245f75da0c8SAlexey Lapshin       if (!EIncr)
1246f75da0c8SAlexey Lapshin         return createStringError(EIncr.getError(),
1247f75da0c8SAlexey Lapshin                                  "bad entry point increment: '%s'",
1248f75da0c8SAlexey Lapshin                                  Arg->getValue());
1249f75da0c8SAlexey Lapshin       auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr)
1250f75da0c8SAlexey Lapshin                                       : [](uint64_t A) { return A; };
1251f75da0c8SAlexey Lapshin       ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
1252f75da0c8SAlexey Lapshin         return Expr(EAddr) + *EIncr;
1253f75da0c8SAlexey Lapshin       };
1254f75da0c8SAlexey Lapshin     }
1255f75da0c8SAlexey Lapshin 
1256*10772807SIgor Kudrin   for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_note)) {
1257*10772807SIgor Kudrin     Expected<RemoveNoteInfo> NoteInfo = parseRemoveNoteInfo(Arg->getValue());
1258*10772807SIgor Kudrin     if (!NoteInfo)
1259*10772807SIgor Kudrin       return NoteInfo.takeError();
1260*10772807SIgor Kudrin 
1261*10772807SIgor Kudrin     ELFConfig.NotesToRemove.push_back(*NoteInfo);
1262*10772807SIgor Kudrin   }
1263*10772807SIgor Kudrin 
1264*10772807SIgor Kudrin   if (!ELFConfig.NotesToRemove.empty()) {
1265*10772807SIgor Kudrin     if (!Config.ToRemove.empty())
1266*10772807SIgor Kudrin       return createStringError(
1267*10772807SIgor Kudrin           errc::invalid_argument,
1268*10772807SIgor Kudrin           "cannot specify both --remove-note and --remove-section");
1269*10772807SIgor Kudrin     if (!Config.AddSection.empty())
1270*10772807SIgor Kudrin       return createStringError(
1271*10772807SIgor Kudrin           errc::invalid_argument,
1272*10772807SIgor Kudrin           "cannot specify both --remove-note and --add-section");
1273*10772807SIgor Kudrin     if (!Config.UpdateSection.empty())
1274*10772807SIgor Kudrin       return createStringError(
1275*10772807SIgor Kudrin           errc::invalid_argument,
1276*10772807SIgor Kudrin           "cannot specify both --remove-note and --update-section");
1277*10772807SIgor Kudrin   }
1278*10772807SIgor Kudrin 
1279f75da0c8SAlexey Lapshin   if (Config.DecompressDebugSections &&
1280f75da0c8SAlexey Lapshin       Config.CompressionType != DebugCompressionType::None) {
1281f75da0c8SAlexey Lapshin     return createStringError(
1282f75da0c8SAlexey Lapshin         errc::invalid_argument,
1283f75da0c8SAlexey Lapshin         "cannot specify both --compress-debug-sections and "
1284f75da0c8SAlexey Lapshin         "--decompress-debug-sections");
1285f75da0c8SAlexey Lapshin   }
1286f75da0c8SAlexey Lapshin 
1287f75da0c8SAlexey Lapshin   if (Config.ExtractPartition && Config.ExtractMainPartition)
1288f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
1289f75da0c8SAlexey Lapshin                              "cannot specify --extract-partition together with "
1290f75da0c8SAlexey Lapshin                              "--extract-main-partition");
1291f75da0c8SAlexey Lapshin 
1292f75da0c8SAlexey Lapshin   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1293f75da0c8SAlexey Lapshin   return std::move(DC);
1294f75da0c8SAlexey Lapshin }
1295f75da0c8SAlexey Lapshin 
1296a91c77eeSNico Weber // parseInstallNameToolOptions returns the config and sets the input arguments.
1297a91c77eeSNico Weber // If a help flag is set then parseInstallNameToolOptions will print the help
1298f75da0c8SAlexey Lapshin // messege and exit.
1299f75da0c8SAlexey Lapshin Expected<DriverConfig>
1300f75da0c8SAlexey Lapshin objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
1301f75da0c8SAlexey Lapshin   DriverConfig DC;
1302f75da0c8SAlexey Lapshin   ConfigManager ConfigMgr;
1303f75da0c8SAlexey Lapshin   CommonConfig &Config = ConfigMgr.Common;
1304f75da0c8SAlexey Lapshin   MachOConfig &MachOConfig = ConfigMgr.MachO;
1305f75da0c8SAlexey Lapshin   InstallNameToolOptTable T;
1306f75da0c8SAlexey Lapshin   unsigned MissingArgumentIndex, MissingArgumentCount;
1307f75da0c8SAlexey Lapshin   llvm::opt::InputArgList InputArgs =
1308f75da0c8SAlexey Lapshin       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1309f75da0c8SAlexey Lapshin 
1310f75da0c8SAlexey Lapshin   if (MissingArgumentCount)
1311f75da0c8SAlexey Lapshin     return createStringError(
1312f75da0c8SAlexey Lapshin         errc::invalid_argument,
1313f75da0c8SAlexey Lapshin         "missing argument to " +
1314f75da0c8SAlexey Lapshin             StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
1315f75da0c8SAlexey Lapshin             " option");
1316f75da0c8SAlexey Lapshin 
1317f75da0c8SAlexey Lapshin   if (InputArgs.size() == 0) {
1318f75da0c8SAlexey Lapshin     printHelp(T, errs(), ToolType::InstallNameTool);
1319f75da0c8SAlexey Lapshin     exit(1);
1320f75da0c8SAlexey Lapshin   }
1321f75da0c8SAlexey Lapshin 
1322f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(INSTALL_NAME_TOOL_help)) {
1323f75da0c8SAlexey Lapshin     printHelp(T, outs(), ToolType::InstallNameTool);
1324f75da0c8SAlexey Lapshin     exit(0);
1325f75da0c8SAlexey Lapshin   }
1326f75da0c8SAlexey Lapshin 
1327f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(INSTALL_NAME_TOOL_version)) {
1328f75da0c8SAlexey Lapshin     outs() << "llvm-install-name-tool, compatible with cctools "
1329f75da0c8SAlexey Lapshin               "install_name_tool\n";
1330f75da0c8SAlexey Lapshin     cl::PrintVersionMessage();
1331f75da0c8SAlexey Lapshin     exit(0);
1332f75da0c8SAlexey Lapshin   }
1333f75da0c8SAlexey Lapshin 
133486e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
1335f75da0c8SAlexey Lapshin     MachOConfig.RPathToAdd.push_back(Arg->getValue());
1336f75da0c8SAlexey Lapshin 
1337f75da0c8SAlexey Lapshin   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
1338f75da0c8SAlexey Lapshin     MachOConfig.RPathToPrepend.push_back(Arg->getValue());
1339f75da0c8SAlexey Lapshin 
134086e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
1341f75da0c8SAlexey Lapshin     StringRef RPath = Arg->getValue();
1342f75da0c8SAlexey Lapshin 
1343f75da0c8SAlexey Lapshin     // Cannot add and delete the same rpath at the same time.
1344f75da0c8SAlexey Lapshin     if (is_contained(MachOConfig.RPathToAdd, RPath))
1345f75da0c8SAlexey Lapshin       return createStringError(
1346f75da0c8SAlexey Lapshin           errc::invalid_argument,
1347f75da0c8SAlexey Lapshin           "cannot specify both -add_rpath '%s' and -delete_rpath '%s'",
1348f75da0c8SAlexey Lapshin           RPath.str().c_str(), RPath.str().c_str());
1349f75da0c8SAlexey Lapshin     if (is_contained(MachOConfig.RPathToPrepend, RPath))
1350f75da0c8SAlexey Lapshin       return createStringError(
1351f75da0c8SAlexey Lapshin           errc::invalid_argument,
1352f75da0c8SAlexey Lapshin           "cannot specify both -prepend_rpath '%s' and -delete_rpath '%s'",
1353f75da0c8SAlexey Lapshin           RPath.str().c_str(), RPath.str().c_str());
1354f75da0c8SAlexey Lapshin 
1355f75da0c8SAlexey Lapshin     MachOConfig.RPathsToRemove.insert(RPath);
1356f75da0c8SAlexey Lapshin   }
1357f75da0c8SAlexey Lapshin 
1358f75da0c8SAlexey Lapshin   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_rpath)) {
1359f75da0c8SAlexey Lapshin     StringRef Old = Arg->getValue(0);
1360f75da0c8SAlexey Lapshin     StringRef New = Arg->getValue(1);
1361f75da0c8SAlexey Lapshin 
1362f75da0c8SAlexey Lapshin     auto Match = [=](StringRef RPath) { return RPath == Old || RPath == New; };
1363f75da0c8SAlexey Lapshin 
1364f75da0c8SAlexey Lapshin     // Cannot specify duplicate -rpath entries
1365f75da0c8SAlexey Lapshin     auto It1 = find_if(
1366f75da0c8SAlexey Lapshin         MachOConfig.RPathsToUpdate,
1367f75da0c8SAlexey Lapshin         [&Match](const DenseMap<StringRef, StringRef>::value_type &OldNew) {
1368f75da0c8SAlexey Lapshin           return Match(OldNew.getFirst()) || Match(OldNew.getSecond());
1369f75da0c8SAlexey Lapshin         });
1370f75da0c8SAlexey Lapshin     if (It1 != MachOConfig.RPathsToUpdate.end())
1371f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
1372f75da0c8SAlexey Lapshin                                "cannot specify both -rpath '" +
1373f75da0c8SAlexey Lapshin                                    It1->getFirst() + "' '" + It1->getSecond() +
1374f75da0c8SAlexey Lapshin                                    "' and -rpath '" + Old + "' '" + New + "'");
1375f75da0c8SAlexey Lapshin 
1376f75da0c8SAlexey Lapshin     // Cannot specify the same rpath under both -delete_rpath and -rpath
1377f75da0c8SAlexey Lapshin     auto It2 = find_if(MachOConfig.RPathsToRemove, Match);
1378f75da0c8SAlexey Lapshin     if (It2 != MachOConfig.RPathsToRemove.end())
1379f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
1380f75da0c8SAlexey Lapshin                                "cannot specify both -delete_rpath '" + *It2 +
1381f75da0c8SAlexey Lapshin                                    "' and -rpath '" + Old + "' '" + New + "'");
1382f75da0c8SAlexey Lapshin 
1383f75da0c8SAlexey Lapshin     // Cannot specify the same rpath under both -add_rpath and -rpath
1384f75da0c8SAlexey Lapshin     auto It3 = find_if(MachOConfig.RPathToAdd, Match);
1385f75da0c8SAlexey Lapshin     if (It3 != MachOConfig.RPathToAdd.end())
1386f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
1387f75da0c8SAlexey Lapshin                                "cannot specify both -add_rpath '" + *It3 +
1388f75da0c8SAlexey Lapshin                                    "' and -rpath '" + Old + "' '" + New + "'");
1389f75da0c8SAlexey Lapshin 
1390f75da0c8SAlexey Lapshin     // Cannot specify the same rpath under both -prepend_rpath and -rpath.
1391f75da0c8SAlexey Lapshin     auto It4 = find_if(MachOConfig.RPathToPrepend, Match);
1392f75da0c8SAlexey Lapshin     if (It4 != MachOConfig.RPathToPrepend.end())
1393f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
1394f75da0c8SAlexey Lapshin                                "cannot specify both -prepend_rpath '" + *It4 +
1395f75da0c8SAlexey Lapshin                                    "' and -rpath '" + Old + "' '" + New + "'");
1396f75da0c8SAlexey Lapshin 
1397f75da0c8SAlexey Lapshin     MachOConfig.RPathsToUpdate.insert({Old, New});
1398f75da0c8SAlexey Lapshin   }
1399f75da0c8SAlexey Lapshin 
1400f75da0c8SAlexey Lapshin   if (auto *Arg = InputArgs.getLastArg(INSTALL_NAME_TOOL_id)) {
1401f75da0c8SAlexey Lapshin     MachOConfig.SharedLibId = Arg->getValue();
1402f75da0c8SAlexey Lapshin     if (MachOConfig.SharedLibId->empty())
1403f75da0c8SAlexey Lapshin       return createStringError(errc::invalid_argument,
1404f75da0c8SAlexey Lapshin                                "cannot specify an empty id");
1405f75da0c8SAlexey Lapshin   }
1406f75da0c8SAlexey Lapshin 
1407f75da0c8SAlexey Lapshin   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_change))
1408f75da0c8SAlexey Lapshin     MachOConfig.InstallNamesToUpdate.insert(
1409f75da0c8SAlexey Lapshin         {Arg->getValue(0), Arg->getValue(1)});
1410f75da0c8SAlexey Lapshin 
1411f75da0c8SAlexey Lapshin   MachOConfig.RemoveAllRpaths =
1412f75da0c8SAlexey Lapshin       InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);
1413f75da0c8SAlexey Lapshin 
1414f75da0c8SAlexey Lapshin   SmallVector<StringRef, 2> Positional;
141586e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
1416f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1417f75da0c8SAlexey Lapshin                              Arg->getAsString(InputArgs).c_str());
141886e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
1419f75da0c8SAlexey Lapshin     Positional.push_back(Arg->getValue());
1420f75da0c8SAlexey Lapshin   if (Positional.empty())
1421f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument, "no input file specified");
1422f75da0c8SAlexey Lapshin   if (Positional.size() > 1)
1423f75da0c8SAlexey Lapshin     return createStringError(
1424f75da0c8SAlexey Lapshin         errc::invalid_argument,
1425f75da0c8SAlexey Lapshin         "llvm-install-name-tool expects a single input file");
1426f75da0c8SAlexey Lapshin   Config.InputFilename = Positional[0];
1427f75da0c8SAlexey Lapshin   Config.OutputFilename = Positional[0];
1428f75da0c8SAlexey Lapshin 
1429fa535452SKeith Smiley   Expected<OwningBinary<Binary>> BinaryOrErr =
1430fa535452SKeith Smiley       createBinary(Config.InputFilename);
1431fa535452SKeith Smiley   if (!BinaryOrErr)
1432fa535452SKeith Smiley     return createFileError(Config.InputFilename, BinaryOrErr.takeError());
1433fa535452SKeith Smiley   auto *Binary = (*BinaryOrErr).getBinary();
1434fa535452SKeith Smiley   if (!Binary->isMachO() && !Binary->isMachOUniversalBinary())
1435fa535452SKeith Smiley     return createStringError(errc::invalid_argument,
1436fa535452SKeith Smiley                              "input file: %s is not a Mach-O file",
1437fa535452SKeith Smiley                              Config.InputFilename.str().c_str());
1438fa535452SKeith Smiley 
1439f75da0c8SAlexey Lapshin   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1440f75da0c8SAlexey Lapshin   return std::move(DC);
1441f75da0c8SAlexey Lapshin }
1442f75da0c8SAlexey Lapshin 
1443f75da0c8SAlexey Lapshin Expected<DriverConfig>
144494fba14fSRichard Howell objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
144594fba14fSRichard Howell                                   function_ref<Error(Error)> ErrorCallback) {
1446f75da0c8SAlexey Lapshin   DriverConfig DC;
1447f75da0c8SAlexey Lapshin   ConfigManager ConfigMgr;
1448f75da0c8SAlexey Lapshin   CommonConfig &Config = ConfigMgr.Common;
144959172194SRichard Howell   MachOConfig &MachOConfig = ConfigMgr.MachO;
1450f75da0c8SAlexey Lapshin   BitcodeStripOptTable T;
1451f75da0c8SAlexey Lapshin   unsigned MissingArgumentIndex, MissingArgumentCount;
1452f75da0c8SAlexey Lapshin   opt::InputArgList InputArgs =
1453f75da0c8SAlexey Lapshin       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1454f75da0c8SAlexey Lapshin 
1455f75da0c8SAlexey Lapshin   if (InputArgs.size() == 0) {
1456f75da0c8SAlexey Lapshin     printHelp(T, errs(), ToolType::BitcodeStrip);
1457f75da0c8SAlexey Lapshin     exit(1);
1458f75da0c8SAlexey Lapshin   }
1459f75da0c8SAlexey Lapshin 
1460f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(BITCODE_STRIP_help)) {
1461f75da0c8SAlexey Lapshin     printHelp(T, outs(), ToolType::BitcodeStrip);
1462f75da0c8SAlexey Lapshin     exit(0);
1463f75da0c8SAlexey Lapshin   }
1464f75da0c8SAlexey Lapshin 
1465f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(BITCODE_STRIP_version)) {
1466f75da0c8SAlexey Lapshin     outs() << "llvm-bitcode-strip, compatible with cctools "
1467f75da0c8SAlexey Lapshin               "bitcode_strip\n";
1468f75da0c8SAlexey Lapshin     cl::PrintVersionMessage();
1469f75da0c8SAlexey Lapshin     exit(0);
1470f75da0c8SAlexey Lapshin   }
1471f75da0c8SAlexey Lapshin 
1472f75da0c8SAlexey Lapshin   for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_UNKNOWN))
1473f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1474f75da0c8SAlexey Lapshin                              Arg->getAsString(InputArgs).c_str());
1475f75da0c8SAlexey Lapshin 
1476f75da0c8SAlexey Lapshin   SmallVector<StringRef, 2> Positional;
1477f75da0c8SAlexey Lapshin   for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
1478f75da0c8SAlexey Lapshin     Positional.push_back(Arg->getValue());
1479f75da0c8SAlexey Lapshin   if (Positional.size() > 1)
1480f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
1481f75da0c8SAlexey Lapshin                              "llvm-bitcode-strip expects a single input file");
1482f75da0c8SAlexey Lapshin   assert(!Positional.empty());
1483f75da0c8SAlexey Lapshin   Config.InputFilename = Positional[0];
14848e6d2fe4SRichard Howell 
14858e6d2fe4SRichard Howell   if (!InputArgs.hasArg(BITCODE_STRIP_output)) {
14868e6d2fe4SRichard Howell     return createStringError(errc::invalid_argument,
14878e6d2fe4SRichard Howell                              "-o is a required argument");
14888e6d2fe4SRichard Howell   }
14898e6d2fe4SRichard Howell   Config.OutputFilename = InputArgs.getLastArgValue(BITCODE_STRIP_output);
1490f75da0c8SAlexey Lapshin 
149194fba14fSRichard Howell   if (!InputArgs.hasArg(BITCODE_STRIP_remove))
149294fba14fSRichard Howell     return createStringError(errc::invalid_argument, "no action specified");
149394fba14fSRichard Howell 
149459172194SRichard Howell   // We only support -r for now, which removes all bitcode sections and
149559172194SRichard Howell   // the __LLVM segment if it's now empty.
149694fba14fSRichard Howell   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1497d991aa91SKeith Smiley       "__LLVM,__asm", MatchStyle::Literal, ErrorCallback)));
1498d991aa91SKeith Smiley   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1499d991aa91SKeith Smiley       "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback)));
1500d991aa91SKeith Smiley   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
150194fba14fSRichard Howell       "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback)));
1502d991aa91SKeith Smiley   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1503d991aa91SKeith Smiley       "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback)));
1504d991aa91SKeith Smiley   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
1505d991aa91SKeith Smiley       "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback)));
150659172194SRichard Howell   MachOConfig.EmptySegmentsToRemove.insert("__LLVM");
150794fba14fSRichard Howell 
1508f75da0c8SAlexey Lapshin   DC.CopyConfigs.push_back(std::move(ConfigMgr));
1509f75da0c8SAlexey Lapshin   return std::move(DC);
1510f75da0c8SAlexey Lapshin }
1511f75da0c8SAlexey Lapshin 
1512a91c77eeSNico Weber // parseStripOptions returns the config and sets the input arguments. If a
1513a91c77eeSNico Weber // help flag is set then parseStripOptions will print the help messege and
1514f75da0c8SAlexey Lapshin // exit.
1515f75da0c8SAlexey Lapshin Expected<DriverConfig>
1516f75da0c8SAlexey Lapshin objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
1517f75da0c8SAlexey Lapshin                            function_ref<Error(Error)> ErrorCallback) {
1518f75da0c8SAlexey Lapshin   const char *const *DashDash =
1519ce9f007cSKazu Hirata       llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
152038818b60Sserge-sans-paille   ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
1521f75da0c8SAlexey Lapshin   if (DashDash != RawArgsArr.end())
1522f75da0c8SAlexey Lapshin     DashDash = std::next(DashDash);
1523f75da0c8SAlexey Lapshin 
1524f75da0c8SAlexey Lapshin   StripOptTable T;
1525f75da0c8SAlexey Lapshin   unsigned MissingArgumentIndex, MissingArgumentCount;
1526f75da0c8SAlexey Lapshin   llvm::opt::InputArgList InputArgs =
1527f75da0c8SAlexey Lapshin       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
1528f75da0c8SAlexey Lapshin 
1529f75da0c8SAlexey Lapshin   if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
1530f75da0c8SAlexey Lapshin     printHelp(T, errs(), ToolType::Strip);
1531f75da0c8SAlexey Lapshin     exit(1);
1532f75da0c8SAlexey Lapshin   }
1533f75da0c8SAlexey Lapshin 
1534f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(STRIP_help)) {
1535f75da0c8SAlexey Lapshin     printHelp(T, outs(), ToolType::Strip);
1536f75da0c8SAlexey Lapshin     exit(0);
1537f75da0c8SAlexey Lapshin   }
1538f75da0c8SAlexey Lapshin 
1539f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(STRIP_version)) {
1540f75da0c8SAlexey Lapshin     outs() << "llvm-strip, compatible with GNU strip\n";
1541f75da0c8SAlexey Lapshin     cl::PrintVersionMessage();
1542f75da0c8SAlexey Lapshin     exit(0);
1543f75da0c8SAlexey Lapshin   }
1544f75da0c8SAlexey Lapshin 
1545f75da0c8SAlexey Lapshin   SmallVector<StringRef, 2> Positional;
154686e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
1547f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument, "unknown argument '%s'",
1548f75da0c8SAlexey Lapshin                              Arg->getAsString(InputArgs).c_str());
154986e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
1550f75da0c8SAlexey Lapshin     Positional.push_back(Arg->getValue());
1551f75da0c8SAlexey Lapshin   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
1552f75da0c8SAlexey Lapshin 
1553f75da0c8SAlexey Lapshin   if (Positional.empty())
1554f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument, "no input file specified");
1555f75da0c8SAlexey Lapshin 
1556f75da0c8SAlexey Lapshin   if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
1557f75da0c8SAlexey Lapshin     return createStringError(
1558f75da0c8SAlexey Lapshin         errc::invalid_argument,
1559f75da0c8SAlexey Lapshin         "multiple input files cannot be used in combination with -o");
1560f75da0c8SAlexey Lapshin 
1561f75da0c8SAlexey Lapshin   ConfigManager ConfigMgr;
1562f75da0c8SAlexey Lapshin   CommonConfig &Config = ConfigMgr.Common;
1563f75da0c8SAlexey Lapshin   ELFConfig &ELFConfig = ConfigMgr.ELF;
1564f75da0c8SAlexey Lapshin   MachOConfig &MachOConfig = ConfigMgr.MachO;
1565f75da0c8SAlexey Lapshin 
1566f75da0c8SAlexey Lapshin   if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
1567f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
1568f75da0c8SAlexey Lapshin                              "--regex and --wildcard are incompatible");
1569f75da0c8SAlexey Lapshin   MatchStyle SectionMatchStyle =
1570f75da0c8SAlexey Lapshin       InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
1571f75da0c8SAlexey Lapshin   MatchStyle SymbolMatchStyle
1572f75da0c8SAlexey Lapshin       = InputArgs.hasArg(STRIP_regex)    ? MatchStyle::Regex
1573f75da0c8SAlexey Lapshin       : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard
1574f75da0c8SAlexey Lapshin                                          : MatchStyle::Literal;
1575f75da0c8SAlexey Lapshin   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
1576f75da0c8SAlexey Lapshin   Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
1577f75da0c8SAlexey Lapshin 
1578c37accf0SFangrui Song   if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals))
1579c37accf0SFangrui Song     Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all)
1580f75da0c8SAlexey Lapshin                              ? DiscardType::All
1581f75da0c8SAlexey Lapshin                              : DiscardType::Locals;
1582f75da0c8SAlexey Lapshin   Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
1583f75da0c8SAlexey Lapshin   Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
1584f75da0c8SAlexey Lapshin   if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
1585f75da0c8SAlexey Lapshin     Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
1586f75da0c8SAlexey Lapshin   Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
1587f75da0c8SAlexey Lapshin   MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
1588f75da0c8SAlexey Lapshin   Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
1589f75da0c8SAlexey Lapshin   ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
1590f75da0c8SAlexey Lapshin   MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
1591f75da0c8SAlexey Lapshin 
159286e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(STRIP_keep_section))
1593f75da0c8SAlexey Lapshin     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
1594f75da0c8SAlexey Lapshin             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1595f75da0c8SAlexey Lapshin       return std::move(E);
1596f75da0c8SAlexey Lapshin 
159786e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(STRIP_remove_section))
1598f75da0c8SAlexey Lapshin     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
1599f75da0c8SAlexey Lapshin             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
1600f75da0c8SAlexey Lapshin       return std::move(E);
1601f75da0c8SAlexey Lapshin 
160286e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol))
1603f75da0c8SAlexey Lapshin     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
1604f75da0c8SAlexey Lapshin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1605f75da0c8SAlexey Lapshin       return std::move(E);
1606f75da0c8SAlexey Lapshin 
160786e8164aSKazu Hirata   for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol))
1608f75da0c8SAlexey Lapshin     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
1609f75da0c8SAlexey Lapshin             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
1610f75da0c8SAlexey Lapshin       return std::move(E);
1611f75da0c8SAlexey Lapshin 
1612f75da0c8SAlexey Lapshin   if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
16133787de40SJohn McIver       !Config.OnlyKeepDebug && !Config.StripUnneeded &&
16143787de40SJohn McIver       Config.DiscardMode == DiscardType::None && !Config.StripAllGNU &&
16153787de40SJohn McIver       Config.SymbolsToRemove.empty())
1616f75da0c8SAlexey Lapshin     Config.StripAll = true;
1617f75da0c8SAlexey Lapshin 
1618f75da0c8SAlexey Lapshin   if (Config.DiscardMode == DiscardType::All) {
1619f75da0c8SAlexey Lapshin     Config.StripDebug = true;
1620f75da0c8SAlexey Lapshin     ELFConfig.KeepFileSymbols = true;
1621f75da0c8SAlexey Lapshin   }
1622f75da0c8SAlexey Lapshin 
1623f75da0c8SAlexey Lapshin   Config.DeterministicArchives =
1624f75da0c8SAlexey Lapshin       InputArgs.hasFlag(STRIP_enable_deterministic_archives,
1625f75da0c8SAlexey Lapshin                         STRIP_disable_deterministic_archives, /*default=*/true);
1626f75da0c8SAlexey Lapshin 
1627f75da0c8SAlexey Lapshin   Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
1628f75da0c8SAlexey Lapshin   Config.InputFormat = FileFormat::Unspecified;
1629f75da0c8SAlexey Lapshin   Config.OutputFormat = FileFormat::Unspecified;
1630f75da0c8SAlexey Lapshin 
1631f75da0c8SAlexey Lapshin   DriverConfig DC;
1632f75da0c8SAlexey Lapshin   if (Positional.size() == 1) {
1633f75da0c8SAlexey Lapshin     Config.InputFilename = Positional[0];
1634f75da0c8SAlexey Lapshin     Config.OutputFilename =
1635f75da0c8SAlexey Lapshin         InputArgs.getLastArgValue(STRIP_output, Positional[0]);
1636f75da0c8SAlexey Lapshin     DC.CopyConfigs.push_back(std::move(ConfigMgr));
1637f75da0c8SAlexey Lapshin   } else {
1638f75da0c8SAlexey Lapshin     StringMap<unsigned> InputFiles;
1639f75da0c8SAlexey Lapshin     for (StringRef Filename : Positional) {
1640f75da0c8SAlexey Lapshin       if (InputFiles[Filename]++ == 1) {
1641f75da0c8SAlexey Lapshin         if (Filename == "-")
1642f75da0c8SAlexey Lapshin           return createStringError(
1643f75da0c8SAlexey Lapshin               errc::invalid_argument,
1644f75da0c8SAlexey Lapshin               "cannot specify '-' as an input file more than once");
1645f75da0c8SAlexey Lapshin         if (Error E = ErrorCallback(createStringError(
1646f75da0c8SAlexey Lapshin                 errc::invalid_argument, "'%s' was already specified",
1647f75da0c8SAlexey Lapshin                 Filename.str().c_str())))
1648f75da0c8SAlexey Lapshin           return std::move(E);
1649f75da0c8SAlexey Lapshin       }
1650f75da0c8SAlexey Lapshin       Config.InputFilename = Filename;
1651f75da0c8SAlexey Lapshin       Config.OutputFilename = Filename;
1652f75da0c8SAlexey Lapshin       DC.CopyConfigs.push_back(ConfigMgr);
1653f75da0c8SAlexey Lapshin     }
1654f75da0c8SAlexey Lapshin   }
1655f75da0c8SAlexey Lapshin 
1656f75da0c8SAlexey Lapshin   if (Config.PreserveDates && (is_contained(Positional, "-") ||
1657f75da0c8SAlexey Lapshin                                InputArgs.getLastArgValue(STRIP_output) == "-"))
1658f75da0c8SAlexey Lapshin     return createStringError(errc::invalid_argument,
1659f75da0c8SAlexey Lapshin                              "--preserve-dates requires a file");
1660f75da0c8SAlexey Lapshin 
1661f75da0c8SAlexey Lapshin   return std::move(DC);
1662f75da0c8SAlexey Lapshin }
1663