181ad6265SDimitry Andric //===- ELFObjcopy.cpp -----------------------------------------------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "llvm/ObjCopy/ELF/ELFObjcopy.h" 1081ad6265SDimitry Andric #include "ELFObject.h" 1181ad6265SDimitry Andric #include "llvm/ADT/BitmaskEnum.h" 1281ad6265SDimitry Andric #include "llvm/ADT/DenseSet.h" 1381ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 1481ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 1581ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 1681ad6265SDimitry Andric #include "llvm/ADT/Twine.h" 1781ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 1881ad6265SDimitry Andric #include "llvm/MC/MCTargetOptions.h" 1981ad6265SDimitry Andric #include "llvm/ObjCopy/CommonConfig.h" 2081ad6265SDimitry Andric #include "llvm/ObjCopy/ELF/ELFConfig.h" 2181ad6265SDimitry Andric #include "llvm/Object/Binary.h" 2281ad6265SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 2381ad6265SDimitry Andric #include "llvm/Object/ELFTypes.h" 2481ad6265SDimitry Andric #include "llvm/Object/Error.h" 2581ad6265SDimitry Andric #include "llvm/Option/Option.h" 2681ad6265SDimitry Andric #include "llvm/Support/Casting.h" 2781ad6265SDimitry Andric #include "llvm/Support/Compression.h" 2881ad6265SDimitry Andric #include "llvm/Support/Errc.h" 2981ad6265SDimitry Andric #include "llvm/Support/Error.h" 3081ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h" 3181ad6265SDimitry Andric #include "llvm/Support/ErrorOr.h" 3281ad6265SDimitry Andric #include "llvm/Support/FileSystem.h" 3381ad6265SDimitry Andric #include "llvm/Support/Memory.h" 3481ad6265SDimitry Andric #include "llvm/Support/Path.h" 3581ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 3681ad6265SDimitry Andric #include <algorithm> 3781ad6265SDimitry Andric #include <cassert> 3881ad6265SDimitry Andric #include <cstdlib> 3981ad6265SDimitry Andric #include <functional> 4081ad6265SDimitry Andric #include <iterator> 4181ad6265SDimitry Andric #include <memory> 4281ad6265SDimitry Andric #include <string> 4381ad6265SDimitry Andric #include <system_error> 4481ad6265SDimitry Andric #include <utility> 4581ad6265SDimitry Andric 4681ad6265SDimitry Andric using namespace llvm; 4781ad6265SDimitry Andric using namespace llvm::ELF; 4881ad6265SDimitry Andric using namespace llvm::objcopy; 4981ad6265SDimitry Andric using namespace llvm::objcopy::elf; 5081ad6265SDimitry Andric using namespace llvm::object; 5181ad6265SDimitry Andric 5281ad6265SDimitry Andric using SectionPred = std::function<bool(const SectionBase &Sec)>; 5381ad6265SDimitry Andric 5481ad6265SDimitry Andric static bool isDebugSection(const SectionBase &Sec) { 555f757f3fSDimitry Andric return StringRef(Sec.Name).starts_with(".debug") || Sec.Name == ".gdb_index"; 5681ad6265SDimitry Andric } 5781ad6265SDimitry Andric 5881ad6265SDimitry Andric static bool isDWOSection(const SectionBase &Sec) { 595f757f3fSDimitry Andric return StringRef(Sec.Name).ends_with(".dwo"); 6081ad6265SDimitry Andric } 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) { 6381ad6265SDimitry Andric // We can't remove the section header string table. 6481ad6265SDimitry Andric if (&Sec == Obj.SectionNames) 6581ad6265SDimitry Andric return false; 6681ad6265SDimitry Andric // Short of keeping the string table we want to keep everything that is a DWO 6781ad6265SDimitry Andric // section and remove everything else. 6881ad6265SDimitry Andric return !isDWOSection(Sec); 6981ad6265SDimitry Andric } 7081ad6265SDimitry Andric 715f757f3fSDimitry Andric static Expected<uint64_t> getNewShfFlags(SectionFlag AllFlags, 725f757f3fSDimitry 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; 865f757f3fSDimitry Andric if (AllFlags & SectionFlag::SecLarge) { 875f757f3fSDimitry Andric if (EMachine != EM_X86_64) 885f757f3fSDimitry Andric return createStringError(errc::invalid_argument, 895f757f3fSDimitry Andric "section flag SHF_X86_64_LARGE can only be used " 905f757f3fSDimitry Andric "with x86_64 architecture"); 915f757f3fSDimitry Andric NewFlags |= ELF::SHF_X86_64_LARGE; 925f757f3fSDimitry Andric } 9381ad6265SDimitry Andric return NewFlags; 9481ad6265SDimitry Andric } 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags, 975f757f3fSDimitry Andric uint64_t NewFlags, 985f757f3fSDimitry 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) & 1055f757f3fSDimitry Andric ~ELF::SHF_EXCLUDE & 1065f757f3fSDimitry Andric ~(EMachine == EM_X86_64 ? (uint64_t)ELF::SHF_X86_64_LARGE : 0UL); 10781ad6265SDimitry Andric return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask); 10881ad6265SDimitry Andric } 10981ad6265SDimitry Andric 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 1185f757f3fSDimitry Andric static Error setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags, 1195f757f3fSDimitry Andric uint16_t EMachine) { 1205f757f3fSDimitry Andric Expected<uint64_t> NewFlags = getNewShfFlags(Flags, EMachine); 1215f757f3fSDimitry Andric if (!NewFlags) 1225f757f3fSDimitry Andric return NewFlags.takeError(); 1235f757f3fSDimitry 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); 1325f757f3fSDimitry Andric 1335f757f3fSDimitry Andric return Error::success(); 13481ad6265SDimitry Andric } 13581ad6265SDimitry Andric 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 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 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 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: 1835f757f3fSDimitry Andric return std::make_unique<BinaryWriter>(Obj, Out, Config); 18481ad6265SDimitry Andric case FileFormat::IHex: 185*0fca6ea1SDimitry Andric return std::make_unique<IHexWriter>(Obj, Out, Config.OutputFilename); 186*0fca6ea1SDimitry Andric case FileFormat::SREC: 187*0fca6ea1SDimitry Andric return std::make_unique<SRECWriter>(Obj, Out, Config.OutputFilename); 18881ad6265SDimitry Andric default: 18981ad6265SDimitry Andric return createELFWriter(Config, Obj, Out, OutputElfType); 19081ad6265SDimitry Andric } 19181ad6265SDimitry Andric } 19281ad6265SDimitry Andric 19381ad6265SDimitry Andric static Error dumpSectionToFile(StringRef SecName, StringRef Filename, 19481ad6265SDimitry Andric Object &Obj) { 19581ad6265SDimitry Andric for (auto &Sec : Obj.sections()) { 19681ad6265SDimitry Andric if (Sec.Name == SecName) { 19781ad6265SDimitry Andric if (Sec.Type == SHT_NOBITS) 19881ad6265SDimitry Andric return createStringError(object_error::parse_failed, 19981ad6265SDimitry Andric "cannot dump section '%s': it has no contents", 20081ad6265SDimitry Andric SecName.str().c_str()); 20181ad6265SDimitry Andric Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = 20281ad6265SDimitry Andric FileOutputBuffer::create(Filename, Sec.OriginalData.size()); 20381ad6265SDimitry Andric if (!BufferOrErr) 20481ad6265SDimitry Andric return BufferOrErr.takeError(); 20581ad6265SDimitry Andric std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr); 20681ad6265SDimitry Andric std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), 20781ad6265SDimitry Andric Buf->getBufferStart()); 20881ad6265SDimitry Andric if (Error E = Buf->commit()) 20981ad6265SDimitry Andric return E; 21081ad6265SDimitry Andric return Error::success(); 21181ad6265SDimitry Andric } 21281ad6265SDimitry Andric } 21381ad6265SDimitry Andric return createStringError(object_error::parse_failed, "section '%s' not found", 21481ad6265SDimitry Andric SecName.str().c_str()); 21581ad6265SDimitry Andric } 21681ad6265SDimitry Andric 217*0fca6ea1SDimitry Andric Error Object::compressOrDecompressSections(const CommonConfig &Config) { 218*0fca6ea1SDimitry Andric // Build a list of sections we are going to replace. 219*0fca6ea1SDimitry Andric // We can't call `addSection` while iterating over sections, 22081ad6265SDimitry Andric // because it would mutate the sections array. 221*0fca6ea1SDimitry Andric SmallVector<std::pair<SectionBase *, std::function<SectionBase *()>>, 0> 222*0fca6ea1SDimitry Andric ToReplace; 223*0fca6ea1SDimitry Andric for (SectionBase &Sec : sections()) { 224*0fca6ea1SDimitry Andric std::optional<DebugCompressionType> CType; 225*0fca6ea1SDimitry Andric for (auto &[Matcher, T] : Config.compressSections) 226*0fca6ea1SDimitry Andric if (Matcher.matches(Sec.Name)) 227*0fca6ea1SDimitry Andric CType = T; 228*0fca6ea1SDimitry Andric // Handle --compress-debug-sections and --decompress-debug-sections, which 229*0fca6ea1SDimitry Andric // apply to non-ALLOC debug sections. 230*0fca6ea1SDimitry Andric if (!(Sec.Flags & SHF_ALLOC) && StringRef(Sec.Name).starts_with(".debug")) { 231*0fca6ea1SDimitry Andric if (Config.CompressionType != DebugCompressionType::None) 232*0fca6ea1SDimitry Andric CType = Config.CompressionType; 233*0fca6ea1SDimitry Andric else if (Config.DecompressDebugSections) 234*0fca6ea1SDimitry Andric CType = DebugCompressionType::None; 235*0fca6ea1SDimitry Andric } 236*0fca6ea1SDimitry Andric if (!CType) 237*0fca6ea1SDimitry Andric continue; 23881ad6265SDimitry Andric 239*0fca6ea1SDimitry Andric if (Sec.ParentSegment) 240*0fca6ea1SDimitry Andric return createStringError( 241*0fca6ea1SDimitry Andric errc::invalid_argument, 242*0fca6ea1SDimitry Andric "section '" + Sec.Name + 243*0fca6ea1SDimitry Andric "' within a segment cannot be (de)compressed"); 24481ad6265SDimitry Andric 245*0fca6ea1SDimitry Andric if (auto *CS = dyn_cast<CompressedSection>(&Sec)) { 246*0fca6ea1SDimitry Andric if (*CType == DebugCompressionType::None) 247*0fca6ea1SDimitry Andric ToReplace.emplace_back( 248*0fca6ea1SDimitry Andric &Sec, [=] { return &addSection<DecompressedSection>(*CS); }); 249*0fca6ea1SDimitry Andric } else if (*CType != DebugCompressionType::None) { 250*0fca6ea1SDimitry Andric ToReplace.emplace_back(&Sec, [=, S = &Sec] { 251*0fca6ea1SDimitry Andric return &addSection<CompressedSection>( 252*0fca6ea1SDimitry Andric CompressedSection(*S, *CType, Is64Bits)); 253*0fca6ea1SDimitry Andric }); 254*0fca6ea1SDimitry Andric } 25581ad6265SDimitry Andric } 25681ad6265SDimitry Andric 257*0fca6ea1SDimitry Andric DenseMap<SectionBase *, SectionBase *> FromTo; 258*0fca6ea1SDimitry Andric for (auto [S, Func] : ToReplace) 259*0fca6ea1SDimitry Andric FromTo[S] = Func(); 260*0fca6ea1SDimitry Andric return replaceSections(FromTo); 26181ad6265SDimitry Andric } 26281ad6265SDimitry Andric 26381ad6265SDimitry Andric static bool isAArch64MappingSymbol(const Symbol &Sym) { 26481ad6265SDimitry Andric if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE || 26581ad6265SDimitry Andric Sym.getShndx() == SHN_UNDEF) 26681ad6265SDimitry Andric return false; 26781ad6265SDimitry Andric StringRef Name = Sym.Name; 26881ad6265SDimitry Andric if (!Name.consume_front("$x") && !Name.consume_front("$d")) 26981ad6265SDimitry Andric return false; 2705f757f3fSDimitry Andric return Name.empty() || Name.starts_with("."); 27181ad6265SDimitry Andric } 27281ad6265SDimitry Andric 27381ad6265SDimitry Andric static bool isArmMappingSymbol(const Symbol &Sym) { 27481ad6265SDimitry Andric if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE || 27581ad6265SDimitry Andric Sym.getShndx() == SHN_UNDEF) 27681ad6265SDimitry Andric return false; 27781ad6265SDimitry Andric StringRef Name = Sym.Name; 27881ad6265SDimitry Andric if (!Name.consume_front("$a") && !Name.consume_front("$d") && 27981ad6265SDimitry Andric !Name.consume_front("$t")) 28081ad6265SDimitry Andric return false; 2815f757f3fSDimitry Andric return Name.empty() || Name.starts_with("."); 28281ad6265SDimitry Andric } 28381ad6265SDimitry Andric 28481ad6265SDimitry Andric // Check if the symbol should be preserved because it is required by ABI. 28581ad6265SDimitry Andric static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym) { 28681ad6265SDimitry Andric switch (Obj.Machine) { 28781ad6265SDimitry Andric case EM_AARCH64: 28881ad6265SDimitry Andric // Mapping symbols should be preserved for a relocatable object file. 28981ad6265SDimitry Andric return Obj.isRelocatable() && isAArch64MappingSymbol(Sym); 29081ad6265SDimitry Andric case EM_ARM: 29181ad6265SDimitry Andric // Mapping symbols should be preserved for a relocatable object file. 29281ad6265SDimitry Andric return Obj.isRelocatable() && isArmMappingSymbol(Sym); 29381ad6265SDimitry Andric default: 29481ad6265SDimitry Andric return false; 29581ad6265SDimitry Andric } 29681ad6265SDimitry Andric } 29781ad6265SDimitry Andric 29881ad6265SDimitry Andric static bool isUnneededSymbol(const Symbol &Sym) { 29981ad6265SDimitry Andric return !Sym.Referenced && 30081ad6265SDimitry Andric (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) && 30181ad6265SDimitry Andric Sym.Type != STT_SECTION; 30281ad6265SDimitry Andric } 30381ad6265SDimitry Andric 30481ad6265SDimitry Andric static Error updateAndRemoveSymbols(const CommonConfig &Config, 30581ad6265SDimitry Andric const ELFConfig &ELFConfig, Object &Obj) { 30681ad6265SDimitry Andric // TODO: update or remove symbols only if there is an option that affects 30781ad6265SDimitry Andric // them. 30881ad6265SDimitry Andric if (!Obj.SymbolTable) 30981ad6265SDimitry Andric return Error::success(); 31081ad6265SDimitry Andric 31181ad6265SDimitry Andric Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { 312*0fca6ea1SDimitry Andric if (Config.SymbolsToSkip.matches(Sym.Name)) 313*0fca6ea1SDimitry Andric return; 314*0fca6ea1SDimitry Andric 31581ad6265SDimitry Andric // Common and undefined symbols don't make sense as local symbols, and can 31681ad6265SDimitry Andric // even cause crashes if we localize those, so skip them. 31781ad6265SDimitry Andric if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF && 31881ad6265SDimitry Andric ((ELFConfig.LocalizeHidden && 31981ad6265SDimitry Andric (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || 32081ad6265SDimitry Andric Config.SymbolsToLocalize.matches(Sym.Name))) 32181ad6265SDimitry Andric Sym.Binding = STB_LOCAL; 32281ad6265SDimitry Andric 323*0fca6ea1SDimitry Andric for (auto &[Matcher, Visibility] : ELFConfig.SymbolsToSetVisibility) 324*0fca6ea1SDimitry Andric if (Matcher.matches(Sym.Name)) 325*0fca6ea1SDimitry Andric Sym.Visibility = Visibility; 326*0fca6ea1SDimitry Andric 32781ad6265SDimitry Andric // Note: these two globalize flags have very similar names but different 32881ad6265SDimitry Andric // meanings: 32981ad6265SDimitry Andric // 33081ad6265SDimitry Andric // --globalize-symbol: promote a symbol to global 33181ad6265SDimitry Andric // --keep-global-symbol: all symbols except for these should be made local 33281ad6265SDimitry Andric // 33381ad6265SDimitry Andric // If --globalize-symbol is specified for a given symbol, it will be 33481ad6265SDimitry Andric // global in the output file even if it is not included via 33581ad6265SDimitry Andric // --keep-global-symbol. Because of that, make sure to check 33681ad6265SDimitry Andric // --globalize-symbol second. 33781ad6265SDimitry Andric if (!Config.SymbolsToKeepGlobal.empty() && 33881ad6265SDimitry Andric !Config.SymbolsToKeepGlobal.matches(Sym.Name) && 33981ad6265SDimitry Andric Sym.getShndx() != SHN_UNDEF) 34081ad6265SDimitry Andric Sym.Binding = STB_LOCAL; 34181ad6265SDimitry Andric 34281ad6265SDimitry Andric if (Config.SymbolsToGlobalize.matches(Sym.Name) && 34381ad6265SDimitry Andric Sym.getShndx() != SHN_UNDEF) 34481ad6265SDimitry Andric Sym.Binding = STB_GLOBAL; 34581ad6265SDimitry Andric 34681ad6265SDimitry Andric // SymbolsToWeaken applies to both STB_GLOBAL and STB_GNU_UNIQUE. 34781ad6265SDimitry Andric if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding != STB_LOCAL) 34881ad6265SDimitry Andric Sym.Binding = STB_WEAK; 34981ad6265SDimitry Andric 35081ad6265SDimitry Andric if (Config.Weaken && Sym.Binding != STB_LOCAL && 35181ad6265SDimitry Andric Sym.getShndx() != SHN_UNDEF) 35281ad6265SDimitry Andric Sym.Binding = STB_WEAK; 35381ad6265SDimitry Andric 35481ad6265SDimitry Andric const auto I = Config.SymbolsToRename.find(Sym.Name); 35581ad6265SDimitry Andric if (I != Config.SymbolsToRename.end()) 35681ad6265SDimitry Andric Sym.Name = std::string(I->getValue()); 35781ad6265SDimitry Andric 358*0fca6ea1SDimitry Andric if (!Config.SymbolsPrefixRemove.empty() && Sym.Type != STT_SECTION) 359*0fca6ea1SDimitry Andric if (Sym.Name.compare(0, Config.SymbolsPrefixRemove.size(), 360*0fca6ea1SDimitry Andric Config.SymbolsPrefixRemove) == 0) 361*0fca6ea1SDimitry Andric Sym.Name = Sym.Name.substr(Config.SymbolsPrefixRemove.size()); 362*0fca6ea1SDimitry Andric 36381ad6265SDimitry Andric if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION) 36481ad6265SDimitry Andric Sym.Name = (Config.SymbolsPrefix + Sym.Name).str(); 36581ad6265SDimitry Andric }); 36681ad6265SDimitry Andric 36781ad6265SDimitry Andric // The purpose of this loop is to mark symbols referenced by sections 36881ad6265SDimitry Andric // (like GroupSection or RelocationSection). This way, we know which 36981ad6265SDimitry Andric // symbols are still 'needed' and which are not. 37081ad6265SDimitry Andric if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() || 37181ad6265SDimitry Andric !Config.OnlySection.empty()) { 37281ad6265SDimitry Andric for (SectionBase &Sec : Obj.sections()) 37381ad6265SDimitry Andric Sec.markSymbols(); 37481ad6265SDimitry Andric } 37581ad6265SDimitry Andric 37681ad6265SDimitry Andric auto RemoveSymbolsPred = [&](const Symbol &Sym) { 37781ad6265SDimitry Andric if (Config.SymbolsToKeep.matches(Sym.Name) || 37881ad6265SDimitry Andric (ELFConfig.KeepFileSymbols && Sym.Type == STT_FILE)) 37981ad6265SDimitry Andric return false; 38081ad6265SDimitry Andric 38181ad6265SDimitry Andric if (Config.SymbolsToRemove.matches(Sym.Name)) 38281ad6265SDimitry Andric return true; 38381ad6265SDimitry Andric 38481ad6265SDimitry Andric if (Config.StripAll || Config.StripAllGNU) 38581ad6265SDimitry Andric return true; 38681ad6265SDimitry Andric 38781ad6265SDimitry Andric if (isRequiredByABISymbol(Obj, Sym)) 38881ad6265SDimitry Andric return false; 38981ad6265SDimitry Andric 39081ad6265SDimitry Andric if (Config.StripDebug && Sym.Type == STT_FILE) 39181ad6265SDimitry Andric return true; 39281ad6265SDimitry Andric 39381ad6265SDimitry Andric if ((Config.DiscardMode == DiscardType::All || 39481ad6265SDimitry Andric (Config.DiscardMode == DiscardType::Locals && 3955f757f3fSDimitry Andric StringRef(Sym.Name).starts_with(".L"))) && 39681ad6265SDimitry Andric Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF && 39781ad6265SDimitry Andric Sym.Type != STT_FILE && Sym.Type != STT_SECTION) 39881ad6265SDimitry Andric return true; 39981ad6265SDimitry Andric 40081ad6265SDimitry Andric if ((Config.StripUnneeded || 40181ad6265SDimitry Andric Config.UnneededSymbolsToRemove.matches(Sym.Name)) && 40281ad6265SDimitry Andric (!Obj.isRelocatable() || isUnneededSymbol(Sym))) 40381ad6265SDimitry Andric return true; 40481ad6265SDimitry Andric 40581ad6265SDimitry Andric // We want to remove undefined symbols if all references have been stripped. 40681ad6265SDimitry Andric if (!Config.OnlySection.empty() && !Sym.Referenced && 40781ad6265SDimitry Andric Sym.getShndx() == SHN_UNDEF) 40881ad6265SDimitry Andric return true; 40981ad6265SDimitry Andric 41081ad6265SDimitry Andric return false; 41181ad6265SDimitry Andric }; 41281ad6265SDimitry Andric 41381ad6265SDimitry Andric return Obj.removeSymbols(RemoveSymbolsPred); 41481ad6265SDimitry Andric } 41581ad6265SDimitry Andric 41681ad6265SDimitry Andric static Error replaceAndRemoveSections(const CommonConfig &Config, 41781ad6265SDimitry Andric const ELFConfig &ELFConfig, Object &Obj) { 41881ad6265SDimitry Andric SectionPred RemovePred = [](const SectionBase &) { return false; }; 41981ad6265SDimitry Andric 42081ad6265SDimitry Andric // Removes: 42181ad6265SDimitry Andric if (!Config.ToRemove.empty()) { 42281ad6265SDimitry Andric RemovePred = [&Config](const SectionBase &Sec) { 42381ad6265SDimitry Andric return Config.ToRemove.matches(Sec.Name); 42481ad6265SDimitry Andric }; 42581ad6265SDimitry Andric } 42681ad6265SDimitry Andric 42781ad6265SDimitry Andric if (Config.StripDWO) 42881ad6265SDimitry Andric RemovePred = [RemovePred](const SectionBase &Sec) { 42981ad6265SDimitry Andric return isDWOSection(Sec) || RemovePred(Sec); 43081ad6265SDimitry Andric }; 43181ad6265SDimitry Andric 43281ad6265SDimitry Andric if (Config.ExtractDWO) 43381ad6265SDimitry Andric RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 43481ad6265SDimitry Andric return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec); 43581ad6265SDimitry Andric }; 43681ad6265SDimitry Andric 43781ad6265SDimitry Andric if (Config.StripAllGNU) 43881ad6265SDimitry Andric RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 43981ad6265SDimitry Andric if (RemovePred(Sec)) 44081ad6265SDimitry Andric return true; 44181ad6265SDimitry Andric if ((Sec.Flags & SHF_ALLOC) != 0) 44281ad6265SDimitry Andric return false; 44381ad6265SDimitry Andric if (&Sec == Obj.SectionNames) 44481ad6265SDimitry Andric return false; 44581ad6265SDimitry Andric switch (Sec.Type) { 44681ad6265SDimitry Andric case SHT_SYMTAB: 44781ad6265SDimitry Andric case SHT_REL: 44881ad6265SDimitry Andric case SHT_RELA: 44981ad6265SDimitry Andric case SHT_STRTAB: 45081ad6265SDimitry Andric return true; 45181ad6265SDimitry Andric } 45281ad6265SDimitry Andric return isDebugSection(Sec); 45381ad6265SDimitry Andric }; 45481ad6265SDimitry Andric 45581ad6265SDimitry Andric if (Config.StripSections) { 45681ad6265SDimitry Andric RemovePred = [RemovePred](const SectionBase &Sec) { 45781ad6265SDimitry Andric return RemovePred(Sec) || Sec.ParentSegment == nullptr; 45881ad6265SDimitry Andric }; 45981ad6265SDimitry Andric } 46081ad6265SDimitry Andric 46181ad6265SDimitry Andric if (Config.StripDebug || Config.StripUnneeded) { 46281ad6265SDimitry Andric RemovePred = [RemovePred](const SectionBase &Sec) { 46381ad6265SDimitry Andric return RemovePred(Sec) || isDebugSection(Sec); 46481ad6265SDimitry Andric }; 46581ad6265SDimitry Andric } 46681ad6265SDimitry Andric 46781ad6265SDimitry Andric if (Config.StripNonAlloc) 46881ad6265SDimitry Andric RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 46981ad6265SDimitry Andric if (RemovePred(Sec)) 47081ad6265SDimitry Andric return true; 47181ad6265SDimitry Andric if (&Sec == Obj.SectionNames) 47281ad6265SDimitry Andric return false; 47381ad6265SDimitry Andric return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr; 47481ad6265SDimitry Andric }; 47581ad6265SDimitry Andric 47681ad6265SDimitry Andric if (Config.StripAll) 47781ad6265SDimitry Andric RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 47881ad6265SDimitry Andric if (RemovePred(Sec)) 47981ad6265SDimitry Andric return true; 48081ad6265SDimitry Andric if (&Sec == Obj.SectionNames) 48181ad6265SDimitry Andric return false; 4825f757f3fSDimitry Andric if (StringRef(Sec.Name).starts_with(".gnu.warning")) 48381ad6265SDimitry Andric return false; 484*0fca6ea1SDimitry Andric if (StringRef(Sec.Name).starts_with(".gnu_debuglink")) 485*0fca6ea1SDimitry Andric return false; 48681ad6265SDimitry Andric // We keep the .ARM.attribute section to maintain compatibility 48781ad6265SDimitry Andric // with Debian derived distributions. This is a bug in their 48881ad6265SDimitry Andric // patchset as documented here: 48981ad6265SDimitry Andric // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798 49081ad6265SDimitry Andric if (Sec.Type == SHT_ARM_ATTRIBUTES) 49181ad6265SDimitry Andric return false; 49281ad6265SDimitry Andric if (Sec.ParentSegment != nullptr) 49381ad6265SDimitry Andric return false; 49481ad6265SDimitry Andric return (Sec.Flags & SHF_ALLOC) == 0; 49581ad6265SDimitry Andric }; 49681ad6265SDimitry Andric 49781ad6265SDimitry Andric if (Config.ExtractPartition || Config.ExtractMainPartition) { 49881ad6265SDimitry Andric RemovePred = [RemovePred](const SectionBase &Sec) { 49981ad6265SDimitry Andric if (RemovePred(Sec)) 50081ad6265SDimitry Andric return true; 50181ad6265SDimitry Andric if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR) 50281ad6265SDimitry Andric return true; 50381ad6265SDimitry Andric return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment; 50481ad6265SDimitry Andric }; 50581ad6265SDimitry Andric } 50681ad6265SDimitry Andric 50781ad6265SDimitry Andric // Explicit copies: 50881ad6265SDimitry Andric if (!Config.OnlySection.empty()) { 50981ad6265SDimitry Andric RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) { 51081ad6265SDimitry Andric // Explicitly keep these sections regardless of previous removes. 51181ad6265SDimitry Andric if (Config.OnlySection.matches(Sec.Name)) 51281ad6265SDimitry Andric return false; 51381ad6265SDimitry Andric 51481ad6265SDimitry Andric // Allow all implicit removes. 51581ad6265SDimitry Andric if (RemovePred(Sec)) 51681ad6265SDimitry Andric return true; 51781ad6265SDimitry Andric 51881ad6265SDimitry Andric // Keep special sections. 51981ad6265SDimitry Andric if (Obj.SectionNames == &Sec) 52081ad6265SDimitry Andric return false; 52181ad6265SDimitry Andric if (Obj.SymbolTable == &Sec || 52281ad6265SDimitry Andric (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec)) 52381ad6265SDimitry Andric return false; 52481ad6265SDimitry Andric 52581ad6265SDimitry Andric // Remove everything else. 52681ad6265SDimitry Andric return true; 52781ad6265SDimitry Andric }; 52881ad6265SDimitry Andric } 52981ad6265SDimitry Andric 53081ad6265SDimitry Andric if (!Config.KeepSection.empty()) { 53181ad6265SDimitry Andric RemovePred = [&Config, RemovePred](const SectionBase &Sec) { 53281ad6265SDimitry Andric // Explicitly keep these sections regardless of previous removes. 53381ad6265SDimitry Andric if (Config.KeepSection.matches(Sec.Name)) 53481ad6265SDimitry Andric return false; 53581ad6265SDimitry Andric // Otherwise defer to RemovePred. 53681ad6265SDimitry Andric return RemovePred(Sec); 53781ad6265SDimitry Andric }; 53881ad6265SDimitry Andric } 53981ad6265SDimitry Andric 54081ad6265SDimitry Andric // This has to be the last predicate assignment. 54181ad6265SDimitry Andric // If the option --keep-symbol has been specified 54281ad6265SDimitry Andric // and at least one of those symbols is present 54381ad6265SDimitry Andric // (equivalently, the updated symbol table is not empty) 54481ad6265SDimitry Andric // the symbol table and the string table should not be removed. 54581ad6265SDimitry Andric if ((!Config.SymbolsToKeep.empty() || ELFConfig.KeepFileSymbols) && 54681ad6265SDimitry Andric Obj.SymbolTable && !Obj.SymbolTable->empty()) { 54781ad6265SDimitry Andric RemovePred = [&Obj, RemovePred](const SectionBase &Sec) { 54881ad6265SDimitry Andric if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab()) 54981ad6265SDimitry Andric return false; 55081ad6265SDimitry Andric return RemovePred(Sec); 55181ad6265SDimitry Andric }; 55281ad6265SDimitry Andric } 55381ad6265SDimitry Andric 55481ad6265SDimitry Andric if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred)) 55581ad6265SDimitry Andric return E; 55681ad6265SDimitry Andric 557*0fca6ea1SDimitry Andric if (Error E = Obj.compressOrDecompressSections(Config)) 558*0fca6ea1SDimitry Andric return E; 55981ad6265SDimitry Andric 56081ad6265SDimitry Andric return Error::success(); 56181ad6265SDimitry Andric } 56281ad6265SDimitry Andric 56381ad6265SDimitry Andric // Add symbol to the Object symbol table with the specified properties. 56481ad6265SDimitry Andric static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo, 56581ad6265SDimitry Andric uint8_t DefaultVisibility) { 56681ad6265SDimitry Andric SectionBase *Sec = Obj.findSection(SymInfo.SectionName); 56781ad6265SDimitry Andric uint64_t Value = Sec ? Sec->Addr + SymInfo.Value : SymInfo.Value; 56881ad6265SDimitry Andric 56981ad6265SDimitry Andric uint8_t Bind = ELF::STB_GLOBAL; 57081ad6265SDimitry Andric uint8_t Type = ELF::STT_NOTYPE; 57181ad6265SDimitry Andric uint8_t Visibility = DefaultVisibility; 57281ad6265SDimitry Andric 57381ad6265SDimitry Andric for (SymbolFlag FlagValue : SymInfo.Flags) 57481ad6265SDimitry Andric switch (FlagValue) { 57581ad6265SDimitry Andric case SymbolFlag::Global: 57681ad6265SDimitry Andric Bind = ELF::STB_GLOBAL; 57781ad6265SDimitry Andric break; 57881ad6265SDimitry Andric case SymbolFlag::Local: 57981ad6265SDimitry Andric Bind = ELF::STB_LOCAL; 58081ad6265SDimitry Andric break; 58181ad6265SDimitry Andric case SymbolFlag::Weak: 58281ad6265SDimitry Andric Bind = ELF::STB_WEAK; 58381ad6265SDimitry Andric break; 58481ad6265SDimitry Andric case SymbolFlag::Default: 58581ad6265SDimitry Andric Visibility = ELF::STV_DEFAULT; 58681ad6265SDimitry Andric break; 58781ad6265SDimitry Andric case SymbolFlag::Hidden: 58881ad6265SDimitry Andric Visibility = ELF::STV_HIDDEN; 58981ad6265SDimitry Andric break; 59081ad6265SDimitry Andric case SymbolFlag::Protected: 59181ad6265SDimitry Andric Visibility = ELF::STV_PROTECTED; 59281ad6265SDimitry Andric break; 59381ad6265SDimitry Andric case SymbolFlag::File: 59481ad6265SDimitry Andric Type = ELF::STT_FILE; 59581ad6265SDimitry Andric break; 59681ad6265SDimitry Andric case SymbolFlag::Section: 59781ad6265SDimitry Andric Type = ELF::STT_SECTION; 59881ad6265SDimitry Andric break; 59981ad6265SDimitry Andric case SymbolFlag::Object: 60081ad6265SDimitry Andric Type = ELF::STT_OBJECT; 60181ad6265SDimitry Andric break; 60281ad6265SDimitry Andric case SymbolFlag::Function: 60381ad6265SDimitry Andric Type = ELF::STT_FUNC; 60481ad6265SDimitry Andric break; 60581ad6265SDimitry Andric case SymbolFlag::IndirectFunction: 60681ad6265SDimitry Andric Type = ELF::STT_GNU_IFUNC; 60781ad6265SDimitry Andric break; 60881ad6265SDimitry Andric default: /* Other flag values are ignored for ELF. */ 60981ad6265SDimitry Andric break; 61081ad6265SDimitry Andric }; 61181ad6265SDimitry Andric 61281ad6265SDimitry Andric Obj.SymbolTable->addSymbol( 61381ad6265SDimitry Andric SymInfo.SymbolName, Bind, Type, Sec, Value, Visibility, 61481ad6265SDimitry Andric Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0); 61581ad6265SDimitry Andric } 61681ad6265SDimitry Andric 61781ad6265SDimitry Andric static Error 61881ad6265SDimitry Andric handleUserSection(const NewSectionInfo &NewSection, 61981ad6265SDimitry Andric function_ref<Error(StringRef, ArrayRef<uint8_t>)> F) { 62081ad6265SDimitry Andric ArrayRef<uint8_t> Data(reinterpret_cast<const uint8_t *>( 62181ad6265SDimitry Andric NewSection.SectionData->getBufferStart()), 62281ad6265SDimitry Andric NewSection.SectionData->getBufferSize()); 62381ad6265SDimitry Andric return F(NewSection.SectionName, Data); 62481ad6265SDimitry Andric } 62581ad6265SDimitry Andric 626*0fca6ea1SDimitry Andric static Error verifyNoteSection(StringRef Name, endianness Endianness, 627*0fca6ea1SDimitry Andric ArrayRef<uint8_t> Data) { 628*0fca6ea1SDimitry Andric // An ELF note has the following structure: 629*0fca6ea1SDimitry Andric // Name Size: 4 bytes (integer) 630*0fca6ea1SDimitry Andric // Desc Size: 4 bytes (integer) 631*0fca6ea1SDimitry Andric // Type : 4 bytes 632*0fca6ea1SDimitry Andric // Name : variable size, padded to a 4 byte boundary 633*0fca6ea1SDimitry Andric // Desc : variable size, padded to a 4 byte boundary 634*0fca6ea1SDimitry Andric 635*0fca6ea1SDimitry Andric if (Data.empty()) 636*0fca6ea1SDimitry Andric return Error::success(); 637*0fca6ea1SDimitry Andric 638*0fca6ea1SDimitry Andric if (Data.size() < 12) { 639*0fca6ea1SDimitry Andric std::string msg; 640*0fca6ea1SDimitry Andric raw_string_ostream(msg) 641*0fca6ea1SDimitry Andric << Name << " data must be either empty or at least 12 bytes long"; 642*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, msg); 643*0fca6ea1SDimitry Andric } 644*0fca6ea1SDimitry Andric if (Data.size() % 4 != 0) { 645*0fca6ea1SDimitry Andric std::string msg; 646*0fca6ea1SDimitry Andric raw_string_ostream(msg) 647*0fca6ea1SDimitry Andric << Name << " data size must be a multiple of 4 bytes"; 648*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, msg); 649*0fca6ea1SDimitry Andric } 650*0fca6ea1SDimitry Andric ArrayRef<uint8_t> NameSize = Data.slice(0, 4); 651*0fca6ea1SDimitry Andric ArrayRef<uint8_t> DescSize = Data.slice(4, 4); 652*0fca6ea1SDimitry Andric 653*0fca6ea1SDimitry Andric uint32_t NameSizeValue = support::endian::read32(NameSize.data(), Endianness); 654*0fca6ea1SDimitry Andric uint32_t DescSizeValue = support::endian::read32(DescSize.data(), Endianness); 655*0fca6ea1SDimitry Andric 656*0fca6ea1SDimitry Andric uint64_t ExpectedDataSize = 657*0fca6ea1SDimitry Andric /*NameSize=*/4 + /*DescSize=*/4 + /*Type=*/4 + 658*0fca6ea1SDimitry Andric /*Name=*/alignTo(NameSizeValue, 4) + 659*0fca6ea1SDimitry Andric /*Desc=*/alignTo(DescSizeValue, 4); 660*0fca6ea1SDimitry Andric uint64_t ActualDataSize = Data.size(); 661*0fca6ea1SDimitry Andric if (ActualDataSize != ExpectedDataSize) { 662*0fca6ea1SDimitry Andric std::string msg; 663*0fca6ea1SDimitry Andric raw_string_ostream(msg) 664*0fca6ea1SDimitry Andric << Name 665*0fca6ea1SDimitry Andric << " data size is incompatible with the content of " 666*0fca6ea1SDimitry Andric "the name and description size fields:" 667*0fca6ea1SDimitry Andric << " expecting " << ExpectedDataSize << ", found " << ActualDataSize; 668*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, msg); 669*0fca6ea1SDimitry Andric } 670*0fca6ea1SDimitry Andric 671*0fca6ea1SDimitry Andric return Error::success(); 672*0fca6ea1SDimitry Andric } 673*0fca6ea1SDimitry Andric 67481ad6265SDimitry Andric // This function handles the high level operations of GNU objcopy including 67581ad6265SDimitry Andric // handling command line options. It's important to outline certain properties 67681ad6265SDimitry Andric // we expect to hold of the command line operations. Any operation that "keeps" 67781ad6265SDimitry Andric // should keep regardless of a remove. Additionally any removal should respect 67881ad6265SDimitry Andric // any previous removals. Lastly whether or not something is removed shouldn't 67981ad6265SDimitry Andric // depend a) on the order the options occur in or b) on some opaque priority 68081ad6265SDimitry Andric // system. The only priority is that keeps/copies overrule removes. 68181ad6265SDimitry Andric static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig, 682*0fca6ea1SDimitry Andric ElfType OutputElfType, Object &Obj) { 68381ad6265SDimitry Andric if (Config.OutputArch) { 684bdd1243dSDimitry Andric Obj.Machine = Config.OutputArch->EMachine; 685bdd1243dSDimitry Andric Obj.OSABI = Config.OutputArch->OSABI; 68681ad6265SDimitry Andric } 68781ad6265SDimitry Andric 68881ad6265SDimitry Andric if (!Config.SplitDWO.empty() && Config.ExtractDWO) { 68981ad6265SDimitry Andric return Obj.removeSections( 69081ad6265SDimitry Andric ELFConfig.AllowBrokenLinks, 69181ad6265SDimitry Andric [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); }); 69281ad6265SDimitry Andric } 69381ad6265SDimitry Andric 69481ad6265SDimitry Andric // Dump sections before add/remove for compatibility with GNU objcopy. 69581ad6265SDimitry Andric for (StringRef Flag : Config.DumpSection) { 69681ad6265SDimitry Andric StringRef SectionName; 69781ad6265SDimitry Andric StringRef FileName; 69881ad6265SDimitry Andric std::tie(SectionName, FileName) = Flag.split('='); 69981ad6265SDimitry Andric if (Error E = dumpSectionToFile(SectionName, FileName, Obj)) 70081ad6265SDimitry Andric return E; 70181ad6265SDimitry Andric } 70281ad6265SDimitry Andric 70381ad6265SDimitry Andric // It is important to remove the sections first. For example, we want to 70481ad6265SDimitry Andric // remove the relocation sections before removing the symbols. That allows 70581ad6265SDimitry Andric // us to avoid reporting the inappropriate errors about removing symbols 70681ad6265SDimitry Andric // named in relocations. 70781ad6265SDimitry Andric if (Error E = replaceAndRemoveSections(Config, ELFConfig, Obj)) 70881ad6265SDimitry Andric return E; 70981ad6265SDimitry Andric 71081ad6265SDimitry Andric if (Error E = updateAndRemoveSymbols(Config, ELFConfig, Obj)) 71181ad6265SDimitry Andric return E; 71281ad6265SDimitry Andric 713753f127fSDimitry Andric if (!Config.SetSectionAlignment.empty()) { 714753f127fSDimitry Andric for (SectionBase &Sec : Obj.sections()) { 715753f127fSDimitry Andric auto I = Config.SetSectionAlignment.find(Sec.Name); 716753f127fSDimitry Andric if (I != Config.SetSectionAlignment.end()) 717753f127fSDimitry Andric Sec.Align = I->second; 718753f127fSDimitry Andric } 719753f127fSDimitry Andric } 720753f127fSDimitry Andric 721*0fca6ea1SDimitry Andric if (Config.ChangeSectionLMAValAll != 0) { 722*0fca6ea1SDimitry Andric for (Segment &Seg : Obj.segments()) { 723*0fca6ea1SDimitry Andric if (Seg.FileSize > 0) { 724*0fca6ea1SDimitry Andric if (Config.ChangeSectionLMAValAll > 0 && 725*0fca6ea1SDimitry Andric Seg.PAddr > std::numeric_limits<uint64_t>::max() - 726*0fca6ea1SDimitry Andric Config.ChangeSectionLMAValAll) { 727*0fca6ea1SDimitry Andric return createStringError( 728*0fca6ea1SDimitry Andric errc::invalid_argument, 729*0fca6ea1SDimitry Andric "address 0x" + Twine::utohexstr(Seg.PAddr) + 730*0fca6ea1SDimitry Andric " cannot be increased by 0x" + 731*0fca6ea1SDimitry Andric Twine::utohexstr(Config.ChangeSectionLMAValAll) + 732*0fca6ea1SDimitry Andric ". The result would overflow"); 733*0fca6ea1SDimitry Andric } else if (Config.ChangeSectionLMAValAll < 0 && 734*0fca6ea1SDimitry Andric Seg.PAddr < std::numeric_limits<uint64_t>::min() - 735*0fca6ea1SDimitry Andric Config.ChangeSectionLMAValAll) { 736*0fca6ea1SDimitry Andric return createStringError( 737*0fca6ea1SDimitry Andric errc::invalid_argument, 738*0fca6ea1SDimitry Andric "address 0x" + Twine::utohexstr(Seg.PAddr) + 739*0fca6ea1SDimitry Andric " cannot be decreased by 0x" + 740*0fca6ea1SDimitry Andric Twine::utohexstr(std::abs(Config.ChangeSectionLMAValAll)) + 741*0fca6ea1SDimitry Andric ". The result would underflow"); 742*0fca6ea1SDimitry Andric } 743*0fca6ea1SDimitry Andric Seg.PAddr += Config.ChangeSectionLMAValAll; 744*0fca6ea1SDimitry Andric } 745*0fca6ea1SDimitry Andric } 746*0fca6ea1SDimitry Andric } 747*0fca6ea1SDimitry Andric 748753f127fSDimitry Andric if (Config.OnlyKeepDebug) 749753f127fSDimitry Andric for (auto &Sec : Obj.sections()) 750753f127fSDimitry Andric if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE) 751753f127fSDimitry Andric Sec.Type = SHT_NOBITS; 752753f127fSDimitry Andric 753*0fca6ea1SDimitry Andric endianness E = OutputElfType == ELFT_ELF32LE || OutputElfType == ELFT_ELF64LE 754*0fca6ea1SDimitry Andric ? endianness::little 755*0fca6ea1SDimitry Andric : endianness::big; 756*0fca6ea1SDimitry Andric 757753f127fSDimitry Andric for (const NewSectionInfo &AddedSection : Config.AddSection) { 758*0fca6ea1SDimitry Andric auto AddSection = [&](StringRef Name, ArrayRef<uint8_t> Data) -> Error { 759753f127fSDimitry Andric OwnedDataSection &NewSection = 760753f127fSDimitry Andric Obj.addSection<OwnedDataSection>(Name, Data); 761*0fca6ea1SDimitry Andric if (Name.starts_with(".note") && Name != ".note.GNU-stack") { 762753f127fSDimitry Andric NewSection.Type = SHT_NOTE; 763*0fca6ea1SDimitry Andric if (ELFConfig.VerifyNoteSections) 764*0fca6ea1SDimitry Andric return verifyNoteSection(Name, E, Data); 765*0fca6ea1SDimitry Andric } 766753f127fSDimitry Andric return Error::success(); 767753f127fSDimitry Andric }; 768753f127fSDimitry Andric if (Error E = handleUserSection(AddedSection, AddSection)) 769753f127fSDimitry Andric return E; 770753f127fSDimitry Andric } 771753f127fSDimitry Andric 772753f127fSDimitry Andric for (const NewSectionInfo &NewSection : Config.UpdateSection) { 773753f127fSDimitry Andric auto UpdateSection = [&](StringRef Name, ArrayRef<uint8_t> Data) { 774753f127fSDimitry Andric return Obj.updateSection(Name, Data); 775753f127fSDimitry Andric }; 776753f127fSDimitry Andric if (Error E = handleUserSection(NewSection, UpdateSection)) 777753f127fSDimitry Andric return E; 778753f127fSDimitry Andric } 779753f127fSDimitry Andric 780753f127fSDimitry Andric if (!Config.AddGnuDebugLink.empty()) 781753f127fSDimitry Andric Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink, 782753f127fSDimitry Andric Config.GnuDebugLinkCRC32); 783753f127fSDimitry Andric 784753f127fSDimitry Andric // If the symbol table was previously removed, we need to create a new one 785753f127fSDimitry Andric // before adding new symbols. 786753f127fSDimitry Andric if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty()) 787753f127fSDimitry Andric if (Error E = Obj.addNewSymbolTable()) 788753f127fSDimitry Andric return E; 789753f127fSDimitry Andric 790753f127fSDimitry Andric for (const NewSymbolInfo &SI : Config.SymbolsToAdd) 791753f127fSDimitry Andric addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility); 792753f127fSDimitry Andric 793753f127fSDimitry Andric // --set-section-{flags,type} work with sections added by --add-section. 794753f127fSDimitry Andric if (!Config.SetSectionFlags.empty() || !Config.SetSectionType.empty()) { 795753f127fSDimitry Andric for (auto &Sec : Obj.sections()) { 796753f127fSDimitry Andric const auto Iter = Config.SetSectionFlags.find(Sec.Name); 797753f127fSDimitry Andric if (Iter != Config.SetSectionFlags.end()) { 798753f127fSDimitry Andric const SectionFlagsUpdate &SFU = Iter->second; 7995f757f3fSDimitry Andric if (Error E = setSectionFlagsAndType(Sec, SFU.NewFlags, Obj.Machine)) 8005f757f3fSDimitry Andric return E; 801753f127fSDimitry Andric } 802753f127fSDimitry Andric auto It2 = Config.SetSectionType.find(Sec.Name); 803753f127fSDimitry Andric if (It2 != Config.SetSectionType.end()) 80406c3fb27SDimitry Andric setSectionType(Sec, It2->second); 805753f127fSDimitry Andric } 806753f127fSDimitry Andric } 807753f127fSDimitry Andric 80881ad6265SDimitry Andric if (!Config.SectionsToRename.empty()) { 80981ad6265SDimitry Andric std::vector<RelocationSectionBase *> RelocSections; 81081ad6265SDimitry Andric DenseSet<SectionBase *> RenamedSections; 81181ad6265SDimitry Andric for (SectionBase &Sec : Obj.sections()) { 81281ad6265SDimitry Andric auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec); 81381ad6265SDimitry Andric const auto Iter = Config.SectionsToRename.find(Sec.Name); 81481ad6265SDimitry Andric if (Iter != Config.SectionsToRename.end()) { 81581ad6265SDimitry Andric const SectionRename &SR = Iter->second; 81681ad6265SDimitry Andric Sec.Name = std::string(SR.NewName); 8175f757f3fSDimitry Andric if (SR.NewFlags) { 8185f757f3fSDimitry Andric if (Error E = setSectionFlagsAndType(Sec, *SR.NewFlags, Obj.Machine)) 8195f757f3fSDimitry Andric return E; 8205f757f3fSDimitry Andric } 82181ad6265SDimitry Andric RenamedSections.insert(&Sec); 82281ad6265SDimitry Andric } else if (RelocSec && !(Sec.Flags & SHF_ALLOC)) 82381ad6265SDimitry Andric // Postpone processing relocation sections which are not specified in 82481ad6265SDimitry Andric // their explicit '--rename-section' commands until after their target 82581ad6265SDimitry Andric // sections are renamed. 82681ad6265SDimitry Andric // Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be 82781ad6265SDimitry Andric // renamed only explicitly. Otherwise, renaming, for example, '.got.plt' 82881ad6265SDimitry Andric // would affect '.rela.plt', which is not desirable. 82981ad6265SDimitry Andric RelocSections.push_back(RelocSec); 83081ad6265SDimitry Andric } 83181ad6265SDimitry Andric 83281ad6265SDimitry Andric // Rename relocation sections according to their target sections. 83381ad6265SDimitry Andric for (RelocationSectionBase *RelocSec : RelocSections) { 83481ad6265SDimitry Andric auto Iter = RenamedSections.find(RelocSec->getSection()); 83581ad6265SDimitry Andric if (Iter != RenamedSections.end()) 83681ad6265SDimitry Andric RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str(); 83781ad6265SDimitry Andric } 83881ad6265SDimitry Andric } 83981ad6265SDimitry Andric 84081ad6265SDimitry Andric // Add a prefix to allocated sections and their relocation sections. This 84181ad6265SDimitry Andric // should be done after renaming the section by Config.SectionToRename to 84281ad6265SDimitry Andric // imitate the GNU objcopy behavior. 84381ad6265SDimitry Andric if (!Config.AllocSectionsPrefix.empty()) { 84481ad6265SDimitry Andric DenseSet<SectionBase *> PrefixedSections; 84581ad6265SDimitry Andric for (SectionBase &Sec : Obj.sections()) { 84681ad6265SDimitry Andric if (Sec.Flags & SHF_ALLOC) { 84781ad6265SDimitry Andric Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str(); 84881ad6265SDimitry Andric PrefixedSections.insert(&Sec); 84981ad6265SDimitry Andric } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) { 85081ad6265SDimitry Andric // Rename relocation sections associated to the allocated sections. 85181ad6265SDimitry Andric // For example, if we rename .text to .prefix.text, we also rename 85281ad6265SDimitry Andric // .rel.text to .rel.prefix.text. 85381ad6265SDimitry Andric // 85481ad6265SDimitry Andric // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled 85581ad6265SDimitry Andric // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not 85681ad6265SDimitry Andric // .rela.prefix.plt since GNU objcopy does so. 85781ad6265SDimitry Andric const SectionBase *TargetSec = RelocSec->getSection(); 85881ad6265SDimitry Andric if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) { 85981ad6265SDimitry Andric // If the relocation section comes *after* the target section, we 86081ad6265SDimitry Andric // don't add Config.AllocSectionsPrefix because we've already added 86181ad6265SDimitry Andric // the prefix to TargetSec->Name. Otherwise, if the relocation 86281ad6265SDimitry Andric // section comes *before* the target section, we add the prefix. 86381ad6265SDimitry Andric if (PrefixedSections.count(TargetSec)) 86481ad6265SDimitry Andric Sec.Name = (RelocSec->getNamePrefix() + TargetSec->Name).str(); 86581ad6265SDimitry Andric else 86681ad6265SDimitry Andric Sec.Name = (RelocSec->getNamePrefix() + Config.AllocSectionsPrefix + 86781ad6265SDimitry Andric TargetSec->Name) 86881ad6265SDimitry Andric .str(); 86981ad6265SDimitry Andric } 87081ad6265SDimitry Andric } 87181ad6265SDimitry Andric } 87281ad6265SDimitry Andric } 87381ad6265SDimitry Andric 87481ad6265SDimitry Andric if (ELFConfig.EntryExpr) 87581ad6265SDimitry Andric Obj.Entry = ELFConfig.EntryExpr(Obj.Entry); 87681ad6265SDimitry Andric return Error::success(); 87781ad6265SDimitry Andric } 87881ad6265SDimitry Andric 87981ad6265SDimitry Andric static Error writeOutput(const CommonConfig &Config, Object &Obj, 88081ad6265SDimitry Andric raw_ostream &Out, ElfType OutputElfType) { 88181ad6265SDimitry Andric std::unique_ptr<Writer> Writer = 88281ad6265SDimitry Andric createWriter(Config, Obj, Out, OutputElfType); 88381ad6265SDimitry Andric if (Error E = Writer->finalize()) 88481ad6265SDimitry Andric return E; 88581ad6265SDimitry Andric return Writer->write(); 88681ad6265SDimitry Andric } 88781ad6265SDimitry Andric 88881ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config, 88981ad6265SDimitry Andric const ELFConfig &ELFConfig, 89081ad6265SDimitry Andric MemoryBuffer &In, raw_ostream &Out) { 89181ad6265SDimitry Andric IHexReader Reader(&In); 89281ad6265SDimitry Andric Expected<std::unique_ptr<Object>> Obj = Reader.create(true); 89381ad6265SDimitry Andric if (!Obj) 89481ad6265SDimitry Andric return Obj.takeError(); 89581ad6265SDimitry Andric 89681ad6265SDimitry Andric const ElfType OutputElfType = 89781ad6265SDimitry Andric getOutputElfType(Config.OutputArch.value_or(MachineInfo())); 898*0fca6ea1SDimitry Andric if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj)) 89981ad6265SDimitry Andric return E; 90081ad6265SDimitry Andric return writeOutput(Config, **Obj, Out, OutputElfType); 90181ad6265SDimitry Andric } 90281ad6265SDimitry Andric 90381ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config, 90481ad6265SDimitry Andric const ELFConfig &ELFConfig, 90581ad6265SDimitry Andric MemoryBuffer &In, 90681ad6265SDimitry Andric raw_ostream &Out) { 90781ad6265SDimitry Andric BinaryReader Reader(&In, ELFConfig.NewSymbolVisibility); 90881ad6265SDimitry Andric Expected<std::unique_ptr<Object>> Obj = Reader.create(true); 90981ad6265SDimitry Andric if (!Obj) 91081ad6265SDimitry Andric return Obj.takeError(); 91181ad6265SDimitry Andric 91281ad6265SDimitry Andric // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch 91381ad6265SDimitry Andric // (-B<arch>). 91481ad6265SDimitry Andric const ElfType OutputElfType = 91581ad6265SDimitry Andric getOutputElfType(Config.OutputArch.value_or(MachineInfo())); 916*0fca6ea1SDimitry Andric if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj)) 91781ad6265SDimitry Andric return E; 91881ad6265SDimitry Andric return writeOutput(Config, **Obj, Out, OutputElfType); 91981ad6265SDimitry Andric } 92081ad6265SDimitry Andric 92181ad6265SDimitry Andric Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config, 92281ad6265SDimitry Andric const ELFConfig &ELFConfig, 92381ad6265SDimitry Andric object::ELFObjectFileBase &In, 92481ad6265SDimitry Andric raw_ostream &Out) { 92581ad6265SDimitry Andric ELFReader Reader(&In, Config.ExtractPartition); 92681ad6265SDimitry Andric Expected<std::unique_ptr<Object>> Obj = 92781ad6265SDimitry Andric Reader.create(!Config.SymbolsToAdd.empty()); 92881ad6265SDimitry Andric if (!Obj) 92981ad6265SDimitry Andric return Obj.takeError(); 93081ad6265SDimitry Andric // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input. 931bdd1243dSDimitry Andric const ElfType OutputElfType = Config.OutputArch 932bdd1243dSDimitry Andric ? getOutputElfType(*Config.OutputArch) 93381ad6265SDimitry Andric : getOutputElfType(In); 93481ad6265SDimitry Andric 935*0fca6ea1SDimitry Andric if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj)) 93681ad6265SDimitry Andric return createFileError(Config.InputFilename, std::move(E)); 93781ad6265SDimitry Andric 93881ad6265SDimitry Andric if (Error E = writeOutput(Config, **Obj, Out, OutputElfType)) 93981ad6265SDimitry Andric return createFileError(Config.InputFilename, std::move(E)); 94081ad6265SDimitry Andric 94181ad6265SDimitry Andric return Error::success(); 94281ad6265SDimitry Andric } 943