1*81ad6265SDimitry Andric //===- ELFObjcopy.cpp -----------------------------------------------------===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric 9*81ad6265SDimitry Andric #include "llvm/ObjCopy/ELF/ELFObjcopy.h" 10*81ad6265SDimitry Andric #include "ELFObject.h" 11*81ad6265SDimitry Andric #include "llvm/ADT/BitmaskEnum.h" 12*81ad6265SDimitry Andric #include "llvm/ADT/DenseSet.h" 13*81ad6265SDimitry Andric #include "llvm/ADT/Optional.h" 14*81ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 15*81ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 16*81ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 17*81ad6265SDimitry Andric #include "llvm/ADT/Twine.h" 18*81ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 19*81ad6265SDimitry Andric #include "llvm/MC/MCTargetOptions.h" 20*81ad6265SDimitry Andric #include "llvm/ObjCopy/CommonConfig.h" 21*81ad6265SDimitry Andric #include "llvm/ObjCopy/ELF/ELFConfig.h" 22*81ad6265SDimitry Andric #include "llvm/Object/Binary.h" 23*81ad6265SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 24*81ad6265SDimitry Andric #include "llvm/Object/ELFTypes.h" 25*81ad6265SDimitry Andric #include "llvm/Object/Error.h" 26*81ad6265SDimitry Andric #include "llvm/Option/Option.h" 27*81ad6265SDimitry Andric #include "llvm/Support/Casting.h" 28*81ad6265SDimitry Andric #include "llvm/Support/Compression.h" 29*81ad6265SDimitry Andric #include "llvm/Support/Errc.h" 30*81ad6265SDimitry Andric #include "llvm/Support/Error.h" 31*81ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 32*81ad6265SDimitry Andric #include "llvm/Support/ErrorOr.h" 33*81ad6265SDimitry Andric #include "llvm/Support/FileSystem.h" 34*81ad6265SDimitry Andric #include "llvm/Support/Memory.h" 35*81ad6265SDimitry Andric #include "llvm/Support/Path.h" 36*81ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 37*81ad6265SDimitry Andric #include <algorithm> 38*81ad6265SDimitry Andric #include <cassert> 39*81ad6265SDimitry Andric #include <cstdlib> 40*81ad6265SDimitry Andric #include <functional> 41*81ad6265SDimitry Andric #include <iterator> 42*81ad6265SDimitry Andric #include <memory> 43*81ad6265SDimitry Andric #include <string> 44*81ad6265SDimitry Andric #include <system_error> 45*81ad6265SDimitry Andric #include <utility> 46*81ad6265SDimitry Andric 47*81ad6265SDimitry Andric using namespace llvm; 48*81ad6265SDimitry Andric using namespace llvm::ELF; 49*81ad6265SDimitry Andric using namespace llvm::objcopy; 50*81ad6265SDimitry Andric using namespace llvm::objcopy::elf; 51*81ad6265SDimitry Andric using namespace llvm::object; 52*81ad6265SDimitry Andric 53*81ad6265SDimitry Andric using SectionPred = std::function<bool(const SectionBase &Sec)>; 54*81ad6265SDimitry Andric 55*81ad6265SDimitry Andric static bool isDebugSection(const SectionBase &Sec) { 56*81ad6265SDimitry Andric return StringRef(Sec.Name).startswith(".debug") || Sec.Name == ".gdb_index"; 57*81ad6265SDimitry Andric } 58*81ad6265SDimitry Andric 59*81ad6265SDimitry Andric static bool isDWOSection(const SectionBase &Sec) { 60*81ad6265SDimitry Andric return StringRef(Sec.Name).endswith(".dwo"); 61*81ad6265SDimitry Andric } 62*81ad6265SDimitry Andric 63*81ad6265SDimitry Andric static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) { 64*81ad6265SDimitry Andric // We can't remove the section header string table. 65*81ad6265SDimitry Andric if (&Sec == Obj.SectionNames) 66*81ad6265SDimitry Andric return false; 67*81ad6265SDimitry Andric // Short of keeping the string table we want to keep everything that is a DWO 68*81ad6265SDimitry Andric // section and remove everything else. 69*81ad6265SDimitry Andric return !isDWOSection(Sec); 70*81ad6265SDimitry Andric } 71*81ad6265SDimitry Andric 72*81ad6265SDimitry Andric static uint64_t getNewShfFlags(SectionFlag AllFlags) { 73*81ad6265SDimitry Andric uint64_t NewFlags = 0; 74*81ad6265SDimitry Andric if (AllFlags & SectionFlag::SecAlloc) 75*81ad6265SDimitry Andric NewFlags |= ELF::SHF_ALLOC; 76*81ad6265SDimitry Andric if (!(AllFlags & SectionFlag::SecReadonly)) 77*81ad6265SDimitry Andric NewFlags |= ELF::SHF_WRITE; 78*81ad6265SDimitry Andric if (AllFlags & SectionFlag::SecCode) 79*81ad6265SDimitry Andric NewFlags |= ELF::SHF_EXECINSTR; 80*81ad6265SDimitry Andric if (AllFlags & SectionFlag::SecMerge) 81*81ad6265SDimitry Andric NewFlags |= ELF::SHF_MERGE; 82*81ad6265SDimitry Andric if (AllFlags & SectionFlag::SecStrings) 83*81ad6265SDimitry Andric NewFlags |= ELF::SHF_STRINGS; 84*81ad6265SDimitry Andric if (AllFlags & SectionFlag::SecExclude) 85*81ad6265SDimitry Andric NewFlags |= ELF::SHF_EXCLUDE; 86*81ad6265SDimitry Andric return NewFlags; 87*81ad6265SDimitry Andric } 88*81ad6265SDimitry Andric 89*81ad6265SDimitry Andric static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags, 90*81ad6265SDimitry Andric uint64_t NewFlags) { 91*81ad6265SDimitry Andric // Preserve some flags which should not be dropped when setting flags. 92*81ad6265SDimitry Andric // Also, preserve anything OS/processor dependant. 93*81ad6265SDimitry Andric const uint64_t PreserveMask = 94*81ad6265SDimitry Andric (ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER | 95*81ad6265SDimitry Andric ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS | 96*81ad6265SDimitry Andric ELF::SHF_INFO_LINK) & 97*81ad6265SDimitry Andric ~ELF::SHF_EXCLUDE; 98*81ad6265SDimitry Andric return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask); 99*81ad6265SDimitry Andric } 100*81ad6265SDimitry Andric 101*81ad6265SDimitry Andric static void setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags) { 102*81ad6265SDimitry Andric Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, getNewShfFlags(Flags)); 103*81ad6265SDimitry Andric 104*81ad6265SDimitry Andric // In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule 105*81ad6265SDimitry Andric // may promote more non-ALLOC sections than GNU objcopy, but it is fine as 106*81ad6265SDimitry Andric // non-ALLOC SHT_NOBITS sections do not make much sense. 107*81ad6265SDimitry Andric if (Sec.Type == SHT_NOBITS && 108*81ad6265SDimitry Andric (!(Sec.Flags & ELF::SHF_ALLOC) || 109*81ad6265SDimitry Andric Flags & (SectionFlag::SecContents | SectionFlag::SecLoad))) 110*81ad6265SDimitry Andric Sec.Type = SHT_PROGBITS; 111*81ad6265SDimitry Andric } 112*81ad6265SDimitry Andric 113*81ad6265SDimitry Andric static ElfType getOutputElfType(const Binary &Bin) { 114*81ad6265SDimitry Andric // Infer output ELF type from the input ELF object 115*81ad6265SDimitry Andric if (isa<ELFObjectFile<ELF32LE>>(Bin)) 116*81ad6265SDimitry Andric return ELFT_ELF32LE; 117*81ad6265SDimitry Andric if (isa<ELFObjectFile<ELF64LE>>(Bin)) 118*81ad6265SDimitry Andric return ELFT_ELF64LE; 119*81ad6265SDimitry Andric if (isa<ELFObjectFile<ELF32BE>>(Bin)) 120*81ad6265SDimitry Andric return ELFT_ELF32BE; 121*81ad6265SDimitry Andric if (isa<ELFObjectFile<ELF64BE>>(Bin)) 122*81ad6265SDimitry Andric return ELFT_ELF64BE; 123*81ad6265SDimitry Andric llvm_unreachable("Invalid ELFType"); 124*81ad6265SDimitry Andric } 125*81ad6265SDimitry Andric 126*81ad6265SDimitry Andric static ElfType getOutputElfType(const MachineInfo &MI) { 127*81ad6265SDimitry Andric // Infer output ELF type from the binary arch specified 128*81ad6265SDimitry Andric if (MI.Is64Bit) 129*81ad6265SDimitry Andric return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE; 130*81ad6265SDimitry Andric else 131*81ad6265SDimitry Andric return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE; 132*81ad6265SDimitry Andric } 133*81ad6265SDimitry Andric 134*81ad6265SDimitry Andric static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config, 135*81ad6265SDimitry Andric Object &Obj, raw_ostream &Out, 136*81ad6265SDimitry Andric ElfType OutputElfType) { 137*81ad6265SDimitry Andric // Depending on the initial ELFT and OutputFormat we need a different Writer. 138*81ad6265SDimitry Andric switch (OutputElfType) { 139*81ad6265SDimitry Andric case ELFT_ELF32LE: 140*81ad6265SDimitry Andric return std::make_unique<ELFWriter<ELF32LE>>(Obj, Out, !Config.StripSections, 141*81ad6265SDimitry Andric Config.OnlyKeepDebug); 142*81ad6265SDimitry Andric case ELFT_ELF64LE: 143*81ad6265SDimitry Andric return std::make_unique<ELFWriter<ELF64LE>>(Obj, Out, !Config.StripSections, 144*81ad6265SDimitry Andric Config.OnlyKeepDebug); 145*81ad6265SDimitry Andric case ELFT_ELF32BE: 146*81ad6265SDimitry Andric return std::make_unique<ELFWriter<ELF32BE>>(Obj, Out, !Config.StripSections, 147*81ad6265SDimitry Andric Config.OnlyKeepDebug); 148*81ad6265SDimitry Andric case ELFT_ELF64BE: 149*81ad6265SDimitry Andric return std::make_unique<ELFWriter<ELF64BE>>(Obj, Out, !Config.StripSections, 150*81ad6265SDimitry Andric Config.OnlyKeepDebug); 151*81ad6265SDimitry Andric } 152*81ad6265SDimitry Andric llvm_unreachable("Invalid output format"); 153*81ad6265SDimitry Andric } 154*81ad6265SDimitry Andric 155*81ad6265SDimitry Andric static std::unique_ptr<Writer> createWriter(const CommonConfig &Config, 156*81ad6265SDimitry Andric Object &Obj, raw_ostream &Out, 157*81ad6265SDimitry Andric ElfType OutputElfType) { 158*81ad6265SDimitry Andric switch (Config.OutputFormat) { 159*81ad6265SDimitry Andric case FileFormat::Binary: 160*81ad6265SDimitry Andric return std::make_unique<BinaryWriter>(Obj, Out); 161*81ad6265SDimitry Andric case FileFormat::IHex: 162*81ad6265SDimitry Andric return std::make_unique<IHexWriter>(Obj, Out); 163*81ad6265SDimitry Andric default: 164*81ad6265SDimitry Andric return createELFWriter(Config, Obj, Out, OutputElfType); 165*81ad6265SDimitry Andric } 166*81ad6265SDimitry Andric } 167*81ad6265SDimitry Andric 168*81ad6265SDimitry Andric template <class... Ts> 169*81ad6265SDimitry Andric static Error makeStringError(std::error_code EC, const Twine &Msg, 170*81ad6265SDimitry Andric Ts &&...Args) { 171*81ad6265SDimitry Andric std::string FullMsg = (EC.message() + ": " + Msg).str(); 172*81ad6265SDimitry Andric return createStringError(EC, FullMsg.c_str(), std::forward<Ts>(Args)...); 173*81ad6265SDimitry Andric } 174*81ad6265SDimitry Andric 175*81ad6265SDimitry Andric static Error dumpSectionToFile(StringRef SecName, StringRef Filename, 176*81ad6265SDimitry Andric Object &Obj) { 177*81ad6265SDimitry Andric for (auto &Sec : Obj.sections()) { 178*81ad6265SDimitry Andric if (Sec.Name == SecName) { 179*81ad6265SDimitry Andric if (Sec.Type == SHT_NOBITS) 180*81ad6265SDimitry Andric return createStringError(object_error::parse_failed, 181*81ad6265SDimitry Andric "cannot dump section '%s': it has no contents", 182*81ad6265SDimitry Andric SecName.str().c_str()); 183*81ad6265SDimitry Andric Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = 184*81ad6265SDimitry Andric FileOutputBuffer::create(Filename, Sec.OriginalData.size()); 185*81ad6265SDimitry Andric if (!BufferOrErr) 186*81ad6265SDimitry Andric return BufferOrErr.takeError(); 187*81ad6265SDimitry Andric std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr); 188*81ad6265SDimitry Andric std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), 189*81ad6265SDimitry Andric Buf->getBufferStart()); 190*81ad6265SDimitry Andric if (Error E = Buf->commit()) 191*81ad6265SDimitry Andric return E; 192*81ad6265SDimitry Andric return Error::success(); 193*81ad6265SDimitry Andric } 194*81ad6265SDimitry Andric } 195*81ad6265SDimitry Andric return createStringError(object_error::parse_failed, "section '%s' not found", 196*81ad6265SDimitry Andric SecName.str().c_str()); 197*81ad6265SDimitry Andric } 198*81ad6265SDimitry Andric 199*81ad6265SDimitry Andric static bool isCompressable(const SectionBase &Sec) { 200*81ad6265SDimitry Andric return !(Sec.Flags & ELF::SHF_COMPRESSED) && 201*81ad6265SDimitry Andric StringRef(Sec.Name).startswith(".debug"); 202*81ad6265SDimitry Andric } 203*81ad6265SDimitry Andric 204*81ad6265SDimitry Andric static Error replaceDebugSections( 205*81ad6265SDimitry Andric Object &Obj, function_ref<bool(const SectionBase &)> ShouldReplace, 206*81ad6265SDimitry Andric function_ref<Expected<SectionBase *>(const SectionBase *)> AddSection) { 207*81ad6265SDimitry Andric // Build a list of the debug sections we are going to replace. 208*81ad6265SDimitry Andric // We can't call `AddSection` while iterating over sections, 209*81ad6265SDimitry Andric // because it would mutate the sections array. 210*81ad6265SDimitry Andric SmallVector<SectionBase *, 13> ToReplace; 211*81ad6265SDimitry Andric for (auto &Sec : Obj.sections()) 212*81ad6265SDimitry Andric if (ShouldReplace(Sec)) 213*81ad6265SDimitry Andric ToReplace.push_back(&Sec); 214*81ad6265SDimitry Andric 215*81ad6265SDimitry Andric // Build a mapping from original section to a new one. 216*81ad6265SDimitry Andric DenseMap<SectionBase *, SectionBase *> FromTo; 217*81ad6265SDimitry Andric for (SectionBase *S : ToReplace) { 218*81ad6265SDimitry Andric Expected<SectionBase *> NewSection = AddSection(S); 219*81ad6265SDimitry Andric if (!NewSection) 220*81ad6265SDimitry Andric return NewSection.takeError(); 221*81ad6265SDimitry Andric 222*81ad6265SDimitry Andric FromTo[S] = *NewSection; 223*81ad6265SDimitry Andric } 224*81ad6265SDimitry Andric 225*81ad6265SDimitry Andric return Obj.replaceSections(FromTo); 226*81ad6265SDimitry Andric } 227*81ad6265SDimitry Andric 228*81ad6265SDimitry Andric static bool isAArch64MappingSymbol(const Symbol &Sym) { 229*81ad6265SDimitry Andric if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE || 230*81ad6265SDimitry Andric Sym.getShndx() == SHN_UNDEF) 231*81ad6265SDimitry Andric return false; 232*81ad6265SDimitry Andric StringRef Name = Sym.Name; 233*81ad6265SDimitry Andric if (!Name.consume_front("$x") && !Name.consume_front("$d")) 234*81ad6265SDimitry Andric return false; 235*81ad6265SDimitry Andric return Name.empty() || Name.startswith("."); 236*81ad6265SDimitry Andric } 237*81ad6265SDimitry Andric 238*81ad6265SDimitry Andric static bool isArmMappingSymbol(const Symbol &Sym) { 239*81ad6265SDimitry Andric if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE || 240*81ad6265SDimitry Andric Sym.getShndx() == SHN_UNDEF) 241*81ad6265SDimitry Andric return false; 242*81ad6265SDimitry Andric StringRef Name = Sym.Name; 243*81ad6265SDimitry Andric if (!Name.consume_front("$a") && !Name.consume_front("$d") && 244*81ad6265SDimitry Andric !Name.consume_front("$t")) 245*81ad6265SDimitry Andric return false; 246*81ad6265SDimitry Andric return Name.empty() || Name.startswith("."); 247*81ad6265SDimitry Andric } 248*81ad6265SDimitry Andric 249*81ad6265SDimitry Andric // Check if the symbol should be preserved because it is required by ABI. 250*81ad6265SDimitry Andric static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym) { 251*81ad6265SDimitry Andric switch (Obj.Machine) { 252*81ad6265SDimitry Andric case EM_AARCH64: 253*81ad6265SDimitry Andric // Mapping symbols should be preserved for a relocatable object file. 254*81ad6265SDimitry Andric return Obj.isRelocatable() && isAArch64MappingSymbol(Sym); 255*81ad6265SDimitry Andric case EM_ARM: 256*81ad6265SDimitry Andric // Mapping symbols should be preserved for a relocatable object file. 257*81ad6265SDimitry Andric return Obj.isRelocatable() && isArmMappingSymbol(Sym); 258*81ad6265SDimitry Andric default: 259*81ad6265SDimitry Andric return false; 260*81ad6265SDimitry Andric } 261*81ad6265SDimitry Andric } 262*81ad6265SDimitry Andric 263*81ad6265SDimitry Andric static bool isUnneededSymbol(const Symbol &Sym) { 264*81ad6265SDimitry Andric return !Sym.Referenced && 265*81ad6265SDimitry Andric (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) && 266*81ad6265SDimitry Andric Sym.Type != STT_SECTION; 267*81ad6265SDimitry Andric } 268*81ad6265SDimitry Andric 269*81ad6265SDimitry Andric static Error updateAndRemoveSymbols(const CommonConfig &Config, 270*81ad6265SDimitry Andric const ELFConfig &ELFConfig, Object &Obj) { 271*81ad6265SDimitry Andric // TODO: update or remove symbols only if there is an option that affects 272*81ad6265SDimitry Andric // them. 273*81ad6265SDimitry Andric if (!Obj.SymbolTable) 274*81ad6265SDimitry Andric return Error::success(); 275*81ad6265SDimitry Andric 276*81ad6265SDimitry Andric Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { 277*81ad6265SDimitry Andric // Common and undefined symbols don't make sense as local symbols, and can 278*81ad6265SDimitry Andric // even cause crashes if we localize those, so skip them. 279*81ad6265SDimitry Andric if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF && 280*81ad6265SDimitry Andric ((ELFConfig.LocalizeHidden && 281*81ad6265SDimitry Andric (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || 282*81ad6265SDimitry Andric Config.SymbolsToLocalize.matches(Sym.Name))) 283*81ad6265SDimitry Andric Sym.Binding = STB_LOCAL; 284*81ad6265SDimitry Andric 285*81ad6265SDimitry Andric // Note: these two globalize flags have very similar names but different 286*81ad6265SDimitry Andric // meanings: 287*81ad6265SDimitry Andric // 288*81ad6265SDimitry Andric // --globalize-symbol: promote a symbol to global 289*81ad6265SDimitry Andric // --keep-global-symbol: all symbols except for these should be made local 290*81ad6265SDimitry Andric // 291*81ad6265SDimitry Andric // If --globalize-symbol is specified for a given symbol, it will be 292*81ad6265SDimitry Andric // global in the output file even if it is not included via 293*81ad6265SDimitry Andric // --keep-global-symbol. Because of that, make sure to check 294*81ad6265SDimitry Andric // --globalize-symbol second. 295*81ad6265SDimitry Andric if (!Config.SymbolsToKeepGlobal.empty() && 296*81ad6265SDimitry Andric !Config.SymbolsToKeepGlobal.matches(Sym.Name) && 297*81ad6265SDimitry Andric Sym.getShndx() != SHN_UNDEF) 298*81ad6265SDimitry Andric Sym.Binding = STB_LOCAL; 299*81ad6265SDimitry Andric 300*81ad6265SDimitry Andric if (Config.SymbolsToGlobalize.matches(Sym.Name) && 301*81ad6265SDimitry Andric Sym.getShndx() != SHN_UNDEF) 302*81ad6265SDimitry Andric Sym.Binding = STB_GLOBAL; 303*81ad6265SDimitry Andric 304*81ad6265SDimitry Andric // SymbolsToWeaken applies to both STB_GLOBAL and STB_GNU_UNIQUE. 305*81ad6265SDimitry Andric if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding != STB_LOCAL) 306*81ad6265SDimitry Andric Sym.Binding = STB_WEAK; 307*81ad6265SDimitry Andric 308*81ad6265SDimitry Andric if (Config.Weaken && Sym.Binding != STB_LOCAL && 309*81ad6265SDimitry Andric Sym.getShndx() != SHN_UNDEF) 310*81ad6265SDimitry Andric Sym.Binding = STB_WEAK; 311*81ad6265SDimitry Andric 312*81ad6265SDimitry Andric const auto I = Config.SymbolsToRename.find(Sym.Name); 313*81ad6265SDimitry Andric if (I != Config.SymbolsToRename.end()) 314*81ad6265SDimitry Andric Sym.Name = std::string(I->getValue()); 315*81ad6265SDimitry Andric 316*81ad6265SDimitry Andric if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION) 317*81ad6265SDimitry Andric Sym.Name = (Config.SymbolsPrefix + Sym.Name).str(); 318*81ad6265SDimitry Andric }); 319*81ad6265SDimitry Andric 320*81ad6265SDimitry Andric // The purpose of this loop is to mark symbols referenced by sections 321*81ad6265SDimitry Andric // (like GroupSection or RelocationSection). This way, we know which 322*81ad6265SDimitry Andric // symbols are still 'needed' and which are not. 323*81ad6265SDimitry Andric if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() || 324*81ad6265SDimitry Andric !Config.OnlySection.empty()) { 325*81ad6265SDimitry Andric for (SectionBase &Sec : Obj.sections()) 326*81ad6265SDimitry Andric Sec.markSymbols(); 327*81ad6265SDimitry Andric } 328*81ad6265SDimitry Andric 329*81ad6265SDimitry Andric auto RemoveSymbolsPred = [&](const Symbol &Sym) { 330*81ad6265SDimitry Andric if (Config.SymbolsToKeep.matches(Sym.Name) || 331*81ad6265SDimitry Andric (ELFConfig.KeepFileSymbols && Sym.Type == STT_FILE)) 332*81ad6265SDimitry Andric return false; 333*81ad6265SDimitry Andric 334*81ad6265SDimitry Andric if (Config.SymbolsToRemove.matches(Sym.Name)) 335*81ad6265SDimitry Andric return true; 336*81ad6265SDimitry Andric 337*81ad6265SDimitry Andric if (Config.StripAll || Config.StripAllGNU) 338*81ad6265SDimitry Andric return true; 339*81ad6265SDimitry Andric 340*81ad6265SDimitry Andric if (isRequiredByABISymbol(Obj, Sym)) 341*81ad6265SDimitry Andric return false; 342*81ad6265SDimitry Andric 343*81ad6265SDimitry Andric if (Config.StripDebug && Sym.Type == STT_FILE) 344*81ad6265SDimitry Andric return true; 345*81ad6265SDimitry Andric 346*81ad6265SDimitry Andric if ((Config.DiscardMode == DiscardType::All || 347*81ad6265SDimitry Andric (Config.DiscardMode == DiscardType::Locals && 348*81ad6265SDimitry Andric StringRef(Sym.Name).startswith(".L"))) && 349*81ad6265SDimitry Andric Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF && 350*81ad6265SDimitry Andric Sym.Type != STT_FILE && Sym.Type != STT_SECTION) 351*81ad6265SDimitry Andric return true; 352*81ad6265SDimitry Andric 353*81ad6265SDimitry Andric if ((Config.StripUnneeded || 354*81ad6265SDimitry Andric Config.UnneededSymbolsToRemove.matches(Sym.Name)) && 355*81ad6265SDimitry Andric (!Obj.isRelocatable() || isUnneededSymbol(Sym))) 356*81ad6265SDimitry Andric return true; 357*81ad6265SDimitry Andric 358*81ad6265SDimitry Andric // We want to remove undefined symbols if all references have been stripped. 359*81ad6265SDimitry Andric if (!Config.OnlySection.empty() && !Sym.Referenced && 360*81ad6265SDimitry Andric Sym.getShndx() == SHN_UNDEF) 361*81ad6265SDimitry Andric return true; 362*81ad6265SDimitry Andric 363*81ad6265SDimitry Andric return false; 364*81ad6265SDimitry Andric }; 365*81ad6265SDimitry Andric 366*81ad6265SDimitry Andric return Obj.removeSymbols(RemoveSymbolsPred); 367*81ad6265SDimitry Andric } 368*81ad6265SDimitry Andric 369*81ad6265SDimitry Andric static Error replaceAndRemoveSections(const CommonConfig &Config, 370*81ad6265SDimitry Andric const ELFConfig &ELFConfig, Object &Obj) { 371*81ad6265SDimitry Andric SectionPred RemovePred = [](const SectionBase &) { return false; }; 372*81ad6265SDimitry Andric 373*81ad6265SDimitry Andric // Removes: 374*81ad6265SDimitry Andric if (!Config.ToRemove.empty()) { 375*81ad6265SDimitry Andric RemovePred = [&Config](const SectionBase &Sec) { 376*81ad6265SDimitry Andric return Config.ToRemove.matches(Sec.Name); 377*81ad6265SDimitry Andric }; 378*81ad6265SDimitry Andric } 379*81ad6265SDimitry Andric 380*81ad6265SDimitry Andric if (Config.StripDWO) 381*81ad6265SDimitry Andric RemovePred = [RemovePred](const SectionBase &Sec) { 382*81ad6265SDimitry Andric return isDWOSection(Sec) || RemovePred(Sec); 383*81ad6265SDimitry Andric }; 384*81ad6265SDimitry Andric 385*81ad6265SDimitry Andric if (Config.ExtractDWO) 386*81ad6265SDimitry Andric RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 387*81ad6265SDimitry Andric return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec); 388*81ad6265SDimitry Andric }; 389*81ad6265SDimitry Andric 390*81ad6265SDimitry Andric if (Config.StripAllGNU) 391*81ad6265SDimitry Andric RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 392*81ad6265SDimitry Andric if (RemovePred(Sec)) 393*81ad6265SDimitry Andric return true; 394*81ad6265SDimitry Andric if ((Sec.Flags & SHF_ALLOC) != 0) 395*81ad6265SDimitry Andric return false; 396*81ad6265SDimitry Andric if (&Sec == Obj.SectionNames) 397*81ad6265SDimitry Andric return false; 398*81ad6265SDimitry Andric switch (Sec.Type) { 399*81ad6265SDimitry Andric case SHT_SYMTAB: 400*81ad6265SDimitry Andric case SHT_REL: 401*81ad6265SDimitry Andric case SHT_RELA: 402*81ad6265SDimitry Andric case SHT_STRTAB: 403*81ad6265SDimitry Andric return true; 404*81ad6265SDimitry Andric } 405*81ad6265SDimitry Andric return isDebugSection(Sec); 406*81ad6265SDimitry Andric }; 407*81ad6265SDimitry Andric 408*81ad6265SDimitry Andric if (Config.StripSections) { 409*81ad6265SDimitry Andric RemovePred = [RemovePred](const SectionBase &Sec) { 410*81ad6265SDimitry Andric return RemovePred(Sec) || Sec.ParentSegment == nullptr; 411*81ad6265SDimitry Andric }; 412*81ad6265SDimitry Andric } 413*81ad6265SDimitry Andric 414*81ad6265SDimitry Andric if (Config.StripDebug || Config.StripUnneeded) { 415*81ad6265SDimitry Andric RemovePred = [RemovePred](const SectionBase &Sec) { 416*81ad6265SDimitry Andric return RemovePred(Sec) || isDebugSection(Sec); 417*81ad6265SDimitry Andric }; 418*81ad6265SDimitry Andric } 419*81ad6265SDimitry Andric 420*81ad6265SDimitry Andric if (Config.StripNonAlloc) 421*81ad6265SDimitry Andric RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 422*81ad6265SDimitry Andric if (RemovePred(Sec)) 423*81ad6265SDimitry Andric return true; 424*81ad6265SDimitry Andric if (&Sec == Obj.SectionNames) 425*81ad6265SDimitry Andric return false; 426*81ad6265SDimitry Andric return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr; 427*81ad6265SDimitry Andric }; 428*81ad6265SDimitry Andric 429*81ad6265SDimitry Andric if (Config.StripAll) 430*81ad6265SDimitry Andric RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 431*81ad6265SDimitry Andric if (RemovePred(Sec)) 432*81ad6265SDimitry Andric return true; 433*81ad6265SDimitry Andric if (&Sec == Obj.SectionNames) 434*81ad6265SDimitry Andric return false; 435*81ad6265SDimitry Andric if (StringRef(Sec.Name).startswith(".gnu.warning")) 436*81ad6265SDimitry Andric return false; 437*81ad6265SDimitry Andric // We keep the .ARM.attribute section to maintain compatibility 438*81ad6265SDimitry Andric // with Debian derived distributions. This is a bug in their 439*81ad6265SDimitry Andric // patchset as documented here: 440*81ad6265SDimitry Andric // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798 441*81ad6265SDimitry Andric if (Sec.Type == SHT_ARM_ATTRIBUTES) 442*81ad6265SDimitry Andric return false; 443*81ad6265SDimitry Andric if (Sec.ParentSegment != nullptr) 444*81ad6265SDimitry Andric return false; 445*81ad6265SDimitry Andric return (Sec.Flags & SHF_ALLOC) == 0; 446*81ad6265SDimitry Andric }; 447*81ad6265SDimitry Andric 448*81ad6265SDimitry Andric if (Config.ExtractPartition || Config.ExtractMainPartition) { 449*81ad6265SDimitry Andric RemovePred = [RemovePred](const SectionBase &Sec) { 450*81ad6265SDimitry Andric if (RemovePred(Sec)) 451*81ad6265SDimitry Andric return true; 452*81ad6265SDimitry Andric if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR) 453*81ad6265SDimitry Andric return true; 454*81ad6265SDimitry Andric return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment; 455*81ad6265SDimitry Andric }; 456*81ad6265SDimitry Andric } 457*81ad6265SDimitry Andric 458*81ad6265SDimitry Andric // Explicit copies: 459*81ad6265SDimitry Andric if (!Config.OnlySection.empty()) { 460*81ad6265SDimitry Andric RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) { 461*81ad6265SDimitry Andric // Explicitly keep these sections regardless of previous removes. 462*81ad6265SDimitry Andric if (Config.OnlySection.matches(Sec.Name)) 463*81ad6265SDimitry Andric return false; 464*81ad6265SDimitry Andric 465*81ad6265SDimitry Andric // Allow all implicit removes. 466*81ad6265SDimitry Andric if (RemovePred(Sec)) 467*81ad6265SDimitry Andric return true; 468*81ad6265SDimitry Andric 469*81ad6265SDimitry Andric // Keep special sections. 470*81ad6265SDimitry Andric if (Obj.SectionNames == &Sec) 471*81ad6265SDimitry Andric return false; 472*81ad6265SDimitry Andric if (Obj.SymbolTable == &Sec || 473*81ad6265SDimitry Andric (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec)) 474*81ad6265SDimitry Andric return false; 475*81ad6265SDimitry Andric 476*81ad6265SDimitry Andric // Remove everything else. 477*81ad6265SDimitry Andric return true; 478*81ad6265SDimitry Andric }; 479*81ad6265SDimitry Andric } 480*81ad6265SDimitry Andric 481*81ad6265SDimitry Andric if (!Config.KeepSection.empty()) { 482*81ad6265SDimitry Andric RemovePred = [&Config, RemovePred](const SectionBase &Sec) { 483*81ad6265SDimitry Andric // Explicitly keep these sections regardless of previous removes. 484*81ad6265SDimitry Andric if (Config.KeepSection.matches(Sec.Name)) 485*81ad6265SDimitry Andric return false; 486*81ad6265SDimitry Andric // Otherwise defer to RemovePred. 487*81ad6265SDimitry Andric return RemovePred(Sec); 488*81ad6265SDimitry Andric }; 489*81ad6265SDimitry Andric } 490*81ad6265SDimitry Andric 491*81ad6265SDimitry Andric // This has to be the last predicate assignment. 492*81ad6265SDimitry Andric // If the option --keep-symbol has been specified 493*81ad6265SDimitry Andric // and at least one of those symbols is present 494*81ad6265SDimitry Andric // (equivalently, the updated symbol table is not empty) 495*81ad6265SDimitry Andric // the symbol table and the string table should not be removed. 496*81ad6265SDimitry Andric if ((!Config.SymbolsToKeep.empty() || ELFConfig.KeepFileSymbols) && 497*81ad6265SDimitry Andric Obj.SymbolTable && !Obj.SymbolTable->empty()) { 498*81ad6265SDimitry Andric RemovePred = [&Obj, RemovePred](const SectionBase &Sec) { 499*81ad6265SDimitry Andric if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab()) 500*81ad6265SDimitry Andric return false; 501*81ad6265SDimitry Andric return RemovePred(Sec); 502*81ad6265SDimitry Andric }; 503*81ad6265SDimitry Andric } 504*81ad6265SDimitry Andric 505*81ad6265SDimitry Andric if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred)) 506*81ad6265SDimitry Andric return E; 507*81ad6265SDimitry Andric 508*81ad6265SDimitry Andric if (Config.CompressionType != DebugCompressionType::None) { 509*81ad6265SDimitry Andric if (Error Err = replaceDebugSections( 510*81ad6265SDimitry Andric Obj, isCompressable, 511*81ad6265SDimitry Andric [&Config, &Obj](const SectionBase *S) -> Expected<SectionBase *> { 512*81ad6265SDimitry Andric return &Obj.addSection<CompressedSection>( 513*81ad6265SDimitry Andric CompressedSection(*S, Config.CompressionType)); 514*81ad6265SDimitry Andric })) 515*81ad6265SDimitry Andric return Err; 516*81ad6265SDimitry Andric } else if (Config.DecompressDebugSections) { 517*81ad6265SDimitry Andric if (Error Err = replaceDebugSections( 518*81ad6265SDimitry Andric Obj, 519*81ad6265SDimitry Andric [](const SectionBase &S) { return isa<CompressedSection>(&S); }, 520*81ad6265SDimitry Andric [&Obj](const SectionBase *S) { 521*81ad6265SDimitry Andric const CompressedSection *CS = cast<CompressedSection>(S); 522*81ad6265SDimitry Andric return &Obj.addSection<DecompressedSection>(*CS); 523*81ad6265SDimitry Andric })) 524*81ad6265SDimitry Andric return Err; 525*81ad6265SDimitry Andric } 526*81ad6265SDimitry Andric 527*81ad6265SDimitry Andric return Error::success(); 528*81ad6265SDimitry Andric } 529*81ad6265SDimitry Andric 530*81ad6265SDimitry Andric // Add symbol to the Object symbol table with the specified properties. 531*81ad6265SDimitry Andric static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo, 532*81ad6265SDimitry Andric uint8_t DefaultVisibility) { 533*81ad6265SDimitry Andric SectionBase *Sec = Obj.findSection(SymInfo.SectionName); 534*81ad6265SDimitry Andric uint64_t Value = Sec ? Sec->Addr + SymInfo.Value : SymInfo.Value; 535*81ad6265SDimitry Andric 536*81ad6265SDimitry Andric uint8_t Bind = ELF::STB_GLOBAL; 537*81ad6265SDimitry Andric uint8_t Type = ELF::STT_NOTYPE; 538*81ad6265SDimitry Andric uint8_t Visibility = DefaultVisibility; 539*81ad6265SDimitry Andric 540*81ad6265SDimitry Andric for (SymbolFlag FlagValue : SymInfo.Flags) 541*81ad6265SDimitry Andric switch (FlagValue) { 542*81ad6265SDimitry Andric case SymbolFlag::Global: 543*81ad6265SDimitry Andric Bind = ELF::STB_GLOBAL; 544*81ad6265SDimitry Andric break; 545*81ad6265SDimitry Andric case SymbolFlag::Local: 546*81ad6265SDimitry Andric Bind = ELF::STB_LOCAL; 547*81ad6265SDimitry Andric break; 548*81ad6265SDimitry Andric case SymbolFlag::Weak: 549*81ad6265SDimitry Andric Bind = ELF::STB_WEAK; 550*81ad6265SDimitry Andric break; 551*81ad6265SDimitry Andric case SymbolFlag::Default: 552*81ad6265SDimitry Andric Visibility = ELF::STV_DEFAULT; 553*81ad6265SDimitry Andric break; 554*81ad6265SDimitry Andric case SymbolFlag::Hidden: 555*81ad6265SDimitry Andric Visibility = ELF::STV_HIDDEN; 556*81ad6265SDimitry Andric break; 557*81ad6265SDimitry Andric case SymbolFlag::Protected: 558*81ad6265SDimitry Andric Visibility = ELF::STV_PROTECTED; 559*81ad6265SDimitry Andric break; 560*81ad6265SDimitry Andric case SymbolFlag::File: 561*81ad6265SDimitry Andric Type = ELF::STT_FILE; 562*81ad6265SDimitry Andric break; 563*81ad6265SDimitry Andric case SymbolFlag::Section: 564*81ad6265SDimitry Andric Type = ELF::STT_SECTION; 565*81ad6265SDimitry Andric break; 566*81ad6265SDimitry Andric case SymbolFlag::Object: 567*81ad6265SDimitry Andric Type = ELF::STT_OBJECT; 568*81ad6265SDimitry Andric break; 569*81ad6265SDimitry Andric case SymbolFlag::Function: 570*81ad6265SDimitry Andric Type = ELF::STT_FUNC; 571*81ad6265SDimitry Andric break; 572*81ad6265SDimitry Andric case SymbolFlag::IndirectFunction: 573*81ad6265SDimitry Andric Type = ELF::STT_GNU_IFUNC; 574*81ad6265SDimitry Andric break; 575*81ad6265SDimitry Andric default: /* Other flag values are ignored for ELF. */ 576*81ad6265SDimitry Andric break; 577*81ad6265SDimitry Andric }; 578*81ad6265SDimitry Andric 579*81ad6265SDimitry Andric Obj.SymbolTable->addSymbol( 580*81ad6265SDimitry Andric SymInfo.SymbolName, Bind, Type, Sec, Value, Visibility, 581*81ad6265SDimitry Andric Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0); 582*81ad6265SDimitry Andric } 583*81ad6265SDimitry Andric 584*81ad6265SDimitry Andric static Error 585*81ad6265SDimitry Andric handleUserSection(const NewSectionInfo &NewSection, 586*81ad6265SDimitry Andric function_ref<Error(StringRef, ArrayRef<uint8_t>)> F) { 587*81ad6265SDimitry Andric ArrayRef<uint8_t> Data(reinterpret_cast<const uint8_t *>( 588*81ad6265SDimitry Andric NewSection.SectionData->getBufferStart()), 589*81ad6265SDimitry Andric NewSection.SectionData->getBufferSize()); 590*81ad6265SDimitry Andric return F(NewSection.SectionName, Data); 591*81ad6265SDimitry Andric } 592*81ad6265SDimitry Andric 593*81ad6265SDimitry Andric // This function handles the high level operations of GNU objcopy including 594*81ad6265SDimitry Andric // handling command line options. It's important to outline certain properties 595*81ad6265SDimitry Andric // we expect to hold of the command line operations. Any operation that "keeps" 596*81ad6265SDimitry Andric // should keep regardless of a remove. Additionally any removal should respect 597*81ad6265SDimitry Andric // any previous removals. Lastly whether or not something is removed shouldn't 598*81ad6265SDimitry Andric // depend a) on the order the options occur in or b) on some opaque priority 599*81ad6265SDimitry Andric // system. The only priority is that keeps/copies overrule removes. 600*81ad6265SDimitry Andric static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig, 601*81ad6265SDimitry Andric Object &Obj) { 602*81ad6265SDimitry Andric if (Config.OutputArch) { 603*81ad6265SDimitry Andric Obj.Machine = Config.OutputArch.getValue().EMachine; 604*81ad6265SDimitry Andric Obj.OSABI = Config.OutputArch.getValue().OSABI; 605*81ad6265SDimitry Andric } 606*81ad6265SDimitry Andric 607*81ad6265SDimitry Andric if (!Config.SplitDWO.empty() && Config.ExtractDWO) { 608*81ad6265SDimitry Andric return Obj.removeSections( 609*81ad6265SDimitry Andric ELFConfig.AllowBrokenLinks, 610*81ad6265SDimitry Andric [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); }); 611*81ad6265SDimitry Andric } 612*81ad6265SDimitry Andric 613*81ad6265SDimitry Andric // Dump sections before add/remove for compatibility with GNU objcopy. 614*81ad6265SDimitry Andric for (StringRef Flag : Config.DumpSection) { 615*81ad6265SDimitry Andric StringRef SectionName; 616*81ad6265SDimitry Andric StringRef FileName; 617*81ad6265SDimitry Andric std::tie(SectionName, FileName) = Flag.split('='); 618*81ad6265SDimitry Andric if (Error E = dumpSectionToFile(SectionName, FileName, Obj)) 619*81ad6265SDimitry Andric return E; 620*81ad6265SDimitry Andric } 621*81ad6265SDimitry Andric 622*81ad6265SDimitry Andric // It is important to remove the sections first. For example, we want to 623*81ad6265SDimitry Andric // remove the relocation sections before removing the symbols. That allows 624*81ad6265SDimitry Andric // us to avoid reporting the inappropriate errors about removing symbols 625*81ad6265SDimitry Andric // named in relocations. 626*81ad6265SDimitry Andric if (Error E = replaceAndRemoveSections(Config, ELFConfig, Obj)) 627*81ad6265SDimitry Andric return E; 628*81ad6265SDimitry Andric 629*81ad6265SDimitry Andric if (Error E = updateAndRemoveSymbols(Config, ELFConfig, Obj)) 630*81ad6265SDimitry Andric return E; 631*81ad6265SDimitry Andric 632*81ad6265SDimitry Andric if (!Config.SectionsToRename.empty()) { 633*81ad6265SDimitry Andric std::vector<RelocationSectionBase *> RelocSections; 634*81ad6265SDimitry Andric DenseSet<SectionBase *> RenamedSections; 635*81ad6265SDimitry Andric for (SectionBase &Sec : Obj.sections()) { 636*81ad6265SDimitry Andric auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec); 637*81ad6265SDimitry Andric const auto Iter = Config.SectionsToRename.find(Sec.Name); 638*81ad6265SDimitry Andric if (Iter != Config.SectionsToRename.end()) { 639*81ad6265SDimitry Andric const SectionRename &SR = Iter->second; 640*81ad6265SDimitry Andric Sec.Name = std::string(SR.NewName); 641*81ad6265SDimitry Andric if (SR.NewFlags) 642*81ad6265SDimitry Andric setSectionFlagsAndType(Sec, SR.NewFlags.getValue()); 643*81ad6265SDimitry Andric RenamedSections.insert(&Sec); 644*81ad6265SDimitry Andric } else if (RelocSec && !(Sec.Flags & SHF_ALLOC)) 645*81ad6265SDimitry Andric // Postpone processing relocation sections which are not specified in 646*81ad6265SDimitry Andric // their explicit '--rename-section' commands until after their target 647*81ad6265SDimitry Andric // sections are renamed. 648*81ad6265SDimitry Andric // Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be 649*81ad6265SDimitry Andric // renamed only explicitly. Otherwise, renaming, for example, '.got.plt' 650*81ad6265SDimitry Andric // would affect '.rela.plt', which is not desirable. 651*81ad6265SDimitry Andric RelocSections.push_back(RelocSec); 652*81ad6265SDimitry Andric } 653*81ad6265SDimitry Andric 654*81ad6265SDimitry Andric // Rename relocation sections according to their target sections. 655*81ad6265SDimitry Andric for (RelocationSectionBase *RelocSec : RelocSections) { 656*81ad6265SDimitry Andric auto Iter = RenamedSections.find(RelocSec->getSection()); 657*81ad6265SDimitry Andric if (Iter != RenamedSections.end()) 658*81ad6265SDimitry Andric RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str(); 659*81ad6265SDimitry Andric } 660*81ad6265SDimitry Andric } 661*81ad6265SDimitry Andric 662*81ad6265SDimitry Andric // Add a prefix to allocated sections and their relocation sections. This 663*81ad6265SDimitry Andric // should be done after renaming the section by Config.SectionToRename to 664*81ad6265SDimitry Andric // imitate the GNU objcopy behavior. 665*81ad6265SDimitry Andric if (!Config.AllocSectionsPrefix.empty()) { 666*81ad6265SDimitry Andric DenseSet<SectionBase *> PrefixedSections; 667*81ad6265SDimitry Andric for (SectionBase &Sec : Obj.sections()) { 668*81ad6265SDimitry Andric if (Sec.Flags & SHF_ALLOC) { 669*81ad6265SDimitry Andric Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str(); 670*81ad6265SDimitry Andric PrefixedSections.insert(&Sec); 671*81ad6265SDimitry Andric } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) { 672*81ad6265SDimitry Andric // Rename relocation sections associated to the allocated sections. 673*81ad6265SDimitry Andric // For example, if we rename .text to .prefix.text, we also rename 674*81ad6265SDimitry Andric // .rel.text to .rel.prefix.text. 675*81ad6265SDimitry Andric // 676*81ad6265SDimitry Andric // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled 677*81ad6265SDimitry Andric // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not 678*81ad6265SDimitry Andric // .rela.prefix.plt since GNU objcopy does so. 679*81ad6265SDimitry Andric const SectionBase *TargetSec = RelocSec->getSection(); 680*81ad6265SDimitry Andric if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) { 681*81ad6265SDimitry Andric // If the relocation section comes *after* the target section, we 682*81ad6265SDimitry Andric // don't add Config.AllocSectionsPrefix because we've already added 683*81ad6265SDimitry Andric // the prefix to TargetSec->Name. Otherwise, if the relocation 684*81ad6265SDimitry Andric // section comes *before* the target section, we add the prefix. 685*81ad6265SDimitry Andric if (PrefixedSections.count(TargetSec)) 686*81ad6265SDimitry Andric Sec.Name = (RelocSec->getNamePrefix() + TargetSec->Name).str(); 687*81ad6265SDimitry Andric else 688*81ad6265SDimitry Andric Sec.Name = (RelocSec->getNamePrefix() + Config.AllocSectionsPrefix + 689*81ad6265SDimitry Andric TargetSec->Name) 690*81ad6265SDimitry Andric .str(); 691*81ad6265SDimitry Andric } 692*81ad6265SDimitry Andric } 693*81ad6265SDimitry Andric } 694*81ad6265SDimitry Andric } 695*81ad6265SDimitry Andric 696*81ad6265SDimitry Andric if (!Config.SetSectionAlignment.empty()) { 697*81ad6265SDimitry Andric for (SectionBase &Sec : Obj.sections()) { 698*81ad6265SDimitry Andric auto I = Config.SetSectionAlignment.find(Sec.Name); 699*81ad6265SDimitry Andric if (I != Config.SetSectionAlignment.end()) 700*81ad6265SDimitry Andric Sec.Align = I->second; 701*81ad6265SDimitry Andric } 702*81ad6265SDimitry Andric } 703*81ad6265SDimitry Andric 704*81ad6265SDimitry Andric if (Config.OnlyKeepDebug) 705*81ad6265SDimitry Andric for (auto &Sec : Obj.sections()) 706*81ad6265SDimitry Andric if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE) 707*81ad6265SDimitry Andric Sec.Type = SHT_NOBITS; 708*81ad6265SDimitry Andric 709*81ad6265SDimitry Andric for (const NewSectionInfo &AddedSection : Config.AddSection) { 710*81ad6265SDimitry Andric auto AddSection = [&](StringRef Name, ArrayRef<uint8_t> Data) { 711*81ad6265SDimitry Andric OwnedDataSection &NewSection = 712*81ad6265SDimitry Andric Obj.addSection<OwnedDataSection>(Name, Data); 713*81ad6265SDimitry Andric if (Name.startswith(".note") && Name != ".note.GNU-stack") 714*81ad6265SDimitry Andric NewSection.Type = SHT_NOTE; 715*81ad6265SDimitry Andric return Error::success(); 716*81ad6265SDimitry Andric }; 717*81ad6265SDimitry Andric if (Error E = handleUserSection(AddedSection, AddSection)) 718*81ad6265SDimitry Andric return E; 719*81ad6265SDimitry Andric } 720*81ad6265SDimitry Andric 721*81ad6265SDimitry Andric for (const NewSectionInfo &NewSection : Config.UpdateSection) { 722*81ad6265SDimitry Andric auto UpdateSection = [&](StringRef Name, ArrayRef<uint8_t> Data) { 723*81ad6265SDimitry Andric return Obj.updateSection(Name, Data); 724*81ad6265SDimitry Andric }; 725*81ad6265SDimitry Andric if (Error E = handleUserSection(NewSection, UpdateSection)) 726*81ad6265SDimitry Andric return E; 727*81ad6265SDimitry Andric } 728*81ad6265SDimitry Andric 729*81ad6265SDimitry Andric if (!Config.AddGnuDebugLink.empty()) 730*81ad6265SDimitry Andric Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink, 731*81ad6265SDimitry Andric Config.GnuDebugLinkCRC32); 732*81ad6265SDimitry Andric 733*81ad6265SDimitry Andric // If the symbol table was previously removed, we need to create a new one 734*81ad6265SDimitry Andric // before adding new symbols. 735*81ad6265SDimitry Andric if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty()) 736*81ad6265SDimitry Andric if (Error E = Obj.addNewSymbolTable()) 737*81ad6265SDimitry Andric return E; 738*81ad6265SDimitry Andric 739*81ad6265SDimitry Andric for (const NewSymbolInfo &SI : Config.SymbolsToAdd) 740*81ad6265SDimitry Andric addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility); 741*81ad6265SDimitry Andric 742*81ad6265SDimitry Andric // --set-section-flags works with sections added by --add-section. 743*81ad6265SDimitry Andric if (!Config.SetSectionFlags.empty()) { 744*81ad6265SDimitry Andric for (auto &Sec : Obj.sections()) { 745*81ad6265SDimitry Andric const auto Iter = Config.SetSectionFlags.find(Sec.Name); 746*81ad6265SDimitry Andric if (Iter != Config.SetSectionFlags.end()) { 747*81ad6265SDimitry Andric const SectionFlagsUpdate &SFU = Iter->second; 748*81ad6265SDimitry Andric setSectionFlagsAndType(Sec, SFU.NewFlags); 749*81ad6265SDimitry Andric } 750*81ad6265SDimitry Andric } 751*81ad6265SDimitry Andric } 752*81ad6265SDimitry Andric 753*81ad6265SDimitry Andric if (ELFConfig.EntryExpr) 754*81ad6265SDimitry Andric Obj.Entry = ELFConfig.EntryExpr(Obj.Entry); 755*81ad6265SDimitry Andric return Error::success(); 756*81ad6265SDimitry Andric } 757*81ad6265SDimitry Andric 758*81ad6265SDimitry Andric static Error writeOutput(const CommonConfig &Config, Object &Obj, 759*81ad6265SDimitry Andric raw_ostream &Out, ElfType OutputElfType) { 760*81ad6265SDimitry Andric std::unique_ptr<Writer> Writer = 761*81ad6265SDimitry Andric createWriter(Config, Obj, Out, OutputElfType); 762*81ad6265SDimitry Andric if (Error E = Writer->finalize()) 763*81ad6265SDimitry Andric return E; 764*81ad6265SDimitry Andric return Writer->write(); 765*81ad6265SDimitry Andric } 766*81ad6265SDimitry Andric 767*81ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config, 768*81ad6265SDimitry Andric const ELFConfig &ELFConfig, 769*81ad6265SDimitry Andric MemoryBuffer &In, raw_ostream &Out) { 770*81ad6265SDimitry Andric IHexReader Reader(&In); 771*81ad6265SDimitry Andric Expected<std::unique_ptr<Object>> Obj = Reader.create(true); 772*81ad6265SDimitry Andric if (!Obj) 773*81ad6265SDimitry Andric return Obj.takeError(); 774*81ad6265SDimitry Andric 775*81ad6265SDimitry Andric const ElfType OutputElfType = 776*81ad6265SDimitry Andric getOutputElfType(Config.OutputArch.value_or(MachineInfo())); 777*81ad6265SDimitry Andric if (Error E = handleArgs(Config, ELFConfig, **Obj)) 778*81ad6265SDimitry Andric return E; 779*81ad6265SDimitry Andric return writeOutput(Config, **Obj, Out, OutputElfType); 780*81ad6265SDimitry Andric } 781*81ad6265SDimitry Andric 782*81ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config, 783*81ad6265SDimitry Andric const ELFConfig &ELFConfig, 784*81ad6265SDimitry Andric MemoryBuffer &In, 785*81ad6265SDimitry Andric raw_ostream &Out) { 786*81ad6265SDimitry Andric BinaryReader Reader(&In, ELFConfig.NewSymbolVisibility); 787*81ad6265SDimitry Andric Expected<std::unique_ptr<Object>> Obj = Reader.create(true); 788*81ad6265SDimitry Andric if (!Obj) 789*81ad6265SDimitry Andric return Obj.takeError(); 790*81ad6265SDimitry Andric 791*81ad6265SDimitry Andric // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch 792*81ad6265SDimitry Andric // (-B<arch>). 793*81ad6265SDimitry Andric const ElfType OutputElfType = 794*81ad6265SDimitry Andric getOutputElfType(Config.OutputArch.value_or(MachineInfo())); 795*81ad6265SDimitry Andric if (Error E = handleArgs(Config, ELFConfig, **Obj)) 796*81ad6265SDimitry Andric return E; 797*81ad6265SDimitry Andric return writeOutput(Config, **Obj, Out, OutputElfType); 798*81ad6265SDimitry Andric } 799*81ad6265SDimitry Andric 800*81ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config, 801*81ad6265SDimitry Andric const ELFConfig &ELFConfig, 802*81ad6265SDimitry Andric object::ELFObjectFileBase &In, 803*81ad6265SDimitry Andric raw_ostream &Out) { 804*81ad6265SDimitry Andric ELFReader Reader(&In, Config.ExtractPartition); 805*81ad6265SDimitry Andric Expected<std::unique_ptr<Object>> Obj = 806*81ad6265SDimitry Andric Reader.create(!Config.SymbolsToAdd.empty()); 807*81ad6265SDimitry Andric if (!Obj) 808*81ad6265SDimitry Andric return Obj.takeError(); 809*81ad6265SDimitry Andric // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input. 810*81ad6265SDimitry Andric const ElfType OutputElfType = 811*81ad6265SDimitry Andric Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue()) 812*81ad6265SDimitry Andric : getOutputElfType(In); 813*81ad6265SDimitry Andric 814*81ad6265SDimitry Andric if (Error E = handleArgs(Config, ELFConfig, **Obj)) 815*81ad6265SDimitry Andric return createFileError(Config.InputFilename, std::move(E)); 816*81ad6265SDimitry Andric 817*81ad6265SDimitry Andric if (Error E = writeOutput(Config, **Obj, Out, OutputElfType)) 818*81ad6265SDimitry Andric return createFileError(Config.InputFilename, std::move(E)); 819*81ad6265SDimitry Andric 820*81ad6265SDimitry Andric return Error::success(); 821*81ad6265SDimitry Andric } 822