xref: /llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp (revision a42dec7a1b905fff024fad2c4e02f5b070e3d0c7)
1 //===- llvm-objcopy.cpp ---------------------------------------------------===//
2 //
3 //                      The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm-objcopy.h"
11 #include "Object.h"
12 #include "llvm/ADT/BitmaskEnum.h"
13 #include "llvm/ADT/Optional.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/BinaryFormat/ELF.h"
19 #include "llvm/Object/Archive.h"
20 #include "llvm/Object/ArchiveWriter.h"
21 #include "llvm/Object/Binary.h"
22 #include "llvm/Object/ELFObjectFile.h"
23 #include "llvm/Object/ELFTypes.h"
24 #include "llvm/Object/Error.h"
25 #include "llvm/Option/Arg.h"
26 #include "llvm/Option/ArgList.h"
27 #include "llvm/Option/Option.h"
28 #include "llvm/Support/Casting.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/Error.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/ErrorOr.h"
34 #include "llvm/Support/FileOutputBuffer.h"
35 #include "llvm/Support/InitLLVM.h"
36 #include "llvm/Support/Path.h"
37 #include "llvm/Support/raw_ostream.h"
38 #include <algorithm>
39 #include <cassert>
40 #include <cstdlib>
41 #include <functional>
42 #include <iterator>
43 #include <memory>
44 #include <string>
45 #include <system_error>
46 #include <utility>
47 
48 using namespace llvm;
49 using namespace llvm::objcopy;
50 using namespace object;
51 using namespace ELF;
52 
53 namespace {
54 
55 enum ObjcopyID {
56   OBJCOPY_INVALID = 0, // This is not an option ID.
57 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
58                HELPTEXT, METAVAR, VALUES)                                      \
59   OBJCOPY_##ID,
60 #include "ObjcopyOpts.inc"
61 #undef OPTION
62 };
63 
64 #define PREFIX(NAME, VALUE) const char *const OBJCOPY_##NAME[] = VALUE;
65 #include "ObjcopyOpts.inc"
66 #undef PREFIX
67 
68 static const opt::OptTable::Info ObjcopyInfoTable[] = {
69 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
70                HELPTEXT, METAVAR, VALUES)                                      \
71   {OBJCOPY_##PREFIX,                                                           \
72    NAME,                                                                       \
73    HELPTEXT,                                                                   \
74    METAVAR,                                                                    \
75    OBJCOPY_##ID,                                                               \
76    opt::Option::KIND##Class,                                                   \
77    PARAM,                                                                      \
78    FLAGS,                                                                      \
79    OBJCOPY_##GROUP,                                                            \
80    OBJCOPY_##ALIAS,                                                            \
81    ALIASARGS,                                                                  \
82    VALUES},
83 #include "ObjcopyOpts.inc"
84 #undef OPTION
85 };
86 
87 class ObjcopyOptTable : public opt::OptTable {
88 public:
89   ObjcopyOptTable() : OptTable(ObjcopyInfoTable, true) {}
90 };
91 
92 enum StripID {
93   STRIP_INVALID = 0, // This is not an option ID.
94 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
95                HELPTEXT, METAVAR, VALUES)                                      \
96   STRIP_##ID,
97 #include "StripOpts.inc"
98 #undef OPTION
99 };
100 
101 #define PREFIX(NAME, VALUE) const char *const STRIP_##NAME[] = VALUE;
102 #include "StripOpts.inc"
103 #undef PREFIX
104 
105 static const opt::OptTable::Info StripInfoTable[] = {
106 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
107                HELPTEXT, METAVAR, VALUES)                                      \
108   {STRIP_##PREFIX, NAME,       HELPTEXT,                                       \
109    METAVAR,        STRIP_##ID, opt::Option::KIND##Class,                       \
110    PARAM,          FLAGS,      STRIP_##GROUP,                                  \
111    STRIP_##ALIAS,  ALIASARGS,  VALUES},
112 #include "StripOpts.inc"
113 #undef OPTION
114 };
115 
116 class StripOptTable : public opt::OptTable {
117 public:
118   StripOptTable() : OptTable(StripInfoTable, true) {}
119 };
120 
121 struct SectionRename {
122   StringRef OriginalName;
123   StringRef NewName;
124   Optional<uint64_t> NewFlags;
125 };
126 
127 struct CopyConfig {
128   StringRef OutputFilename;
129   StringRef InputFilename;
130   StringRef OutputFormat;
131   StringRef InputFormat;
132   StringRef BinaryArch;
133 
134   StringRef SplitDWO;
135   StringRef AddGnuDebugLink;
136   std::vector<StringRef> ToRemove;
137   std::vector<StringRef> Keep;
138   std::vector<StringRef> OnlyKeep;
139   std::vector<StringRef> AddSection;
140   std::vector<StringRef> DumpSection;
141   std::vector<StringRef> SymbolsToLocalize;
142   std::vector<StringRef> SymbolsToGlobalize;
143   std::vector<StringRef> SymbolsToWeaken;
144   std::vector<StringRef> SymbolsToRemove;
145   std::vector<StringRef> SymbolsToKeep;
146   StringMap<SectionRename> SectionsToRename;
147   StringMap<StringRef> SymbolsToRename;
148   bool StripAll = false;
149   bool StripAllGNU = false;
150   bool StripDebug = false;
151   bool StripSections = false;
152   bool StripNonAlloc = false;
153   bool StripDWO = false;
154   bool StripUnneeded = false;
155   bool ExtractDWO = false;
156   bool LocalizeHidden = false;
157   bool Weaken = false;
158   bool DiscardAll = false;
159   bool OnlyKeepDebug = false;
160   bool KeepFileSymbols = false;
161 };
162 
163 using SectionPred = std::function<bool(const SectionBase &Sec)>;
164 
165 enum SectionFlag {
166   SecNone = 0,
167   SecAlloc = 1 << 0,
168   SecLoad = 1 << 1,
169   SecNoload = 1 << 2,
170   SecReadonly = 1 << 3,
171   SecDebug = 1 << 4,
172   SecCode = 1 << 5,
173   SecData = 1 << 6,
174   SecRom = 1 << 7,
175   SecMerge = 1 << 8,
176   SecStrings = 1 << 9,
177   SecContents = 1 << 10,
178   SecShare = 1 << 11,
179   LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ SecShare)
180 };
181 
182 } // namespace
183 
184 namespace llvm {
185 namespace objcopy {
186 
187 // The name this program was invoked as.
188 StringRef ToolName;
189 
190 LLVM_ATTRIBUTE_NORETURN void error(Twine Message) {
191   errs() << ToolName << ": " << Message << ".\n";
192   errs().flush();
193   exit(1);
194 }
195 
196 LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) {
197   assert(EC);
198   errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n";
199   exit(1);
200 }
201 
202 LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, Error E) {
203   assert(E);
204   std::string Buf;
205   raw_string_ostream OS(Buf);
206   logAllUnhandledErrors(std::move(E), OS, "");
207   OS.flush();
208   errs() << ToolName << ": '" << File << "': " << Buf;
209   exit(1);
210 }
211 
212 } // end namespace objcopy
213 } // end namespace llvm
214 
215 static SectionFlag ParseSectionRenameFlag(StringRef SectionName) {
216   return llvm::StringSwitch<SectionFlag>(SectionName)
217       .Case("alloc", SectionFlag::SecAlloc)
218       .Case("load", SectionFlag::SecLoad)
219       .Case("noload", SectionFlag::SecNoload)
220       .Case("readonly", SectionFlag::SecReadonly)
221       .Case("debug", SectionFlag::SecDebug)
222       .Case("code", SectionFlag::SecCode)
223       .Case("data", SectionFlag::SecData)
224       .Case("rom", SectionFlag::SecRom)
225       .Case("merge", SectionFlag::SecMerge)
226       .Case("strings", SectionFlag::SecStrings)
227       .Case("contents", SectionFlag::SecContents)
228       .Case("share", SectionFlag::SecShare)
229       .Default(SectionFlag::SecNone);
230 }
231 
232 static SectionRename ParseRenameSectionValue(StringRef FlagValue) {
233   if (!FlagValue.contains('='))
234     error("Bad format for --rename-section: missing '='");
235 
236   // Initial split: ".foo" = ".bar,f1,f2,..."
237   auto Old2New = FlagValue.split('=');
238   SectionRename SR;
239   SR.OriginalName = Old2New.first;
240 
241   // Flags split: ".bar" "f1" "f2" ...
242   SmallVector<StringRef, 6> NameAndFlags;
243   Old2New.second.split(NameAndFlags, ',');
244   SR.NewName = NameAndFlags[0];
245 
246   if (NameAndFlags.size() > 1) {
247     SectionFlag Flags = SectionFlag::SecNone;
248     for (size_t I = 1, Size = NameAndFlags.size(); I < Size; ++I) {
249       SectionFlag Flag = ParseSectionRenameFlag(NameAndFlags[I]);
250       if (Flag == SectionFlag::SecNone)
251         error("Unrecognized section flag '" + NameAndFlags[I] +
252               "'. Flags supported for GNU compatibility: alloc, load, noload, "
253               "readonly, debug, code, data, rom, share, contents, merge, "
254               "strings.");
255       Flags |= Flag;
256     }
257 
258     SR.NewFlags = 0;
259     if (Flags & SectionFlag::SecAlloc)
260       *SR.NewFlags |= ELF::SHF_ALLOC;
261     if (!(Flags & SectionFlag::SecReadonly))
262       *SR.NewFlags |= ELF::SHF_WRITE;
263     if (Flags & SectionFlag::SecCode)
264       *SR.NewFlags |= ELF::SHF_EXECINSTR;
265     if (Flags & SectionFlag::SecMerge)
266       *SR.NewFlags |= ELF::SHF_MERGE;
267     if (Flags & SectionFlag::SecStrings)
268       *SR.NewFlags |= ELF::SHF_STRINGS;
269   }
270 
271   return SR;
272 }
273 
274 static bool IsDebugSection(const SectionBase &Sec) {
275   return Sec.Name.startswith(".debug") || Sec.Name.startswith(".zdebug") ||
276          Sec.Name == ".gdb_index";
277 }
278 
279 static bool IsDWOSection(const SectionBase &Sec) {
280   return Sec.Name.endswith(".dwo");
281 }
282 
283 static bool OnlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {
284   // We can't remove the section header string table.
285   if (&Sec == Obj.SectionNames)
286     return false;
287   // Short of keeping the string table we want to keep everything that is a DWO
288   // section and remove everything else.
289   return !IsDWOSection(Sec);
290 }
291 
292 static std::unique_ptr<Writer> CreateWriter(const CopyConfig &Config,
293                                             Object &Obj, Buffer &Buf,
294                                             ElfType OutputElfType) {
295   if (Config.OutputFormat == "binary") {
296     return llvm::make_unique<BinaryWriter>(Obj, Buf);
297   }
298   // Depending on the initial ELFT and OutputFormat we need a different Writer.
299   switch (OutputElfType) {
300   case ELFT_ELF32LE:
301     return llvm::make_unique<ELFWriter<ELF32LE>>(Obj, Buf,
302                                                  !Config.StripSections);
303   case ELFT_ELF64LE:
304     return llvm::make_unique<ELFWriter<ELF64LE>>(Obj, Buf,
305                                                  !Config.StripSections);
306   case ELFT_ELF32BE:
307     return llvm::make_unique<ELFWriter<ELF32BE>>(Obj, Buf,
308                                                  !Config.StripSections);
309   case ELFT_ELF64BE:
310     return llvm::make_unique<ELFWriter<ELF64BE>>(Obj, Buf,
311                                                  !Config.StripSections);
312   }
313   llvm_unreachable("Invalid output format");
314 }
315 
316 static void SplitDWOToFile(const CopyConfig &Config, const Reader &Reader,
317                            StringRef File, ElfType OutputElfType) {
318   auto DWOFile = Reader.create();
319   DWOFile->removeSections(
320       [&](const SectionBase &Sec) { return OnlyKeepDWOPred(*DWOFile, Sec); });
321   FileBuffer FB(File);
322   auto Writer = CreateWriter(Config, *DWOFile, FB, OutputElfType);
323   Writer->finalize();
324   Writer->write();
325 }
326 
327 static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
328                                Object &Obj) {
329   for (auto &Sec : Obj.sections()) {
330     if (Sec.Name == SecName) {
331       if (Sec.OriginalData.size() == 0)
332         return make_error<StringError>("Can't dump section \"" + SecName +
333                                            "\": it has no contents",
334                                        object_error::parse_failed);
335       Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
336           FileOutputBuffer::create(Filename, Sec.OriginalData.size());
337       if (!BufferOrErr)
338         return BufferOrErr.takeError();
339       std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
340       std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(),
341                 Buf->getBufferStart());
342       if (Error E = Buf->commit())
343         return E;
344       return Error::success();
345     }
346   }
347   return make_error<StringError>("Section not found",
348                                  object_error::parse_failed);
349 }
350 
351 // This function handles the high level operations of GNU objcopy including
352 // handling command line options. It's important to outline certain properties
353 // we expect to hold of the command line operations. Any operation that "keeps"
354 // should keep regardless of a remove. Additionally any removal should respect
355 // any previous removals. Lastly whether or not something is removed shouldn't
356 // depend a) on the order the options occur in or b) on some opaque priority
357 // system. The only priority is that keeps/copies overrule removes.
358 static void HandleArgs(const CopyConfig &Config, Object &Obj,
359                        const Reader &Reader, ElfType OutputElfType) {
360 
361   if (!Config.SplitDWO.empty()) {
362     SplitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType);
363   }
364 
365   // TODO: update or remove symbols only if there is an option that affects
366   // them.
367   if (Obj.SymbolTable) {
368     Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
369       if ((Config.LocalizeHidden &&
370            (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
371           (!Config.SymbolsToLocalize.empty() &&
372            is_contained(Config.SymbolsToLocalize, Sym.Name)))
373         Sym.Binding = STB_LOCAL;
374 
375       if (!Config.SymbolsToGlobalize.empty() &&
376           is_contained(Config.SymbolsToGlobalize, Sym.Name))
377         Sym.Binding = STB_GLOBAL;
378 
379       if (!Config.SymbolsToWeaken.empty() &&
380           is_contained(Config.SymbolsToWeaken, Sym.Name) &&
381           Sym.Binding == STB_GLOBAL)
382         Sym.Binding = STB_WEAK;
383 
384       if (Config.Weaken && Sym.Binding == STB_GLOBAL &&
385           Sym.getShndx() != SHN_UNDEF)
386         Sym.Binding = STB_WEAK;
387 
388       const auto I = Config.SymbolsToRename.find(Sym.Name);
389       if (I != Config.SymbolsToRename.end())
390         Sym.Name = I->getValue();
391     });
392 
393     // The purpose of this loop is to mark symbols referenced by sections
394     // (like GroupSection or RelocationSection). This way, we know which
395     // symbols are still 'needed' and wich are not.
396     if (Config.StripUnneeded) {
397       for (auto &Section : Obj.sections())
398         Section.markSymbols();
399     }
400 
401     Obj.removeSymbols([&](const Symbol &Sym) {
402       if ((!Config.SymbolsToKeep.empty() &&
403            is_contained(Config.SymbolsToKeep, Sym.Name)) ||
404           (Config.KeepFileSymbols && Sym.Type == STT_FILE))
405         return false;
406 
407       if (Config.DiscardAll && Sym.Binding == STB_LOCAL &&
408           Sym.getShndx() != SHN_UNDEF && Sym.Type != STT_FILE &&
409           Sym.Type != STT_SECTION)
410         return true;
411 
412       if (Config.StripAll || Config.StripAllGNU)
413         return true;
414 
415       if (!Config.SymbolsToRemove.empty() &&
416           is_contained(Config.SymbolsToRemove, Sym.Name)) {
417         return true;
418       }
419 
420       if (Config.StripUnneeded && !Sym.Referenced &&
421           (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&
422           Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
423         return true;
424 
425       return false;
426     });
427   }
428 
429   SectionPred RemovePred = [](const SectionBase &) { return false; };
430 
431   // Removes:
432   if (!Config.ToRemove.empty()) {
433     RemovePred = [&Config](const SectionBase &Sec) {
434       return find(Config.ToRemove, Sec.Name) != Config.ToRemove.end();
435     };
436   }
437 
438   if (Config.StripDWO || !Config.SplitDWO.empty())
439     RemovePred = [RemovePred](const SectionBase &Sec) {
440       return IsDWOSection(Sec) || RemovePred(Sec);
441     };
442 
443   if (Config.ExtractDWO)
444     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
445       return OnlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);
446     };
447 
448   if (Config.StripAllGNU)
449     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
450       if (RemovePred(Sec))
451         return true;
452       if ((Sec.Flags & SHF_ALLOC) != 0)
453         return false;
454       if (&Sec == Obj.SectionNames)
455         return false;
456       switch (Sec.Type) {
457       case SHT_SYMTAB:
458       case SHT_REL:
459       case SHT_RELA:
460       case SHT_STRTAB:
461         return true;
462       }
463       return IsDebugSection(Sec);
464     };
465 
466   if (Config.StripSections) {
467     RemovePred = [RemovePred](const SectionBase &Sec) {
468       return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0;
469     };
470   }
471 
472   if (Config.StripDebug) {
473     RemovePred = [RemovePred](const SectionBase &Sec) {
474       return RemovePred(Sec) || IsDebugSection(Sec);
475     };
476   }
477 
478   if (Config.StripNonAlloc)
479     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
480       if (RemovePred(Sec))
481         return true;
482       if (&Sec == Obj.SectionNames)
483         return false;
484       return (Sec.Flags & SHF_ALLOC) == 0;
485     };
486 
487   if (Config.StripAll)
488     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
489       if (RemovePred(Sec))
490         return true;
491       if (&Sec == Obj.SectionNames)
492         return false;
493       if (Sec.Name.startswith(".gnu.warning"))
494         return false;
495       return (Sec.Flags & SHF_ALLOC) == 0;
496     };
497 
498   // Explicit copies:
499   if (!Config.OnlyKeep.empty()) {
500     RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {
501       // Explicitly keep these sections regardless of previous removes.
502       if (find(Config.OnlyKeep, Sec.Name) != Config.OnlyKeep.end())
503         return false;
504 
505       // Allow all implicit removes.
506       if (RemovePred(Sec))
507         return true;
508 
509       // Keep special sections.
510       if (Obj.SectionNames == &Sec)
511         return false;
512       if (Obj.SymbolTable == &Sec ||
513           (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec))
514         return false;
515 
516       // Remove everything else.
517       return true;
518     };
519   }
520 
521   if (!Config.Keep.empty()) {
522     RemovePred = [Config, RemovePred](const SectionBase &Sec) {
523       // Explicitly keep these sections regardless of previous removes.
524       if (find(Config.Keep, Sec.Name) != Config.Keep.end())
525         return false;
526       // Otherwise defer to RemovePred.
527       return RemovePred(Sec);
528     };
529   }
530 
531   // This has to be the last predicate assignment.
532   // If the option --keep-symbol has been specified
533   // and at least one of those symbols is present
534   // (equivalently, the updated symbol table is not empty)
535   // the symbol table and the string table should not be removed.
536   if ((!Config.SymbolsToKeep.empty() || Config.KeepFileSymbols) &&
537       Obj.SymbolTable && !Obj.SymbolTable->empty()) {
538     RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {
539       if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
540         return false;
541       return RemovePred(Sec);
542     };
543   }
544 
545   Obj.removeSections(RemovePred);
546 
547   if (!Config.SectionsToRename.empty()) {
548     for (auto &Sec : Obj.sections()) {
549       const auto Iter = Config.SectionsToRename.find(Sec.Name);
550       if (Iter != Config.SectionsToRename.end()) {
551         const SectionRename &SR = Iter->second;
552         Sec.Name = SR.NewName;
553         if (SR.NewFlags.hasValue()) {
554           // Preserve some flags which should not be dropped when setting flags.
555           // Also, preserve anything OS/processor dependant.
556           const uint64_t PreserveMask = ELF::SHF_COMPRESSED | ELF::SHF_EXCLUDE |
557                                         ELF::SHF_GROUP | ELF::SHF_LINK_ORDER |
558                                         ELF::SHF_MASKOS | ELF::SHF_MASKPROC |
559                                         ELF::SHF_TLS | ELF::SHF_INFO_LINK;
560           Sec.Flags = (Sec.Flags & PreserveMask) |
561                       (SR.NewFlags.getValue() & ~PreserveMask);
562         }
563       }
564     }
565   }
566 
567   if (!Config.AddSection.empty()) {
568     for (const auto &Flag : Config.AddSection) {
569       auto SecPair = Flag.split("=");
570       auto SecName = SecPair.first;
571       auto File = SecPair.second;
572       auto BufOrErr = MemoryBuffer::getFile(File);
573       if (!BufOrErr)
574         reportError(File, BufOrErr.getError());
575       auto Buf = std::move(*BufOrErr);
576       auto BufPtr = reinterpret_cast<const uint8_t *>(Buf->getBufferStart());
577       auto BufSize = Buf->getBufferSize();
578       Obj.addSection<OwnedDataSection>(SecName,
579                                        ArrayRef<uint8_t>(BufPtr, BufSize));
580     }
581   }
582 
583   if (!Config.DumpSection.empty()) {
584     for (const auto &Flag : Config.DumpSection) {
585       std::pair<StringRef, StringRef> SecPair = Flag.split("=");
586       StringRef SecName = SecPair.first;
587       StringRef File = SecPair.second;
588       if (Error E = dumpSectionToFile(SecName, File, Obj))
589         reportError(Config.InputFilename, std::move(E));
590     }
591   }
592 
593   if (!Config.AddGnuDebugLink.empty())
594     Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink);
595 }
596 
597 static void ExecuteElfObjcopyOnBinary(const CopyConfig &Config, Binary &Binary,
598                                       Buffer &Out) {
599   ELFReader Reader(&Binary);
600   std::unique_ptr<Object> Obj = Reader.create();
601 
602   HandleArgs(Config, *Obj, Reader, Reader.getElfType());
603 
604   std::unique_ptr<Writer> Writer =
605       CreateWriter(Config, *Obj, Out, Reader.getElfType());
606   Writer->finalize();
607   Writer->write();
608 }
609 
610 // For regular archives this function simply calls llvm::writeArchive,
611 // For thin archives it writes the archive file itself as well as its members.
612 static Error deepWriteArchive(StringRef ArcName,
613                               ArrayRef<NewArchiveMember> NewMembers,
614                               bool WriteSymtab, object::Archive::Kind Kind,
615                               bool Deterministic, bool Thin) {
616   Error E =
617       writeArchive(ArcName, NewMembers, WriteSymtab, Kind, Deterministic, Thin);
618   if (!Thin || E)
619     return E;
620   for (const NewArchiveMember &Member : NewMembers) {
621     // Internally, FileBuffer will use the buffer created by
622     // FileOutputBuffer::create, for regular files (that is the case for
623     // deepWriteArchive) FileOutputBuffer::create will return OnDiskBuffer.
624     // OnDiskBuffer uses a temporary file and then renames it. So in reality
625     // there is no inefficiency / duplicated in-memory buffers in this case. For
626     // now in-memory buffers can not be completely avoided since
627     // NewArchiveMember still requires them even though writeArchive does not
628     // write them on disk.
629     FileBuffer FB(Member.MemberName);
630     FB.allocate(Member.Buf->getBufferSize());
631     std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
632               FB.getBufferStart());
633     if (auto E = FB.commit())
634       return E;
635   }
636   return Error::success();
637 }
638 
639 static void ExecuteElfObjcopyOnArchive(const CopyConfig &Config,
640                                        const Archive &Ar) {
641   std::vector<NewArchiveMember> NewArchiveMembers;
642   Error Err = Error::success();
643   for (const Archive::Child &Child : Ar.children(Err)) {
644     Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
645     if (!ChildOrErr)
646       reportError(Ar.getFileName(), ChildOrErr.takeError());
647     Expected<StringRef> ChildNameOrErr = Child.getName();
648     if (!ChildNameOrErr)
649       reportError(Ar.getFileName(), ChildNameOrErr.takeError());
650 
651     MemBuffer MB(ChildNameOrErr.get());
652     ExecuteElfObjcopyOnBinary(Config, **ChildOrErr, MB);
653 
654     Expected<NewArchiveMember> Member =
655         NewArchiveMember::getOldMember(Child, true);
656     if (!Member)
657       reportError(Ar.getFileName(), Member.takeError());
658     Member->Buf = MB.releaseMemoryBuffer();
659     Member->MemberName = Member->Buf->getBufferIdentifier();
660     NewArchiveMembers.push_back(std::move(*Member));
661   }
662 
663   if (Err)
664     reportError(Config.InputFilename, std::move(Err));
665   if (Error E =
666           deepWriteArchive(Config.OutputFilename, NewArchiveMembers,
667                            Ar.hasSymbolTable(), Ar.kind(), true, Ar.isThin()))
668     reportError(Config.OutputFilename, std::move(E));
669 }
670 
671 static void ExecuteElfObjcopy(const CopyConfig &Config) {
672   Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
673       createBinary(Config.InputFilename);
674   if (!BinaryOrErr)
675     reportError(Config.InputFilename, BinaryOrErr.takeError());
676 
677   if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary()))
678     return ExecuteElfObjcopyOnArchive(Config, *Ar);
679 
680   FileBuffer FB(Config.OutputFilename);
681   ExecuteElfObjcopyOnBinary(Config, *BinaryOrErr.get().getBinary(), FB);
682 }
683 
684 // ParseObjcopyOptions returns the config and sets the input arguments. If a
685 // help flag is set then ParseObjcopyOptions will print the help messege and
686 // exit.
687 static CopyConfig ParseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
688   ObjcopyOptTable T;
689   unsigned MissingArgumentIndex, MissingArgumentCount;
690   llvm::opt::InputArgList InputArgs =
691       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
692 
693   if (InputArgs.size() == 0) {
694     T.PrintHelp(errs(), "llvm-objcopy <input> [ <output> ]", "objcopy tool");
695     exit(1);
696   }
697 
698   if (InputArgs.hasArg(OBJCOPY_help)) {
699     T.PrintHelp(outs(), "llvm-objcopy <input> [ <output> ]", "objcopy tool");
700     exit(0);
701   }
702 
703   SmallVector<const char *, 2> Positional;
704 
705   for (auto Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
706     error("unknown argument '" + Arg->getAsString(InputArgs) + "'");
707 
708   for (auto Arg : InputArgs.filtered(OBJCOPY_INPUT))
709     Positional.push_back(Arg->getValue());
710 
711   if (Positional.empty())
712     error("No input file specified");
713 
714   if (Positional.size() > 2)
715     error("Too many positional arguments");
716 
717   CopyConfig Config;
718   Config.InputFilename = Positional[0];
719   Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
720   Config.InputFormat = InputArgs.getLastArgValue(OBJCOPY_input_target);
721   Config.OutputFormat = InputArgs.getLastArgValue(OBJCOPY_output_target);
722   Config.BinaryArch = InputArgs.getLastArgValue(OBJCOPY_binary_architecture);
723 
724   Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
725   Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
726 
727   for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
728     if (!StringRef(Arg->getValue()).contains('='))
729       error("Bad format for --redefine-sym");
730     auto Old2New = StringRef(Arg->getValue()).split('=');
731     if (!Config.SymbolsToRename.insert(Old2New).second)
732       error("Multiple redefinition of symbol " + Old2New.first);
733   }
734 
735   for (auto Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
736     SectionRename SR = ParseRenameSectionValue(StringRef(Arg->getValue()));
737     if (!Config.SectionsToRename.try_emplace(SR.OriginalName, SR).second)
738       error("Multiple renames of section " + SR.OriginalName);
739   }
740 
741   for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section))
742     Config.ToRemove.push_back(Arg->getValue());
743   for (auto Arg : InputArgs.filtered(OBJCOPY_keep))
744     Config.Keep.push_back(Arg->getValue());
745   for (auto Arg : InputArgs.filtered(OBJCOPY_only_keep))
746     Config.OnlyKeep.push_back(Arg->getValue());
747   for (auto Arg : InputArgs.filtered(OBJCOPY_add_section))
748     Config.AddSection.push_back(Arg->getValue());
749   for (auto Arg : InputArgs.filtered(OBJCOPY_dump_section))
750     Config.DumpSection.push_back(Arg->getValue());
751   Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
752   Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
753   Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
754   Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
755   Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
756   Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
757   Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
758   Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
759   Config.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
760   Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
761   Config.DiscardAll = InputArgs.hasArg(OBJCOPY_discard_all);
762   Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
763   Config.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
764   for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
765     Config.SymbolsToLocalize.push_back(Arg->getValue());
766   for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
767     Config.SymbolsToGlobalize.push_back(Arg->getValue());
768   for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
769     Config.SymbolsToWeaken.push_back(Arg->getValue());
770   for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
771     Config.SymbolsToRemove.push_back(Arg->getValue());
772   for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
773     Config.SymbolsToKeep.push_back(Arg->getValue());
774 
775   return Config;
776 }
777 
778 // ParseStripOptions returns the config and sets the input arguments. If a
779 // help flag is set then ParseStripOptions will print the help messege and
780 // exit.
781 static CopyConfig ParseStripOptions(ArrayRef<const char *> ArgsArr) {
782   StripOptTable T;
783   unsigned MissingArgumentIndex, MissingArgumentCount;
784   llvm::opt::InputArgList InputArgs =
785       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
786 
787   if (InputArgs.size() == 0) {
788     T.PrintHelp(errs(), "llvm-strip <input> [ <output> ]", "strip tool");
789     exit(1);
790   }
791 
792   if (InputArgs.hasArg(STRIP_help)) {
793     T.PrintHelp(outs(), "llvm-strip <input> [ <output> ]", "strip tool");
794     exit(0);
795   }
796 
797   SmallVector<const char *, 2> Positional;
798   for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN))
799     error("unknown argument '" + Arg->getAsString(InputArgs) + "'");
800   for (auto Arg : InputArgs.filtered(STRIP_INPUT))
801     Positional.push_back(Arg->getValue());
802 
803   if (Positional.empty())
804     error("No input file specified");
805 
806   if (Positional.size() > 2)
807     error("Support for multiple input files is not implemented yet");
808 
809   CopyConfig Config;
810   Config.InputFilename = Positional[0];
811   Config.OutputFilename =
812       InputArgs.getLastArgValue(STRIP_output, Positional[0]);
813 
814   Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
815 
816   Config.DiscardAll = InputArgs.hasArg(STRIP_discard_all);
817   Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
818   Config.StripAll = InputArgs.hasArg(STRIP_strip_all);
819 
820   if (!Config.StripDebug && !Config.StripUnneeded && !Config.DiscardAll)
821     Config.StripAll = true;
822 
823   for (auto Arg : InputArgs.filtered(STRIP_remove_section))
824     Config.ToRemove.push_back(Arg->getValue());
825 
826   for (auto Arg : InputArgs.filtered(STRIP_keep_symbol))
827     Config.SymbolsToKeep.push_back(Arg->getValue());
828 
829   return Config;
830 }
831 
832 int main(int argc, char **argv) {
833   InitLLVM X(argc, argv);
834   ToolName = argv[0];
835   CopyConfig Config;
836   if (sys::path::stem(ToolName).endswith_lower("strip"))
837     Config = ParseStripOptions(makeArrayRef(argv + 1, argc));
838   else
839     Config = ParseObjcopyOptions(makeArrayRef(argv + 1, argc));
840   ExecuteElfObjcopy(Config);
841 }
842