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