181ad6265SDimitry Andric //===- ELFObjcopy.cpp -----------------------------------------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "llvm/ObjCopy/ELF/ELFObjcopy.h"
1081ad6265SDimitry Andric #include "ELFObject.h"
1181ad6265SDimitry Andric #include "llvm/ADT/BitmaskEnum.h"
1281ad6265SDimitry Andric #include "llvm/ADT/DenseSet.h"
1381ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h"
1481ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h"
1581ad6265SDimitry Andric #include "llvm/ADT/StringRef.h"
1681ad6265SDimitry Andric #include "llvm/ADT/Twine.h"
1781ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
1881ad6265SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
1981ad6265SDimitry Andric #include "llvm/ObjCopy/CommonConfig.h"
2081ad6265SDimitry Andric #include "llvm/ObjCopy/ELF/ELFConfig.h"
2181ad6265SDimitry Andric #include "llvm/Object/Binary.h"
2281ad6265SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
2381ad6265SDimitry Andric #include "llvm/Object/ELFTypes.h"
2481ad6265SDimitry Andric #include "llvm/Object/Error.h"
2581ad6265SDimitry Andric #include "llvm/Option/Option.h"
2681ad6265SDimitry Andric #include "llvm/Support/Casting.h"
2781ad6265SDimitry Andric #include "llvm/Support/Compression.h"
2881ad6265SDimitry Andric #include "llvm/Support/Errc.h"
2981ad6265SDimitry Andric #include "llvm/Support/Error.h"
3081ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h"
3181ad6265SDimitry Andric #include "llvm/Support/ErrorOr.h"
3281ad6265SDimitry Andric #include "llvm/Support/FileSystem.h"
3381ad6265SDimitry Andric #include "llvm/Support/Memory.h"
3481ad6265SDimitry Andric #include "llvm/Support/Path.h"
3581ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
3681ad6265SDimitry Andric #include <algorithm>
3781ad6265SDimitry Andric #include <cassert>
3881ad6265SDimitry Andric #include <cstdlib>
3981ad6265SDimitry Andric #include <functional>
4081ad6265SDimitry Andric #include <iterator>
4181ad6265SDimitry Andric #include <memory>
4281ad6265SDimitry Andric #include <string>
4381ad6265SDimitry Andric #include <system_error>
4481ad6265SDimitry Andric #include <utility>
4581ad6265SDimitry Andric 
4681ad6265SDimitry Andric using namespace llvm;
4781ad6265SDimitry Andric using namespace llvm::ELF;
4881ad6265SDimitry Andric using namespace llvm::objcopy;
4981ad6265SDimitry Andric using namespace llvm::objcopy::elf;
5081ad6265SDimitry Andric using namespace llvm::object;
5181ad6265SDimitry Andric 
5281ad6265SDimitry Andric using SectionPred = std::function<bool(const SectionBase &Sec)>;
5381ad6265SDimitry Andric 
5481ad6265SDimitry Andric static bool isDebugSection(const SectionBase &Sec) {
5581ad6265SDimitry Andric   return StringRef(Sec.Name).startswith(".debug") || Sec.Name == ".gdb_index";
5681ad6265SDimitry Andric }
5781ad6265SDimitry Andric 
5881ad6265SDimitry Andric static bool isDWOSection(const SectionBase &Sec) {
5981ad6265SDimitry Andric   return StringRef(Sec.Name).endswith(".dwo");
6081ad6265SDimitry Andric }
6181ad6265SDimitry Andric 
6281ad6265SDimitry Andric static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {
6381ad6265SDimitry Andric   // We can't remove the section header string table.
6481ad6265SDimitry Andric   if (&Sec == Obj.SectionNames)
6581ad6265SDimitry Andric     return false;
6681ad6265SDimitry Andric   // Short of keeping the string table we want to keep everything that is a DWO
6781ad6265SDimitry Andric   // section and remove everything else.
6881ad6265SDimitry Andric   return !isDWOSection(Sec);
6981ad6265SDimitry Andric }
7081ad6265SDimitry Andric 
7181ad6265SDimitry Andric static uint64_t getNewShfFlags(SectionFlag AllFlags) {
7281ad6265SDimitry Andric   uint64_t NewFlags = 0;
7381ad6265SDimitry Andric   if (AllFlags & SectionFlag::SecAlloc)
7481ad6265SDimitry Andric     NewFlags |= ELF::SHF_ALLOC;
7581ad6265SDimitry Andric   if (!(AllFlags & SectionFlag::SecReadonly))
7681ad6265SDimitry Andric     NewFlags |= ELF::SHF_WRITE;
7781ad6265SDimitry Andric   if (AllFlags & SectionFlag::SecCode)
7881ad6265SDimitry Andric     NewFlags |= ELF::SHF_EXECINSTR;
7981ad6265SDimitry Andric   if (AllFlags & SectionFlag::SecMerge)
8081ad6265SDimitry Andric     NewFlags |= ELF::SHF_MERGE;
8181ad6265SDimitry Andric   if (AllFlags & SectionFlag::SecStrings)
8281ad6265SDimitry Andric     NewFlags |= ELF::SHF_STRINGS;
8381ad6265SDimitry Andric   if (AllFlags & SectionFlag::SecExclude)
8481ad6265SDimitry Andric     NewFlags |= ELF::SHF_EXCLUDE;
8581ad6265SDimitry Andric   return NewFlags;
8681ad6265SDimitry Andric }
8781ad6265SDimitry Andric 
8881ad6265SDimitry Andric static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags,
8981ad6265SDimitry Andric                                             uint64_t NewFlags) {
9081ad6265SDimitry Andric   // Preserve some flags which should not be dropped when setting flags.
9181ad6265SDimitry Andric   // Also, preserve anything OS/processor dependant.
9281ad6265SDimitry Andric   const uint64_t PreserveMask =
9381ad6265SDimitry Andric       (ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER |
9481ad6265SDimitry Andric        ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS |
9581ad6265SDimitry Andric        ELF::SHF_INFO_LINK) &
9681ad6265SDimitry Andric       ~ELF::SHF_EXCLUDE;
9781ad6265SDimitry Andric   return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask);
9881ad6265SDimitry Andric }
9981ad6265SDimitry Andric 
100*06c3fb27SDimitry Andric static void setSectionType(SectionBase &Sec, uint64_t Type) {
101*06c3fb27SDimitry Andric   // If Sec's type is changed from SHT_NOBITS due to --set-section-flags,
102*06c3fb27SDimitry Andric   // Offset may not be aligned. Align it to max(Align, 1).
103*06c3fb27SDimitry Andric   if (Sec.Type == ELF::SHT_NOBITS && Type != ELF::SHT_NOBITS)
104*06c3fb27SDimitry Andric     Sec.Offset = alignTo(Sec.Offset, std::max(Sec.Align, uint64_t(1)));
105*06c3fb27SDimitry Andric   Sec.Type = Type;
106*06c3fb27SDimitry Andric }
107*06c3fb27SDimitry Andric 
10881ad6265SDimitry Andric static void setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags) {
10981ad6265SDimitry Andric   Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, getNewShfFlags(Flags));
11081ad6265SDimitry Andric 
11181ad6265SDimitry Andric   // In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule
11281ad6265SDimitry Andric   // may promote more non-ALLOC sections than GNU objcopy, but it is fine as
11381ad6265SDimitry Andric   // non-ALLOC SHT_NOBITS sections do not make much sense.
11481ad6265SDimitry Andric   if (Sec.Type == SHT_NOBITS &&
11581ad6265SDimitry Andric       (!(Sec.Flags & ELF::SHF_ALLOC) ||
11681ad6265SDimitry Andric        Flags & (SectionFlag::SecContents | SectionFlag::SecLoad)))
117*06c3fb27SDimitry Andric     setSectionType(Sec, ELF::SHT_PROGBITS);
11881ad6265SDimitry Andric }
11981ad6265SDimitry Andric 
12081ad6265SDimitry Andric static ElfType getOutputElfType(const Binary &Bin) {
12181ad6265SDimitry Andric   // Infer output ELF type from the input ELF object
12281ad6265SDimitry Andric   if (isa<ELFObjectFile<ELF32LE>>(Bin))
12381ad6265SDimitry Andric     return ELFT_ELF32LE;
12481ad6265SDimitry Andric   if (isa<ELFObjectFile<ELF64LE>>(Bin))
12581ad6265SDimitry Andric     return ELFT_ELF64LE;
12681ad6265SDimitry Andric   if (isa<ELFObjectFile<ELF32BE>>(Bin))
12781ad6265SDimitry Andric     return ELFT_ELF32BE;
12881ad6265SDimitry Andric   if (isa<ELFObjectFile<ELF64BE>>(Bin))
12981ad6265SDimitry Andric     return ELFT_ELF64BE;
13081ad6265SDimitry Andric   llvm_unreachable("Invalid ELFType");
13181ad6265SDimitry Andric }
13281ad6265SDimitry Andric 
13381ad6265SDimitry Andric static ElfType getOutputElfType(const MachineInfo &MI) {
13481ad6265SDimitry Andric   // Infer output ELF type from the binary arch specified
13581ad6265SDimitry Andric   if (MI.Is64Bit)
13681ad6265SDimitry Andric     return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE;
13781ad6265SDimitry Andric   else
13881ad6265SDimitry Andric     return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE;
13981ad6265SDimitry Andric }
14081ad6265SDimitry Andric 
14181ad6265SDimitry Andric static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config,
14281ad6265SDimitry Andric                                                Object &Obj, raw_ostream &Out,
14381ad6265SDimitry Andric                                                ElfType OutputElfType) {
14481ad6265SDimitry Andric   // Depending on the initial ELFT and OutputFormat we need a different Writer.
14581ad6265SDimitry Andric   switch (OutputElfType) {
14681ad6265SDimitry Andric   case ELFT_ELF32LE:
14781ad6265SDimitry Andric     return std::make_unique<ELFWriter<ELF32LE>>(Obj, Out, !Config.StripSections,
14881ad6265SDimitry Andric                                                 Config.OnlyKeepDebug);
14981ad6265SDimitry Andric   case ELFT_ELF64LE:
15081ad6265SDimitry Andric     return std::make_unique<ELFWriter<ELF64LE>>(Obj, Out, !Config.StripSections,
15181ad6265SDimitry Andric                                                 Config.OnlyKeepDebug);
15281ad6265SDimitry Andric   case ELFT_ELF32BE:
15381ad6265SDimitry Andric     return std::make_unique<ELFWriter<ELF32BE>>(Obj, Out, !Config.StripSections,
15481ad6265SDimitry Andric                                                 Config.OnlyKeepDebug);
15581ad6265SDimitry Andric   case ELFT_ELF64BE:
15681ad6265SDimitry Andric     return std::make_unique<ELFWriter<ELF64BE>>(Obj, Out, !Config.StripSections,
15781ad6265SDimitry Andric                                                 Config.OnlyKeepDebug);
15881ad6265SDimitry Andric   }
15981ad6265SDimitry Andric   llvm_unreachable("Invalid output format");
16081ad6265SDimitry Andric }
16181ad6265SDimitry Andric 
16281ad6265SDimitry Andric static std::unique_ptr<Writer> createWriter(const CommonConfig &Config,
16381ad6265SDimitry Andric                                             Object &Obj, raw_ostream &Out,
16481ad6265SDimitry Andric                                             ElfType OutputElfType) {
16581ad6265SDimitry Andric   switch (Config.OutputFormat) {
16681ad6265SDimitry Andric   case FileFormat::Binary:
16781ad6265SDimitry Andric     return std::make_unique<BinaryWriter>(Obj, Out);
16881ad6265SDimitry Andric   case FileFormat::IHex:
16981ad6265SDimitry Andric     return std::make_unique<IHexWriter>(Obj, Out);
17081ad6265SDimitry Andric   default:
17181ad6265SDimitry Andric     return createELFWriter(Config, Obj, Out, OutputElfType);
17281ad6265SDimitry Andric   }
17381ad6265SDimitry Andric }
17481ad6265SDimitry Andric 
17581ad6265SDimitry Andric static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
17681ad6265SDimitry Andric                                Object &Obj) {
17781ad6265SDimitry Andric   for (auto &Sec : Obj.sections()) {
17881ad6265SDimitry Andric     if (Sec.Name == SecName) {
17981ad6265SDimitry Andric       if (Sec.Type == SHT_NOBITS)
18081ad6265SDimitry Andric         return createStringError(object_error::parse_failed,
18181ad6265SDimitry Andric                                  "cannot dump section '%s': it has no contents",
18281ad6265SDimitry Andric                                  SecName.str().c_str());
18381ad6265SDimitry Andric       Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
18481ad6265SDimitry Andric           FileOutputBuffer::create(Filename, Sec.OriginalData.size());
18581ad6265SDimitry Andric       if (!BufferOrErr)
18681ad6265SDimitry Andric         return BufferOrErr.takeError();
18781ad6265SDimitry Andric       std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
18881ad6265SDimitry Andric       std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(),
18981ad6265SDimitry Andric                 Buf->getBufferStart());
19081ad6265SDimitry Andric       if (Error E = Buf->commit())
19181ad6265SDimitry Andric         return E;
19281ad6265SDimitry Andric       return Error::success();
19381ad6265SDimitry Andric     }
19481ad6265SDimitry Andric   }
19581ad6265SDimitry Andric   return createStringError(object_error::parse_failed, "section '%s' not found",
19681ad6265SDimitry Andric                            SecName.str().c_str());
19781ad6265SDimitry Andric }
19881ad6265SDimitry Andric 
19981ad6265SDimitry Andric static bool isCompressable(const SectionBase &Sec) {
20081ad6265SDimitry Andric   return !(Sec.Flags & ELF::SHF_COMPRESSED) &&
20181ad6265SDimitry Andric          StringRef(Sec.Name).startswith(".debug");
20281ad6265SDimitry Andric }
20381ad6265SDimitry Andric 
20481ad6265SDimitry Andric static Error replaceDebugSections(
20581ad6265SDimitry Andric     Object &Obj, function_ref<bool(const SectionBase &)> ShouldReplace,
20681ad6265SDimitry Andric     function_ref<Expected<SectionBase *>(const SectionBase *)> AddSection) {
20781ad6265SDimitry Andric   // Build a list of the debug sections we are going to replace.
20881ad6265SDimitry Andric   // We can't call `AddSection` while iterating over sections,
20981ad6265SDimitry Andric   // because it would mutate the sections array.
21081ad6265SDimitry Andric   SmallVector<SectionBase *, 13> ToReplace;
21181ad6265SDimitry Andric   for (auto &Sec : Obj.sections())
21281ad6265SDimitry Andric     if (ShouldReplace(Sec))
21381ad6265SDimitry Andric       ToReplace.push_back(&Sec);
21481ad6265SDimitry Andric 
21581ad6265SDimitry Andric   // Build a mapping from original section to a new one.
21681ad6265SDimitry Andric   DenseMap<SectionBase *, SectionBase *> FromTo;
21781ad6265SDimitry Andric   for (SectionBase *S : ToReplace) {
21881ad6265SDimitry Andric     Expected<SectionBase *> NewSection = AddSection(S);
21981ad6265SDimitry Andric     if (!NewSection)
22081ad6265SDimitry Andric       return NewSection.takeError();
22181ad6265SDimitry Andric 
22281ad6265SDimitry Andric     FromTo[S] = *NewSection;
22381ad6265SDimitry Andric   }
22481ad6265SDimitry Andric 
22581ad6265SDimitry Andric   return Obj.replaceSections(FromTo);
22681ad6265SDimitry Andric }
22781ad6265SDimitry Andric 
22881ad6265SDimitry Andric static bool isAArch64MappingSymbol(const Symbol &Sym) {
22981ad6265SDimitry Andric   if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE ||
23081ad6265SDimitry Andric       Sym.getShndx() == SHN_UNDEF)
23181ad6265SDimitry Andric     return false;
23281ad6265SDimitry Andric   StringRef Name = Sym.Name;
23381ad6265SDimitry Andric   if (!Name.consume_front("$x") && !Name.consume_front("$d"))
23481ad6265SDimitry Andric     return false;
23581ad6265SDimitry Andric   return Name.empty() || Name.startswith(".");
23681ad6265SDimitry Andric }
23781ad6265SDimitry Andric 
23881ad6265SDimitry Andric static bool isArmMappingSymbol(const Symbol &Sym) {
23981ad6265SDimitry Andric   if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE ||
24081ad6265SDimitry Andric       Sym.getShndx() == SHN_UNDEF)
24181ad6265SDimitry Andric     return false;
24281ad6265SDimitry Andric   StringRef Name = Sym.Name;
24381ad6265SDimitry Andric   if (!Name.consume_front("$a") && !Name.consume_front("$d") &&
24481ad6265SDimitry Andric       !Name.consume_front("$t"))
24581ad6265SDimitry Andric     return false;
24681ad6265SDimitry Andric   return Name.empty() || Name.startswith(".");
24781ad6265SDimitry Andric }
24881ad6265SDimitry Andric 
24981ad6265SDimitry Andric // Check if the symbol should be preserved because it is required by ABI.
25081ad6265SDimitry Andric static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym) {
25181ad6265SDimitry Andric   switch (Obj.Machine) {
25281ad6265SDimitry Andric   case EM_AARCH64:
25381ad6265SDimitry Andric     // Mapping symbols should be preserved for a relocatable object file.
25481ad6265SDimitry Andric     return Obj.isRelocatable() && isAArch64MappingSymbol(Sym);
25581ad6265SDimitry Andric   case EM_ARM:
25681ad6265SDimitry Andric     // Mapping symbols should be preserved for a relocatable object file.
25781ad6265SDimitry Andric     return Obj.isRelocatable() && isArmMappingSymbol(Sym);
25881ad6265SDimitry Andric   default:
25981ad6265SDimitry Andric     return false;
26081ad6265SDimitry Andric   }
26181ad6265SDimitry Andric }
26281ad6265SDimitry Andric 
26381ad6265SDimitry Andric static bool isUnneededSymbol(const Symbol &Sym) {
26481ad6265SDimitry Andric   return !Sym.Referenced &&
26581ad6265SDimitry Andric          (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&
26681ad6265SDimitry Andric          Sym.Type != STT_SECTION;
26781ad6265SDimitry Andric }
26881ad6265SDimitry Andric 
26981ad6265SDimitry Andric static Error updateAndRemoveSymbols(const CommonConfig &Config,
27081ad6265SDimitry Andric                                     const ELFConfig &ELFConfig, Object &Obj) {
27181ad6265SDimitry Andric   // TODO: update or remove symbols only if there is an option that affects
27281ad6265SDimitry Andric   // them.
27381ad6265SDimitry Andric   if (!Obj.SymbolTable)
27481ad6265SDimitry Andric     return Error::success();
27581ad6265SDimitry Andric 
27681ad6265SDimitry Andric   Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
27781ad6265SDimitry Andric     // Common and undefined symbols don't make sense as local symbols, and can
27881ad6265SDimitry Andric     // even cause crashes if we localize those, so skip them.
27981ad6265SDimitry Andric     if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
28081ad6265SDimitry Andric         ((ELFConfig.LocalizeHidden &&
28181ad6265SDimitry Andric           (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
28281ad6265SDimitry Andric          Config.SymbolsToLocalize.matches(Sym.Name)))
28381ad6265SDimitry Andric       Sym.Binding = STB_LOCAL;
28481ad6265SDimitry Andric 
28581ad6265SDimitry Andric     // Note: these two globalize flags have very similar names but different
28681ad6265SDimitry Andric     // meanings:
28781ad6265SDimitry Andric     //
28881ad6265SDimitry Andric     // --globalize-symbol: promote a symbol to global
28981ad6265SDimitry Andric     // --keep-global-symbol: all symbols except for these should be made local
29081ad6265SDimitry Andric     //
29181ad6265SDimitry Andric     // If --globalize-symbol is specified for a given symbol, it will be
29281ad6265SDimitry Andric     // global in the output file even if it is not included via
29381ad6265SDimitry Andric     // --keep-global-symbol. Because of that, make sure to check
29481ad6265SDimitry Andric     // --globalize-symbol second.
29581ad6265SDimitry Andric     if (!Config.SymbolsToKeepGlobal.empty() &&
29681ad6265SDimitry Andric         !Config.SymbolsToKeepGlobal.matches(Sym.Name) &&
29781ad6265SDimitry Andric         Sym.getShndx() != SHN_UNDEF)
29881ad6265SDimitry Andric       Sym.Binding = STB_LOCAL;
29981ad6265SDimitry Andric 
30081ad6265SDimitry Andric     if (Config.SymbolsToGlobalize.matches(Sym.Name) &&
30181ad6265SDimitry Andric         Sym.getShndx() != SHN_UNDEF)
30281ad6265SDimitry Andric       Sym.Binding = STB_GLOBAL;
30381ad6265SDimitry Andric 
30481ad6265SDimitry Andric     // SymbolsToWeaken applies to both STB_GLOBAL and STB_GNU_UNIQUE.
30581ad6265SDimitry Andric     if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding != STB_LOCAL)
30681ad6265SDimitry Andric       Sym.Binding = STB_WEAK;
30781ad6265SDimitry Andric 
30881ad6265SDimitry Andric     if (Config.Weaken && Sym.Binding != STB_LOCAL &&
30981ad6265SDimitry Andric         Sym.getShndx() != SHN_UNDEF)
31081ad6265SDimitry Andric       Sym.Binding = STB_WEAK;
31181ad6265SDimitry Andric 
31281ad6265SDimitry Andric     const auto I = Config.SymbolsToRename.find(Sym.Name);
31381ad6265SDimitry Andric     if (I != Config.SymbolsToRename.end())
31481ad6265SDimitry Andric       Sym.Name = std::string(I->getValue());
31581ad6265SDimitry Andric 
31681ad6265SDimitry Andric     if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION)
31781ad6265SDimitry Andric       Sym.Name = (Config.SymbolsPrefix + Sym.Name).str();
31881ad6265SDimitry Andric   });
31981ad6265SDimitry Andric 
32081ad6265SDimitry Andric   // The purpose of this loop is to mark symbols referenced by sections
32181ad6265SDimitry Andric   // (like GroupSection or RelocationSection). This way, we know which
32281ad6265SDimitry Andric   // symbols are still 'needed' and which are not.
32381ad6265SDimitry Andric   if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() ||
32481ad6265SDimitry Andric       !Config.OnlySection.empty()) {
32581ad6265SDimitry Andric     for (SectionBase &Sec : Obj.sections())
32681ad6265SDimitry Andric       Sec.markSymbols();
32781ad6265SDimitry Andric   }
32881ad6265SDimitry Andric 
32981ad6265SDimitry Andric   auto RemoveSymbolsPred = [&](const Symbol &Sym) {
33081ad6265SDimitry Andric     if (Config.SymbolsToKeep.matches(Sym.Name) ||
33181ad6265SDimitry Andric         (ELFConfig.KeepFileSymbols && Sym.Type == STT_FILE))
33281ad6265SDimitry Andric       return false;
33381ad6265SDimitry Andric 
33481ad6265SDimitry Andric     if (Config.SymbolsToRemove.matches(Sym.Name))
33581ad6265SDimitry Andric       return true;
33681ad6265SDimitry Andric 
33781ad6265SDimitry Andric     if (Config.StripAll || Config.StripAllGNU)
33881ad6265SDimitry Andric       return true;
33981ad6265SDimitry Andric 
34081ad6265SDimitry Andric     if (isRequiredByABISymbol(Obj, Sym))
34181ad6265SDimitry Andric       return false;
34281ad6265SDimitry Andric 
34381ad6265SDimitry Andric     if (Config.StripDebug && Sym.Type == STT_FILE)
34481ad6265SDimitry Andric       return true;
34581ad6265SDimitry Andric 
34681ad6265SDimitry Andric     if ((Config.DiscardMode == DiscardType::All ||
34781ad6265SDimitry Andric          (Config.DiscardMode == DiscardType::Locals &&
34881ad6265SDimitry Andric           StringRef(Sym.Name).startswith(".L"))) &&
34981ad6265SDimitry Andric         Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
35081ad6265SDimitry Andric         Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
35181ad6265SDimitry Andric       return true;
35281ad6265SDimitry Andric 
35381ad6265SDimitry Andric     if ((Config.StripUnneeded ||
35481ad6265SDimitry Andric          Config.UnneededSymbolsToRemove.matches(Sym.Name)) &&
35581ad6265SDimitry Andric         (!Obj.isRelocatable() || isUnneededSymbol(Sym)))
35681ad6265SDimitry Andric       return true;
35781ad6265SDimitry Andric 
35881ad6265SDimitry Andric     // We want to remove undefined symbols if all references have been stripped.
35981ad6265SDimitry Andric     if (!Config.OnlySection.empty() && !Sym.Referenced &&
36081ad6265SDimitry Andric         Sym.getShndx() == SHN_UNDEF)
36181ad6265SDimitry Andric       return true;
36281ad6265SDimitry Andric 
36381ad6265SDimitry Andric     return false;
36481ad6265SDimitry Andric   };
36581ad6265SDimitry Andric 
36681ad6265SDimitry Andric   return Obj.removeSymbols(RemoveSymbolsPred);
36781ad6265SDimitry Andric }
36881ad6265SDimitry Andric 
36981ad6265SDimitry Andric static Error replaceAndRemoveSections(const CommonConfig &Config,
37081ad6265SDimitry Andric                                       const ELFConfig &ELFConfig, Object &Obj) {
37181ad6265SDimitry Andric   SectionPred RemovePred = [](const SectionBase &) { return false; };
37281ad6265SDimitry Andric 
37381ad6265SDimitry Andric   // Removes:
37481ad6265SDimitry Andric   if (!Config.ToRemove.empty()) {
37581ad6265SDimitry Andric     RemovePred = [&Config](const SectionBase &Sec) {
37681ad6265SDimitry Andric       return Config.ToRemove.matches(Sec.Name);
37781ad6265SDimitry Andric     };
37881ad6265SDimitry Andric   }
37981ad6265SDimitry Andric 
38081ad6265SDimitry Andric   if (Config.StripDWO)
38181ad6265SDimitry Andric     RemovePred = [RemovePred](const SectionBase &Sec) {
38281ad6265SDimitry Andric       return isDWOSection(Sec) || RemovePred(Sec);
38381ad6265SDimitry Andric     };
38481ad6265SDimitry Andric 
38581ad6265SDimitry Andric   if (Config.ExtractDWO)
38681ad6265SDimitry Andric     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
38781ad6265SDimitry Andric       return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);
38881ad6265SDimitry Andric     };
38981ad6265SDimitry Andric 
39081ad6265SDimitry Andric   if (Config.StripAllGNU)
39181ad6265SDimitry Andric     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
39281ad6265SDimitry Andric       if (RemovePred(Sec))
39381ad6265SDimitry Andric         return true;
39481ad6265SDimitry Andric       if ((Sec.Flags & SHF_ALLOC) != 0)
39581ad6265SDimitry Andric         return false;
39681ad6265SDimitry Andric       if (&Sec == Obj.SectionNames)
39781ad6265SDimitry Andric         return false;
39881ad6265SDimitry Andric       switch (Sec.Type) {
39981ad6265SDimitry Andric       case SHT_SYMTAB:
40081ad6265SDimitry Andric       case SHT_REL:
40181ad6265SDimitry Andric       case SHT_RELA:
40281ad6265SDimitry Andric       case SHT_STRTAB:
40381ad6265SDimitry Andric         return true;
40481ad6265SDimitry Andric       }
40581ad6265SDimitry Andric       return isDebugSection(Sec);
40681ad6265SDimitry Andric     };
40781ad6265SDimitry Andric 
40881ad6265SDimitry Andric   if (Config.StripSections) {
40981ad6265SDimitry Andric     RemovePred = [RemovePred](const SectionBase &Sec) {
41081ad6265SDimitry Andric       return RemovePred(Sec) || Sec.ParentSegment == nullptr;
41181ad6265SDimitry Andric     };
41281ad6265SDimitry Andric   }
41381ad6265SDimitry Andric 
41481ad6265SDimitry Andric   if (Config.StripDebug || Config.StripUnneeded) {
41581ad6265SDimitry Andric     RemovePred = [RemovePred](const SectionBase &Sec) {
41681ad6265SDimitry Andric       return RemovePred(Sec) || isDebugSection(Sec);
41781ad6265SDimitry Andric     };
41881ad6265SDimitry Andric   }
41981ad6265SDimitry Andric 
42081ad6265SDimitry Andric   if (Config.StripNonAlloc)
42181ad6265SDimitry Andric     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
42281ad6265SDimitry Andric       if (RemovePred(Sec))
42381ad6265SDimitry Andric         return true;
42481ad6265SDimitry Andric       if (&Sec == Obj.SectionNames)
42581ad6265SDimitry Andric         return false;
42681ad6265SDimitry Andric       return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr;
42781ad6265SDimitry Andric     };
42881ad6265SDimitry Andric 
42981ad6265SDimitry Andric   if (Config.StripAll)
43081ad6265SDimitry Andric     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
43181ad6265SDimitry Andric       if (RemovePred(Sec))
43281ad6265SDimitry Andric         return true;
43381ad6265SDimitry Andric       if (&Sec == Obj.SectionNames)
43481ad6265SDimitry Andric         return false;
43581ad6265SDimitry Andric       if (StringRef(Sec.Name).startswith(".gnu.warning"))
43681ad6265SDimitry Andric         return false;
43781ad6265SDimitry Andric       // We keep the .ARM.attribute section to maintain compatibility
43881ad6265SDimitry Andric       // with Debian derived distributions. This is a bug in their
43981ad6265SDimitry Andric       // patchset as documented here:
44081ad6265SDimitry Andric       // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798
44181ad6265SDimitry Andric       if (Sec.Type == SHT_ARM_ATTRIBUTES)
44281ad6265SDimitry Andric         return false;
44381ad6265SDimitry Andric       if (Sec.ParentSegment != nullptr)
44481ad6265SDimitry Andric         return false;
44581ad6265SDimitry Andric       return (Sec.Flags & SHF_ALLOC) == 0;
44681ad6265SDimitry Andric     };
44781ad6265SDimitry Andric 
44881ad6265SDimitry Andric   if (Config.ExtractPartition || Config.ExtractMainPartition) {
44981ad6265SDimitry Andric     RemovePred = [RemovePred](const SectionBase &Sec) {
45081ad6265SDimitry Andric       if (RemovePred(Sec))
45181ad6265SDimitry Andric         return true;
45281ad6265SDimitry Andric       if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR)
45381ad6265SDimitry Andric         return true;
45481ad6265SDimitry Andric       return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment;
45581ad6265SDimitry Andric     };
45681ad6265SDimitry Andric   }
45781ad6265SDimitry Andric 
45881ad6265SDimitry Andric   // Explicit copies:
45981ad6265SDimitry Andric   if (!Config.OnlySection.empty()) {
46081ad6265SDimitry Andric     RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {
46181ad6265SDimitry Andric       // Explicitly keep these sections regardless of previous removes.
46281ad6265SDimitry Andric       if (Config.OnlySection.matches(Sec.Name))
46381ad6265SDimitry Andric         return false;
46481ad6265SDimitry Andric 
46581ad6265SDimitry Andric       // Allow all implicit removes.
46681ad6265SDimitry Andric       if (RemovePred(Sec))
46781ad6265SDimitry Andric         return true;
46881ad6265SDimitry Andric 
46981ad6265SDimitry Andric       // Keep special sections.
47081ad6265SDimitry Andric       if (Obj.SectionNames == &Sec)
47181ad6265SDimitry Andric         return false;
47281ad6265SDimitry Andric       if (Obj.SymbolTable == &Sec ||
47381ad6265SDimitry Andric           (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec))
47481ad6265SDimitry Andric         return false;
47581ad6265SDimitry Andric 
47681ad6265SDimitry Andric       // Remove everything else.
47781ad6265SDimitry Andric       return true;
47881ad6265SDimitry Andric     };
47981ad6265SDimitry Andric   }
48081ad6265SDimitry Andric 
48181ad6265SDimitry Andric   if (!Config.KeepSection.empty()) {
48281ad6265SDimitry Andric     RemovePred = [&Config, RemovePred](const SectionBase &Sec) {
48381ad6265SDimitry Andric       // Explicitly keep these sections regardless of previous removes.
48481ad6265SDimitry Andric       if (Config.KeepSection.matches(Sec.Name))
48581ad6265SDimitry Andric         return false;
48681ad6265SDimitry Andric       // Otherwise defer to RemovePred.
48781ad6265SDimitry Andric       return RemovePred(Sec);
48881ad6265SDimitry Andric     };
48981ad6265SDimitry Andric   }
49081ad6265SDimitry Andric 
49181ad6265SDimitry Andric   // This has to be the last predicate assignment.
49281ad6265SDimitry Andric   // If the option --keep-symbol has been specified
49381ad6265SDimitry Andric   // and at least one of those symbols is present
49481ad6265SDimitry Andric   // (equivalently, the updated symbol table is not empty)
49581ad6265SDimitry Andric   // the symbol table and the string table should not be removed.
49681ad6265SDimitry Andric   if ((!Config.SymbolsToKeep.empty() || ELFConfig.KeepFileSymbols) &&
49781ad6265SDimitry Andric       Obj.SymbolTable && !Obj.SymbolTable->empty()) {
49881ad6265SDimitry Andric     RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {
49981ad6265SDimitry Andric       if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
50081ad6265SDimitry Andric         return false;
50181ad6265SDimitry Andric       return RemovePred(Sec);
50281ad6265SDimitry Andric     };
50381ad6265SDimitry Andric   }
50481ad6265SDimitry Andric 
50581ad6265SDimitry Andric   if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred))
50681ad6265SDimitry Andric     return E;
50781ad6265SDimitry Andric 
50881ad6265SDimitry Andric   if (Config.CompressionType != DebugCompressionType::None) {
50981ad6265SDimitry Andric     if (Error Err = replaceDebugSections(
51081ad6265SDimitry Andric             Obj, isCompressable,
51181ad6265SDimitry Andric             [&Config, &Obj](const SectionBase *S) -> Expected<SectionBase *> {
51281ad6265SDimitry Andric               return &Obj.addSection<CompressedSection>(
513bdd1243dSDimitry Andric                   CompressedSection(*S, Config.CompressionType, Obj.Is64Bits));
51481ad6265SDimitry Andric             }))
51581ad6265SDimitry Andric       return Err;
51681ad6265SDimitry Andric   } else if (Config.DecompressDebugSections) {
51781ad6265SDimitry Andric     if (Error Err = replaceDebugSections(
51881ad6265SDimitry Andric             Obj,
51981ad6265SDimitry Andric             [](const SectionBase &S) { return isa<CompressedSection>(&S); },
52081ad6265SDimitry Andric             [&Obj](const SectionBase *S) {
52181ad6265SDimitry Andric               const CompressedSection *CS = cast<CompressedSection>(S);
52281ad6265SDimitry Andric               return &Obj.addSection<DecompressedSection>(*CS);
52381ad6265SDimitry Andric             }))
52481ad6265SDimitry Andric       return Err;
52581ad6265SDimitry Andric   }
52681ad6265SDimitry Andric 
52781ad6265SDimitry Andric   return Error::success();
52881ad6265SDimitry Andric }
52981ad6265SDimitry Andric 
53081ad6265SDimitry Andric // Add symbol to the Object symbol table with the specified properties.
53181ad6265SDimitry Andric static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo,
53281ad6265SDimitry Andric                       uint8_t DefaultVisibility) {
53381ad6265SDimitry Andric   SectionBase *Sec = Obj.findSection(SymInfo.SectionName);
53481ad6265SDimitry Andric   uint64_t Value = Sec ? Sec->Addr + SymInfo.Value : SymInfo.Value;
53581ad6265SDimitry Andric 
53681ad6265SDimitry Andric   uint8_t Bind = ELF::STB_GLOBAL;
53781ad6265SDimitry Andric   uint8_t Type = ELF::STT_NOTYPE;
53881ad6265SDimitry Andric   uint8_t Visibility = DefaultVisibility;
53981ad6265SDimitry Andric 
54081ad6265SDimitry Andric   for (SymbolFlag FlagValue : SymInfo.Flags)
54181ad6265SDimitry Andric     switch (FlagValue) {
54281ad6265SDimitry Andric     case SymbolFlag::Global:
54381ad6265SDimitry Andric       Bind = ELF::STB_GLOBAL;
54481ad6265SDimitry Andric       break;
54581ad6265SDimitry Andric     case SymbolFlag::Local:
54681ad6265SDimitry Andric       Bind = ELF::STB_LOCAL;
54781ad6265SDimitry Andric       break;
54881ad6265SDimitry Andric     case SymbolFlag::Weak:
54981ad6265SDimitry Andric       Bind = ELF::STB_WEAK;
55081ad6265SDimitry Andric       break;
55181ad6265SDimitry Andric     case SymbolFlag::Default:
55281ad6265SDimitry Andric       Visibility = ELF::STV_DEFAULT;
55381ad6265SDimitry Andric       break;
55481ad6265SDimitry Andric     case SymbolFlag::Hidden:
55581ad6265SDimitry Andric       Visibility = ELF::STV_HIDDEN;
55681ad6265SDimitry Andric       break;
55781ad6265SDimitry Andric     case SymbolFlag::Protected:
55881ad6265SDimitry Andric       Visibility = ELF::STV_PROTECTED;
55981ad6265SDimitry Andric       break;
56081ad6265SDimitry Andric     case SymbolFlag::File:
56181ad6265SDimitry Andric       Type = ELF::STT_FILE;
56281ad6265SDimitry Andric       break;
56381ad6265SDimitry Andric     case SymbolFlag::Section:
56481ad6265SDimitry Andric       Type = ELF::STT_SECTION;
56581ad6265SDimitry Andric       break;
56681ad6265SDimitry Andric     case SymbolFlag::Object:
56781ad6265SDimitry Andric       Type = ELF::STT_OBJECT;
56881ad6265SDimitry Andric       break;
56981ad6265SDimitry Andric     case SymbolFlag::Function:
57081ad6265SDimitry Andric       Type = ELF::STT_FUNC;
57181ad6265SDimitry Andric       break;
57281ad6265SDimitry Andric     case SymbolFlag::IndirectFunction:
57381ad6265SDimitry Andric       Type = ELF::STT_GNU_IFUNC;
57481ad6265SDimitry Andric       break;
57581ad6265SDimitry Andric     default: /* Other flag values are ignored for ELF. */
57681ad6265SDimitry Andric       break;
57781ad6265SDimitry Andric     };
57881ad6265SDimitry Andric 
57981ad6265SDimitry Andric   Obj.SymbolTable->addSymbol(
58081ad6265SDimitry Andric       SymInfo.SymbolName, Bind, Type, Sec, Value, Visibility,
58181ad6265SDimitry Andric       Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
58281ad6265SDimitry Andric }
58381ad6265SDimitry Andric 
58481ad6265SDimitry Andric static Error
58581ad6265SDimitry Andric handleUserSection(const NewSectionInfo &NewSection,
58681ad6265SDimitry Andric                   function_ref<Error(StringRef, ArrayRef<uint8_t>)> F) {
58781ad6265SDimitry Andric   ArrayRef<uint8_t> Data(reinterpret_cast<const uint8_t *>(
58881ad6265SDimitry Andric                              NewSection.SectionData->getBufferStart()),
58981ad6265SDimitry Andric                          NewSection.SectionData->getBufferSize());
59081ad6265SDimitry Andric   return F(NewSection.SectionName, Data);
59181ad6265SDimitry Andric }
59281ad6265SDimitry Andric 
59381ad6265SDimitry Andric // This function handles the high level operations of GNU objcopy including
59481ad6265SDimitry Andric // handling command line options. It's important to outline certain properties
59581ad6265SDimitry Andric // we expect to hold of the command line operations. Any operation that "keeps"
59681ad6265SDimitry Andric // should keep regardless of a remove. Additionally any removal should respect
59781ad6265SDimitry Andric // any previous removals. Lastly whether or not something is removed shouldn't
59881ad6265SDimitry Andric // depend a) on the order the options occur in or b) on some opaque priority
59981ad6265SDimitry Andric // system. The only priority is that keeps/copies overrule removes.
60081ad6265SDimitry Andric static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
60181ad6265SDimitry Andric                         Object &Obj) {
60281ad6265SDimitry Andric   if (Config.OutputArch) {
603bdd1243dSDimitry Andric     Obj.Machine = Config.OutputArch->EMachine;
604bdd1243dSDimitry Andric     Obj.OSABI = Config.OutputArch->OSABI;
60581ad6265SDimitry Andric   }
60681ad6265SDimitry Andric 
60781ad6265SDimitry Andric   if (!Config.SplitDWO.empty() && Config.ExtractDWO) {
60881ad6265SDimitry Andric     return Obj.removeSections(
60981ad6265SDimitry Andric         ELFConfig.AllowBrokenLinks,
61081ad6265SDimitry Andric         [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); });
61181ad6265SDimitry Andric   }
61281ad6265SDimitry Andric 
61381ad6265SDimitry Andric   // Dump sections before add/remove for compatibility with GNU objcopy.
61481ad6265SDimitry Andric   for (StringRef Flag : Config.DumpSection) {
61581ad6265SDimitry Andric     StringRef SectionName;
61681ad6265SDimitry Andric     StringRef FileName;
61781ad6265SDimitry Andric     std::tie(SectionName, FileName) = Flag.split('=');
61881ad6265SDimitry Andric     if (Error E = dumpSectionToFile(SectionName, FileName, Obj))
61981ad6265SDimitry Andric       return E;
62081ad6265SDimitry Andric   }
62181ad6265SDimitry Andric 
62281ad6265SDimitry Andric   // It is important to remove the sections first. For example, we want to
62381ad6265SDimitry Andric   // remove the relocation sections before removing the symbols. That allows
62481ad6265SDimitry Andric   // us to avoid reporting the inappropriate errors about removing symbols
62581ad6265SDimitry Andric   // named in relocations.
62681ad6265SDimitry Andric   if (Error E = replaceAndRemoveSections(Config, ELFConfig, Obj))
62781ad6265SDimitry Andric     return E;
62881ad6265SDimitry Andric 
62981ad6265SDimitry Andric   if (Error E = updateAndRemoveSymbols(Config, ELFConfig, Obj))
63081ad6265SDimitry Andric     return E;
63181ad6265SDimitry Andric 
632753f127fSDimitry Andric   if (!Config.SetSectionAlignment.empty()) {
633753f127fSDimitry Andric     for (SectionBase &Sec : Obj.sections()) {
634753f127fSDimitry Andric       auto I = Config.SetSectionAlignment.find(Sec.Name);
635753f127fSDimitry Andric       if (I != Config.SetSectionAlignment.end())
636753f127fSDimitry Andric         Sec.Align = I->second;
637753f127fSDimitry Andric     }
638753f127fSDimitry Andric   }
639753f127fSDimitry Andric 
640753f127fSDimitry Andric   if (Config.OnlyKeepDebug)
641753f127fSDimitry Andric     for (auto &Sec : Obj.sections())
642753f127fSDimitry Andric       if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
643753f127fSDimitry Andric         Sec.Type = SHT_NOBITS;
644753f127fSDimitry Andric 
645753f127fSDimitry Andric   for (const NewSectionInfo &AddedSection : Config.AddSection) {
646753f127fSDimitry Andric     auto AddSection = [&](StringRef Name, ArrayRef<uint8_t> Data) {
647753f127fSDimitry Andric       OwnedDataSection &NewSection =
648753f127fSDimitry Andric           Obj.addSection<OwnedDataSection>(Name, Data);
649753f127fSDimitry Andric       if (Name.startswith(".note") && Name != ".note.GNU-stack")
650753f127fSDimitry Andric         NewSection.Type = SHT_NOTE;
651753f127fSDimitry Andric       return Error::success();
652753f127fSDimitry Andric     };
653753f127fSDimitry Andric     if (Error E = handleUserSection(AddedSection, AddSection))
654753f127fSDimitry Andric       return E;
655753f127fSDimitry Andric   }
656753f127fSDimitry Andric 
657753f127fSDimitry Andric   for (const NewSectionInfo &NewSection : Config.UpdateSection) {
658753f127fSDimitry Andric     auto UpdateSection = [&](StringRef Name, ArrayRef<uint8_t> Data) {
659753f127fSDimitry Andric       return Obj.updateSection(Name, Data);
660753f127fSDimitry Andric     };
661753f127fSDimitry Andric     if (Error E = handleUserSection(NewSection, UpdateSection))
662753f127fSDimitry Andric       return E;
663753f127fSDimitry Andric   }
664753f127fSDimitry Andric 
665753f127fSDimitry Andric   if (!Config.AddGnuDebugLink.empty())
666753f127fSDimitry Andric     Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink,
667753f127fSDimitry Andric                                         Config.GnuDebugLinkCRC32);
668753f127fSDimitry Andric 
669753f127fSDimitry Andric   // If the symbol table was previously removed, we need to create a new one
670753f127fSDimitry Andric   // before adding new symbols.
671753f127fSDimitry Andric   if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty())
672753f127fSDimitry Andric     if (Error E = Obj.addNewSymbolTable())
673753f127fSDimitry Andric       return E;
674753f127fSDimitry Andric 
675753f127fSDimitry Andric   for (const NewSymbolInfo &SI : Config.SymbolsToAdd)
676753f127fSDimitry Andric     addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility);
677753f127fSDimitry Andric 
678753f127fSDimitry Andric   // --set-section-{flags,type} work with sections added by --add-section.
679753f127fSDimitry Andric   if (!Config.SetSectionFlags.empty() || !Config.SetSectionType.empty()) {
680753f127fSDimitry Andric     for (auto &Sec : Obj.sections()) {
681753f127fSDimitry Andric       const auto Iter = Config.SetSectionFlags.find(Sec.Name);
682753f127fSDimitry Andric       if (Iter != Config.SetSectionFlags.end()) {
683753f127fSDimitry Andric         const SectionFlagsUpdate &SFU = Iter->second;
684753f127fSDimitry Andric         setSectionFlagsAndType(Sec, SFU.NewFlags);
685753f127fSDimitry Andric       }
686753f127fSDimitry Andric       auto It2 = Config.SetSectionType.find(Sec.Name);
687753f127fSDimitry Andric       if (It2 != Config.SetSectionType.end())
688*06c3fb27SDimitry Andric         setSectionType(Sec, It2->second);
689753f127fSDimitry Andric     }
690753f127fSDimitry Andric   }
691753f127fSDimitry Andric 
69281ad6265SDimitry Andric   if (!Config.SectionsToRename.empty()) {
69381ad6265SDimitry Andric     std::vector<RelocationSectionBase *> RelocSections;
69481ad6265SDimitry Andric     DenseSet<SectionBase *> RenamedSections;
69581ad6265SDimitry Andric     for (SectionBase &Sec : Obj.sections()) {
69681ad6265SDimitry Andric       auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec);
69781ad6265SDimitry Andric       const auto Iter = Config.SectionsToRename.find(Sec.Name);
69881ad6265SDimitry Andric       if (Iter != Config.SectionsToRename.end()) {
69981ad6265SDimitry Andric         const SectionRename &SR = Iter->second;
70081ad6265SDimitry Andric         Sec.Name = std::string(SR.NewName);
70181ad6265SDimitry Andric         if (SR.NewFlags)
702bdd1243dSDimitry Andric           setSectionFlagsAndType(Sec, *SR.NewFlags);
70381ad6265SDimitry Andric         RenamedSections.insert(&Sec);
70481ad6265SDimitry Andric       } else if (RelocSec && !(Sec.Flags & SHF_ALLOC))
70581ad6265SDimitry Andric         // Postpone processing relocation sections which are not specified in
70681ad6265SDimitry Andric         // their explicit '--rename-section' commands until after their target
70781ad6265SDimitry Andric         // sections are renamed.
70881ad6265SDimitry Andric         // Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be
70981ad6265SDimitry Andric         // renamed only explicitly. Otherwise, renaming, for example, '.got.plt'
71081ad6265SDimitry Andric         // would affect '.rela.plt', which is not desirable.
71181ad6265SDimitry Andric         RelocSections.push_back(RelocSec);
71281ad6265SDimitry Andric     }
71381ad6265SDimitry Andric 
71481ad6265SDimitry Andric     // Rename relocation sections according to their target sections.
71581ad6265SDimitry Andric     for (RelocationSectionBase *RelocSec : RelocSections) {
71681ad6265SDimitry Andric       auto Iter = RenamedSections.find(RelocSec->getSection());
71781ad6265SDimitry Andric       if (Iter != RenamedSections.end())
71881ad6265SDimitry Andric         RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str();
71981ad6265SDimitry Andric     }
72081ad6265SDimitry Andric   }
72181ad6265SDimitry Andric 
72281ad6265SDimitry Andric   // Add a prefix to allocated sections and their relocation sections. This
72381ad6265SDimitry Andric   // should be done after renaming the section by Config.SectionToRename to
72481ad6265SDimitry Andric   // imitate the GNU objcopy behavior.
72581ad6265SDimitry Andric   if (!Config.AllocSectionsPrefix.empty()) {
72681ad6265SDimitry Andric     DenseSet<SectionBase *> PrefixedSections;
72781ad6265SDimitry Andric     for (SectionBase &Sec : Obj.sections()) {
72881ad6265SDimitry Andric       if (Sec.Flags & SHF_ALLOC) {
72981ad6265SDimitry Andric         Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str();
73081ad6265SDimitry Andric         PrefixedSections.insert(&Sec);
73181ad6265SDimitry Andric       } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) {
73281ad6265SDimitry Andric         // Rename relocation sections associated to the allocated sections.
73381ad6265SDimitry Andric         // For example, if we rename .text to .prefix.text, we also rename
73481ad6265SDimitry Andric         // .rel.text to .rel.prefix.text.
73581ad6265SDimitry Andric         //
73681ad6265SDimitry Andric         // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled
73781ad6265SDimitry Andric         // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not
73881ad6265SDimitry Andric         // .rela.prefix.plt since GNU objcopy does so.
73981ad6265SDimitry Andric         const SectionBase *TargetSec = RelocSec->getSection();
74081ad6265SDimitry Andric         if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) {
74181ad6265SDimitry Andric           // If the relocation section comes *after* the target section, we
74281ad6265SDimitry Andric           // don't add Config.AllocSectionsPrefix because we've already added
74381ad6265SDimitry Andric           // the prefix to TargetSec->Name. Otherwise, if the relocation
74481ad6265SDimitry Andric           // section comes *before* the target section, we add the prefix.
74581ad6265SDimitry Andric           if (PrefixedSections.count(TargetSec))
74681ad6265SDimitry Andric             Sec.Name = (RelocSec->getNamePrefix() + TargetSec->Name).str();
74781ad6265SDimitry Andric           else
74881ad6265SDimitry Andric             Sec.Name = (RelocSec->getNamePrefix() + Config.AllocSectionsPrefix +
74981ad6265SDimitry Andric                         TargetSec->Name)
75081ad6265SDimitry Andric                            .str();
75181ad6265SDimitry Andric         }
75281ad6265SDimitry Andric       }
75381ad6265SDimitry Andric     }
75481ad6265SDimitry Andric   }
75581ad6265SDimitry Andric 
75681ad6265SDimitry Andric   if (ELFConfig.EntryExpr)
75781ad6265SDimitry Andric     Obj.Entry = ELFConfig.EntryExpr(Obj.Entry);
75881ad6265SDimitry Andric   return Error::success();
75981ad6265SDimitry Andric }
76081ad6265SDimitry Andric 
76181ad6265SDimitry Andric static Error writeOutput(const CommonConfig &Config, Object &Obj,
76281ad6265SDimitry Andric                          raw_ostream &Out, ElfType OutputElfType) {
76381ad6265SDimitry Andric   std::unique_ptr<Writer> Writer =
76481ad6265SDimitry Andric       createWriter(Config, Obj, Out, OutputElfType);
76581ad6265SDimitry Andric   if (Error E = Writer->finalize())
76681ad6265SDimitry Andric     return E;
76781ad6265SDimitry Andric   return Writer->write();
76881ad6265SDimitry Andric }
76981ad6265SDimitry Andric 
77081ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,
77181ad6265SDimitry Andric                                          const ELFConfig &ELFConfig,
77281ad6265SDimitry Andric                                          MemoryBuffer &In, raw_ostream &Out) {
77381ad6265SDimitry Andric   IHexReader Reader(&In);
77481ad6265SDimitry Andric   Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
77581ad6265SDimitry Andric   if (!Obj)
77681ad6265SDimitry Andric     return Obj.takeError();
77781ad6265SDimitry Andric 
77881ad6265SDimitry Andric   const ElfType OutputElfType =
77981ad6265SDimitry Andric       getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
78081ad6265SDimitry Andric   if (Error E = handleArgs(Config, ELFConfig, **Obj))
78181ad6265SDimitry Andric     return E;
78281ad6265SDimitry Andric   return writeOutput(Config, **Obj, Out, OutputElfType);
78381ad6265SDimitry Andric }
78481ad6265SDimitry Andric 
78581ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
78681ad6265SDimitry Andric                                               const ELFConfig &ELFConfig,
78781ad6265SDimitry Andric                                               MemoryBuffer &In,
78881ad6265SDimitry Andric                                               raw_ostream &Out) {
78981ad6265SDimitry Andric   BinaryReader Reader(&In, ELFConfig.NewSymbolVisibility);
79081ad6265SDimitry Andric   Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
79181ad6265SDimitry Andric   if (!Obj)
79281ad6265SDimitry Andric     return Obj.takeError();
79381ad6265SDimitry Andric 
79481ad6265SDimitry Andric   // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch
79581ad6265SDimitry Andric   // (-B<arch>).
79681ad6265SDimitry Andric   const ElfType OutputElfType =
79781ad6265SDimitry Andric       getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
79881ad6265SDimitry Andric   if (Error E = handleArgs(Config, ELFConfig, **Obj))
79981ad6265SDimitry Andric     return E;
80081ad6265SDimitry Andric   return writeOutput(Config, **Obj, Out, OutputElfType);
80181ad6265SDimitry Andric }
80281ad6265SDimitry Andric 
80381ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
80481ad6265SDimitry Andric                                            const ELFConfig &ELFConfig,
80581ad6265SDimitry Andric                                            object::ELFObjectFileBase &In,
80681ad6265SDimitry Andric                                            raw_ostream &Out) {
80781ad6265SDimitry Andric   ELFReader Reader(&In, Config.ExtractPartition);
80881ad6265SDimitry Andric   Expected<std::unique_ptr<Object>> Obj =
80981ad6265SDimitry Andric       Reader.create(!Config.SymbolsToAdd.empty());
81081ad6265SDimitry Andric   if (!Obj)
81181ad6265SDimitry Andric     return Obj.takeError();
81281ad6265SDimitry Andric   // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
813bdd1243dSDimitry Andric   const ElfType OutputElfType = Config.OutputArch
814bdd1243dSDimitry Andric                                     ? getOutputElfType(*Config.OutputArch)
81581ad6265SDimitry Andric                                     : getOutputElfType(In);
81681ad6265SDimitry Andric 
81781ad6265SDimitry Andric   if (Error E = handleArgs(Config, ELFConfig, **Obj))
81881ad6265SDimitry Andric     return createFileError(Config.InputFilename, std::move(E));
81981ad6265SDimitry Andric 
82081ad6265SDimitry Andric   if (Error E = writeOutput(Config, **Obj, Out, OutputElfType))
82181ad6265SDimitry Andric     return createFileError(Config.InputFilename, std::move(E));
82281ad6265SDimitry Andric 
82381ad6265SDimitry Andric   return Error::success();
82481ad6265SDimitry Andric }
825