1f75da0c8SAlexey Lapshin //===- ELFObjcopy.cpp -----------------------------------------------------===// 2f75da0c8SAlexey Lapshin // 3f75da0c8SAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f75da0c8SAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information. 5f75da0c8SAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f75da0c8SAlexey Lapshin // 7f75da0c8SAlexey Lapshin //===----------------------------------------------------------------------===// 8f75da0c8SAlexey Lapshin 9f75da0c8SAlexey Lapshin #include "llvm/ObjCopy/ELF/ELFObjcopy.h" 1025d7b4fbSAlexey Lapshin #include "ELFObject.h" 11f75da0c8SAlexey Lapshin #include "llvm/ADT/BitmaskEnum.h" 12f75da0c8SAlexey Lapshin #include "llvm/ADT/DenseSet.h" 13f75da0c8SAlexey Lapshin #include "llvm/ADT/SmallVector.h" 14f75da0c8SAlexey Lapshin #include "llvm/ADT/StringRef.h" 15f75da0c8SAlexey Lapshin #include "llvm/ADT/Twine.h" 16f75da0c8SAlexey Lapshin #include "llvm/BinaryFormat/ELF.h" 17f75da0c8SAlexey Lapshin #include "llvm/MC/MCTargetOptions.h" 18f75da0c8SAlexey Lapshin #include "llvm/ObjCopy/CommonConfig.h" 19f75da0c8SAlexey Lapshin #include "llvm/ObjCopy/ELF/ELFConfig.h" 20f75da0c8SAlexey Lapshin #include "llvm/Object/Binary.h" 21f75da0c8SAlexey Lapshin #include "llvm/Object/ELFObjectFile.h" 22f75da0c8SAlexey Lapshin #include "llvm/Object/ELFTypes.h" 23f75da0c8SAlexey Lapshin #include "llvm/Object/Error.h" 24f75da0c8SAlexey Lapshin #include "llvm/Option/Option.h" 25f75da0c8SAlexey Lapshin #include "llvm/Support/Casting.h" 26f75da0c8SAlexey Lapshin #include "llvm/Support/Compression.h" 27f75da0c8SAlexey Lapshin #include "llvm/Support/Errc.h" 28f75da0c8SAlexey Lapshin #include "llvm/Support/Error.h" 29f75da0c8SAlexey Lapshin #include "llvm/Support/ErrorHandling.h" 30f75da0c8SAlexey Lapshin #include "llvm/Support/Memory.h" 31f75da0c8SAlexey Lapshin #include "llvm/Support/raw_ostream.h" 32f75da0c8SAlexey Lapshin #include <algorithm> 33f75da0c8SAlexey Lapshin #include <cassert> 34f75da0c8SAlexey Lapshin #include <cstdlib> 35f75da0c8SAlexey Lapshin #include <functional> 36f75da0c8SAlexey Lapshin #include <memory> 37f75da0c8SAlexey Lapshin #include <string> 38f75da0c8SAlexey Lapshin #include <system_error> 39f75da0c8SAlexey Lapshin #include <utility> 40f75da0c8SAlexey Lapshin 41f75da0c8SAlexey Lapshin using namespace llvm; 42f75da0c8SAlexey Lapshin using namespace llvm::ELF; 43f75da0c8SAlexey Lapshin using namespace llvm::objcopy; 44f75da0c8SAlexey Lapshin using namespace llvm::objcopy::elf; 45f75da0c8SAlexey Lapshin using namespace llvm::object; 46f75da0c8SAlexey Lapshin 47f75da0c8SAlexey Lapshin using SectionPred = std::function<bool(const SectionBase &Sec)>; 48f75da0c8SAlexey Lapshin 49f75da0c8SAlexey Lapshin static bool isDebugSection(const SectionBase &Sec) { 50586ecdf2SKazu Hirata return StringRef(Sec.Name).starts_with(".debug") || Sec.Name == ".gdb_index"; 51f75da0c8SAlexey Lapshin } 52f75da0c8SAlexey Lapshin 53f75da0c8SAlexey Lapshin static bool isDWOSection(const SectionBase &Sec) { 54586ecdf2SKazu Hirata return StringRef(Sec.Name).ends_with(".dwo"); 55f75da0c8SAlexey Lapshin } 56f75da0c8SAlexey Lapshin 57f75da0c8SAlexey Lapshin static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) { 58f75da0c8SAlexey Lapshin // We can't remove the section header string table. 59f75da0c8SAlexey Lapshin if (&Sec == Obj.SectionNames) 60f75da0c8SAlexey Lapshin return false; 61f75da0c8SAlexey Lapshin // Short of keeping the string table we want to keep everything that is a DWO 62f75da0c8SAlexey Lapshin // section and remove everything else. 63f75da0c8SAlexey Lapshin return !isDWOSection(Sec); 64f75da0c8SAlexey Lapshin } 65f75da0c8SAlexey Lapshin 666f1395a1SThomas Köppe static Expected<uint64_t> getNewShfFlags(SectionFlag AllFlags, 676f1395a1SThomas Köppe uint16_t EMachine) { 68f75da0c8SAlexey Lapshin uint64_t NewFlags = 0; 69f75da0c8SAlexey Lapshin if (AllFlags & SectionFlag::SecAlloc) 70f75da0c8SAlexey Lapshin NewFlags |= ELF::SHF_ALLOC; 71f75da0c8SAlexey Lapshin if (!(AllFlags & SectionFlag::SecReadonly)) 72f75da0c8SAlexey Lapshin NewFlags |= ELF::SHF_WRITE; 73f75da0c8SAlexey Lapshin if (AllFlags & SectionFlag::SecCode) 74f75da0c8SAlexey Lapshin NewFlags |= ELF::SHF_EXECINSTR; 75f75da0c8SAlexey Lapshin if (AllFlags & SectionFlag::SecMerge) 76f75da0c8SAlexey Lapshin NewFlags |= ELF::SHF_MERGE; 77f75da0c8SAlexey Lapshin if (AllFlags & SectionFlag::SecStrings) 78f75da0c8SAlexey Lapshin NewFlags |= ELF::SHF_STRINGS; 79f75da0c8SAlexey Lapshin if (AllFlags & SectionFlag::SecExclude) 80f75da0c8SAlexey Lapshin NewFlags |= ELF::SHF_EXCLUDE; 816f1395a1SThomas Köppe if (AllFlags & SectionFlag::SecLarge) { 826f1395a1SThomas Köppe if (EMachine != EM_X86_64) 836f1395a1SThomas Köppe return createStringError(errc::invalid_argument, 846f1395a1SThomas Köppe "section flag SHF_X86_64_LARGE can only be used " 856f1395a1SThomas Köppe "with x86_64 architecture"); 866f1395a1SThomas Köppe NewFlags |= ELF::SHF_X86_64_LARGE; 876f1395a1SThomas Köppe } 88f75da0c8SAlexey Lapshin return NewFlags; 89f75da0c8SAlexey Lapshin } 90f75da0c8SAlexey Lapshin 91f75da0c8SAlexey Lapshin static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags, 926f1395a1SThomas Köppe uint64_t NewFlags, 936f1395a1SThomas Köppe uint16_t EMachine) { 94f75da0c8SAlexey Lapshin // Preserve some flags which should not be dropped when setting flags. 95f75da0c8SAlexey Lapshin // Also, preserve anything OS/processor dependant. 96f75da0c8SAlexey Lapshin const uint64_t PreserveMask = 97f75da0c8SAlexey Lapshin (ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER | 98f75da0c8SAlexey Lapshin ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS | 99f75da0c8SAlexey Lapshin ELF::SHF_INFO_LINK) & 1006f1395a1SThomas Köppe ~ELF::SHF_EXCLUDE & 101336b7a25SMikael Holmen ~(EMachine == EM_X86_64 ? (uint64_t)ELF::SHF_X86_64_LARGE : 0UL); 102f75da0c8SAlexey Lapshin return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask); 103f75da0c8SAlexey Lapshin } 104f75da0c8SAlexey Lapshin 105c973123fSAlexey Karyakin static void setSectionType(SectionBase &Sec, uint64_t Type) { 106c973123fSAlexey Karyakin // If Sec's type is changed from SHT_NOBITS due to --set-section-flags, 107c973123fSAlexey Karyakin // Offset may not be aligned. Align it to max(Align, 1). 108c973123fSAlexey Karyakin if (Sec.Type == ELF::SHT_NOBITS && Type != ELF::SHT_NOBITS) 109c973123fSAlexey Karyakin Sec.Offset = alignTo(Sec.Offset, std::max(Sec.Align, uint64_t(1))); 110c973123fSAlexey Karyakin Sec.Type = Type; 111c973123fSAlexey Karyakin } 112c973123fSAlexey Karyakin 1136f1395a1SThomas Köppe static Error setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags, 1146f1395a1SThomas Köppe uint16_t EMachine) { 1156f1395a1SThomas Köppe Expected<uint64_t> NewFlags = getNewShfFlags(Flags, EMachine); 1166f1395a1SThomas Köppe if (!NewFlags) 1176f1395a1SThomas Köppe return NewFlags.takeError(); 1186f1395a1SThomas Köppe Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, *NewFlags, EMachine); 119f75da0c8SAlexey Lapshin 120f75da0c8SAlexey Lapshin // In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule 121f75da0c8SAlexey Lapshin // may promote more non-ALLOC sections than GNU objcopy, but it is fine as 122f75da0c8SAlexey Lapshin // non-ALLOC SHT_NOBITS sections do not make much sense. 123f75da0c8SAlexey Lapshin if (Sec.Type == SHT_NOBITS && 124f75da0c8SAlexey Lapshin (!(Sec.Flags & ELF::SHF_ALLOC) || 125f75da0c8SAlexey Lapshin Flags & (SectionFlag::SecContents | SectionFlag::SecLoad))) 126c973123fSAlexey Karyakin setSectionType(Sec, ELF::SHT_PROGBITS); 1276f1395a1SThomas Köppe 1286f1395a1SThomas Köppe return Error::success(); 129f75da0c8SAlexey Lapshin } 130f75da0c8SAlexey Lapshin 131f75da0c8SAlexey Lapshin static ElfType getOutputElfType(const Binary &Bin) { 132f75da0c8SAlexey Lapshin // Infer output ELF type from the input ELF object 133f75da0c8SAlexey Lapshin if (isa<ELFObjectFile<ELF32LE>>(Bin)) 134f75da0c8SAlexey Lapshin return ELFT_ELF32LE; 135f75da0c8SAlexey Lapshin if (isa<ELFObjectFile<ELF64LE>>(Bin)) 136f75da0c8SAlexey Lapshin return ELFT_ELF64LE; 137f75da0c8SAlexey Lapshin if (isa<ELFObjectFile<ELF32BE>>(Bin)) 138f75da0c8SAlexey Lapshin return ELFT_ELF32BE; 139f75da0c8SAlexey Lapshin if (isa<ELFObjectFile<ELF64BE>>(Bin)) 140f75da0c8SAlexey Lapshin return ELFT_ELF64BE; 141f75da0c8SAlexey Lapshin llvm_unreachable("Invalid ELFType"); 142f75da0c8SAlexey Lapshin } 143f75da0c8SAlexey Lapshin 144f75da0c8SAlexey Lapshin static ElfType getOutputElfType(const MachineInfo &MI) { 145f75da0c8SAlexey Lapshin // Infer output ELF type from the binary arch specified 146f75da0c8SAlexey Lapshin if (MI.Is64Bit) 147f75da0c8SAlexey Lapshin return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE; 148f75da0c8SAlexey Lapshin else 149f75da0c8SAlexey Lapshin return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE; 150f75da0c8SAlexey Lapshin } 151f75da0c8SAlexey Lapshin 152f75da0c8SAlexey Lapshin static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config, 153f75da0c8SAlexey Lapshin Object &Obj, raw_ostream &Out, 154f75da0c8SAlexey Lapshin ElfType OutputElfType) { 155f75da0c8SAlexey Lapshin // Depending on the initial ELFT and OutputFormat we need a different Writer. 156f75da0c8SAlexey Lapshin switch (OutputElfType) { 157f75da0c8SAlexey Lapshin case ELFT_ELF32LE: 158f75da0c8SAlexey Lapshin return std::make_unique<ELFWriter<ELF32LE>>(Obj, Out, !Config.StripSections, 159f75da0c8SAlexey Lapshin Config.OnlyKeepDebug); 160f75da0c8SAlexey Lapshin case ELFT_ELF64LE: 161f75da0c8SAlexey Lapshin return std::make_unique<ELFWriter<ELF64LE>>(Obj, Out, !Config.StripSections, 162f75da0c8SAlexey Lapshin Config.OnlyKeepDebug); 163f75da0c8SAlexey Lapshin case ELFT_ELF32BE: 164f75da0c8SAlexey Lapshin return std::make_unique<ELFWriter<ELF32BE>>(Obj, Out, !Config.StripSections, 165f75da0c8SAlexey Lapshin Config.OnlyKeepDebug); 166f75da0c8SAlexey Lapshin case ELFT_ELF64BE: 167f75da0c8SAlexey Lapshin return std::make_unique<ELFWriter<ELF64BE>>(Obj, Out, !Config.StripSections, 168f75da0c8SAlexey Lapshin Config.OnlyKeepDebug); 169f75da0c8SAlexey Lapshin } 170f75da0c8SAlexey Lapshin llvm_unreachable("Invalid output format"); 171f75da0c8SAlexey Lapshin } 172f75da0c8SAlexey Lapshin 173f75da0c8SAlexey Lapshin static std::unique_ptr<Writer> createWriter(const CommonConfig &Config, 174f75da0c8SAlexey Lapshin Object &Obj, raw_ostream &Out, 175f75da0c8SAlexey Lapshin ElfType OutputElfType) { 176f75da0c8SAlexey Lapshin switch (Config.OutputFormat) { 177f75da0c8SAlexey Lapshin case FileFormat::Binary: 1784070dffdSquic-akaryaki return std::make_unique<BinaryWriter>(Obj, Out, Config); 179f75da0c8SAlexey Lapshin case FileFormat::IHex: 1807ddc3205Squic-areg return std::make_unique<IHexWriter>(Obj, Out, Config.OutputFilename); 1817ddc3205Squic-areg case FileFormat::SREC: 1827ddc3205Squic-areg return std::make_unique<SRECWriter>(Obj, Out, Config.OutputFilename); 183f75da0c8SAlexey Lapshin default: 184f75da0c8SAlexey Lapshin return createELFWriter(Config, Obj, Out, OutputElfType); 185f75da0c8SAlexey Lapshin } 186f75da0c8SAlexey Lapshin } 187f75da0c8SAlexey Lapshin 188f75da0c8SAlexey Lapshin static Error dumpSectionToFile(StringRef SecName, StringRef Filename, 189f75da0c8SAlexey Lapshin Object &Obj) { 190f75da0c8SAlexey Lapshin for (auto &Sec : Obj.sections()) { 191f75da0c8SAlexey Lapshin if (Sec.Name == SecName) { 192f75da0c8SAlexey Lapshin if (Sec.Type == SHT_NOBITS) 193f75da0c8SAlexey Lapshin return createStringError(object_error::parse_failed, 194f75da0c8SAlexey Lapshin "cannot dump section '%s': it has no contents", 195f75da0c8SAlexey Lapshin SecName.str().c_str()); 196f75da0c8SAlexey Lapshin Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = 197f75da0c8SAlexey Lapshin FileOutputBuffer::create(Filename, Sec.OriginalData.size()); 198f75da0c8SAlexey Lapshin if (!BufferOrErr) 199f75da0c8SAlexey Lapshin return BufferOrErr.takeError(); 200f75da0c8SAlexey Lapshin std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr); 201f75da0c8SAlexey Lapshin std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), 202f75da0c8SAlexey Lapshin Buf->getBufferStart()); 203f75da0c8SAlexey Lapshin if (Error E = Buf->commit()) 204f75da0c8SAlexey Lapshin return E; 205f75da0c8SAlexey Lapshin return Error::success(); 206f75da0c8SAlexey Lapshin } 207f75da0c8SAlexey Lapshin } 208f75da0c8SAlexey Lapshin return createStringError(object_error::parse_failed, "section '%s' not found", 209f75da0c8SAlexey Lapshin SecName.str().c_str()); 210f75da0c8SAlexey Lapshin } 211f75da0c8SAlexey Lapshin 212122d368bSFangrui Song Error Object::compressOrDecompressSections(const CommonConfig &Config) { 21307942987SFangrui Song // Build a list of sections we are going to replace. 21407942987SFangrui Song // We can't call `addSection` while iterating over sections, 215f75da0c8SAlexey Lapshin // because it would mutate the sections array. 216122d368bSFangrui Song SmallVector<std::pair<SectionBase *, std::function<SectionBase *()>>, 0> 217122d368bSFangrui Song ToReplace; 218122d368bSFangrui Song for (SectionBase &Sec : sections()) { 21907942987SFangrui Song std::optional<DebugCompressionType> CType; 22007942987SFangrui Song for (auto &[Matcher, T] : Config.compressSections) 22107942987SFangrui Song if (Matcher.matches(Sec.Name)) 22207942987SFangrui Song CType = T; 22307942987SFangrui Song // Handle --compress-debug-sections and --decompress-debug-sections, which 22407942987SFangrui Song // apply to non-ALLOC debug sections. 22507942987SFangrui Song if (!(Sec.Flags & SHF_ALLOC) && StringRef(Sec.Name).starts_with(".debug")) { 22607942987SFangrui Song if (Config.CompressionType != DebugCompressionType::None) 22707942987SFangrui Song CType = Config.CompressionType; 22807942987SFangrui Song else if (Config.DecompressDebugSections) 22907942987SFangrui Song CType = DebugCompressionType::None; 23007942987SFangrui Song } 23107942987SFangrui Song if (!CType) 232122d368bSFangrui Song continue; 23307942987SFangrui Song 23407942987SFangrui Song if (Sec.ParentSegment) 23507942987SFangrui Song return createStringError( 23607942987SFangrui Song errc::invalid_argument, 23707942987SFangrui Song "section '" + Sec.Name + 23807942987SFangrui Song "' within a segment cannot be (de)compressed"); 23907942987SFangrui Song 240122d368bSFangrui Song if (auto *CS = dyn_cast<CompressedSection>(&Sec)) { 24107942987SFangrui Song if (*CType == DebugCompressionType::None) 242122d368bSFangrui Song ToReplace.emplace_back( 243122d368bSFangrui Song &Sec, [=] { return &addSection<DecompressedSection>(*CS); }); 24407942987SFangrui Song } else if (*CType != DebugCompressionType::None) { 24507942987SFangrui Song ToReplace.emplace_back(&Sec, [=, S = &Sec] { 246122d368bSFangrui Song return &addSection<CompressedSection>( 24707942987SFangrui Song CompressedSection(*S, *CType, Is64Bits)); 248122d368bSFangrui Song }); 249122d368bSFangrui Song } 250f75da0c8SAlexey Lapshin } 251f75da0c8SAlexey Lapshin 252122d368bSFangrui Song DenseMap<SectionBase *, SectionBase *> FromTo; 253122d368bSFangrui Song for (auto [S, Func] : ToReplace) 254122d368bSFangrui Song FromTo[S] = Func(); 255122d368bSFangrui Song return replaceSections(FromTo); 256f75da0c8SAlexey Lapshin } 257f75da0c8SAlexey Lapshin 258f75da0c8SAlexey Lapshin static bool isAArch64MappingSymbol(const Symbol &Sym) { 259f75da0c8SAlexey Lapshin if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE || 260f75da0c8SAlexey Lapshin Sym.getShndx() == SHN_UNDEF) 261f75da0c8SAlexey Lapshin return false; 262f75da0c8SAlexey Lapshin StringRef Name = Sym.Name; 263f75da0c8SAlexey Lapshin if (!Name.consume_front("$x") && !Name.consume_front("$d")) 264f75da0c8SAlexey Lapshin return false; 265586ecdf2SKazu Hirata return Name.empty() || Name.starts_with("."); 266f75da0c8SAlexey Lapshin } 267f75da0c8SAlexey Lapshin 268f75da0c8SAlexey Lapshin static bool isArmMappingSymbol(const Symbol &Sym) { 269f75da0c8SAlexey Lapshin if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE || 270f75da0c8SAlexey Lapshin Sym.getShndx() == SHN_UNDEF) 271f75da0c8SAlexey Lapshin return false; 272f75da0c8SAlexey Lapshin StringRef Name = Sym.Name; 273f75da0c8SAlexey Lapshin if (!Name.consume_front("$a") && !Name.consume_front("$d") && 274f75da0c8SAlexey Lapshin !Name.consume_front("$t")) 275f75da0c8SAlexey Lapshin return false; 276586ecdf2SKazu Hirata return Name.empty() || Name.starts_with("."); 277f75da0c8SAlexey Lapshin } 278f75da0c8SAlexey Lapshin 279f75da0c8SAlexey Lapshin // Check if the symbol should be preserved because it is required by ABI. 280f75da0c8SAlexey Lapshin static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym) { 281f75da0c8SAlexey Lapshin switch (Obj.Machine) { 282f75da0c8SAlexey Lapshin case EM_AARCH64: 283f75da0c8SAlexey Lapshin // Mapping symbols should be preserved for a relocatable object file. 284f75da0c8SAlexey Lapshin return Obj.isRelocatable() && isAArch64MappingSymbol(Sym); 285f75da0c8SAlexey Lapshin case EM_ARM: 286f75da0c8SAlexey Lapshin // Mapping symbols should be preserved for a relocatable object file. 287f75da0c8SAlexey Lapshin return Obj.isRelocatable() && isArmMappingSymbol(Sym); 288f75da0c8SAlexey Lapshin default: 289f75da0c8SAlexey Lapshin return false; 290f75da0c8SAlexey Lapshin } 291f75da0c8SAlexey Lapshin } 292f75da0c8SAlexey Lapshin 293f75da0c8SAlexey Lapshin static bool isUnneededSymbol(const Symbol &Sym) { 294f75da0c8SAlexey Lapshin return !Sym.Referenced && 295f75da0c8SAlexey Lapshin (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) && 296f75da0c8SAlexey Lapshin Sym.Type != STT_SECTION; 297f75da0c8SAlexey Lapshin } 298f75da0c8SAlexey Lapshin 299f75da0c8SAlexey Lapshin static Error updateAndRemoveSymbols(const CommonConfig &Config, 300f75da0c8SAlexey Lapshin const ELFConfig &ELFConfig, Object &Obj) { 301f75da0c8SAlexey Lapshin // TODO: update or remove symbols only if there is an option that affects 302f75da0c8SAlexey Lapshin // them. 303f75da0c8SAlexey Lapshin if (!Obj.SymbolTable) 304f75da0c8SAlexey Lapshin return Error::success(); 305f75da0c8SAlexey Lapshin 306f75da0c8SAlexey Lapshin Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { 3074946cc37SIlia Kuklin if (Config.SymbolsToSkip.matches(Sym.Name)) 3084946cc37SIlia Kuklin return; 3094946cc37SIlia Kuklin 310f75da0c8SAlexey Lapshin // Common and undefined symbols don't make sense as local symbols, and can 311f75da0c8SAlexey Lapshin // even cause crashes if we localize those, so skip them. 312f75da0c8SAlexey Lapshin if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF && 313f75da0c8SAlexey Lapshin ((ELFConfig.LocalizeHidden && 314f75da0c8SAlexey Lapshin (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || 315f75da0c8SAlexey Lapshin Config.SymbolsToLocalize.matches(Sym.Name))) 316f75da0c8SAlexey Lapshin Sym.Binding = STB_LOCAL; 317f75da0c8SAlexey Lapshin 31807d8a457SIlia Kuklin for (auto &[Matcher, Visibility] : ELFConfig.SymbolsToSetVisibility) 31907d8a457SIlia Kuklin if (Matcher.matches(Sym.Name)) 32007d8a457SIlia Kuklin Sym.Visibility = Visibility; 32107d8a457SIlia Kuklin 322f75da0c8SAlexey Lapshin // Note: these two globalize flags have very similar names but different 323f75da0c8SAlexey Lapshin // meanings: 324f75da0c8SAlexey Lapshin // 325f75da0c8SAlexey Lapshin // --globalize-symbol: promote a symbol to global 326f75da0c8SAlexey Lapshin // --keep-global-symbol: all symbols except for these should be made local 327f75da0c8SAlexey Lapshin // 328f75da0c8SAlexey Lapshin // If --globalize-symbol is specified for a given symbol, it will be 329f75da0c8SAlexey Lapshin // global in the output file even if it is not included via 330f75da0c8SAlexey Lapshin // --keep-global-symbol. Because of that, make sure to check 331f75da0c8SAlexey Lapshin // --globalize-symbol second. 332f75da0c8SAlexey Lapshin if (!Config.SymbolsToKeepGlobal.empty() && 333f75da0c8SAlexey Lapshin !Config.SymbolsToKeepGlobal.matches(Sym.Name) && 334f75da0c8SAlexey Lapshin Sym.getShndx() != SHN_UNDEF) 335f75da0c8SAlexey Lapshin Sym.Binding = STB_LOCAL; 336f75da0c8SAlexey Lapshin 337f75da0c8SAlexey Lapshin if (Config.SymbolsToGlobalize.matches(Sym.Name) && 338f75da0c8SAlexey Lapshin Sym.getShndx() != SHN_UNDEF) 339f75da0c8SAlexey Lapshin Sym.Binding = STB_GLOBAL; 340f75da0c8SAlexey Lapshin 34130718f3aSFangrui Song // SymbolsToWeaken applies to both STB_GLOBAL and STB_GNU_UNIQUE. 34230718f3aSFangrui Song if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding != STB_LOCAL) 343f75da0c8SAlexey Lapshin Sym.Binding = STB_WEAK; 344f75da0c8SAlexey Lapshin 34530718f3aSFangrui Song if (Config.Weaken && Sym.Binding != STB_LOCAL && 346f75da0c8SAlexey Lapshin Sym.getShndx() != SHN_UNDEF) 347f75da0c8SAlexey Lapshin Sym.Binding = STB_WEAK; 348f75da0c8SAlexey Lapshin 349f75da0c8SAlexey Lapshin const auto I = Config.SymbolsToRename.find(Sym.Name); 350f75da0c8SAlexey Lapshin if (I != Config.SymbolsToRename.end()) 351f75da0c8SAlexey Lapshin Sym.Name = std::string(I->getValue()); 352f75da0c8SAlexey Lapshin 3531b87ebceSYi Kong if (!Config.SymbolsPrefixRemove.empty() && Sym.Type != STT_SECTION) 3541b87ebceSYi Kong if (Sym.Name.compare(0, Config.SymbolsPrefixRemove.size(), 3551b87ebceSYi Kong Config.SymbolsPrefixRemove) == 0) 3561b87ebceSYi Kong Sym.Name = Sym.Name.substr(Config.SymbolsPrefixRemove.size()); 3571b87ebceSYi Kong 358f75da0c8SAlexey Lapshin if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION) 359f75da0c8SAlexey Lapshin Sym.Name = (Config.SymbolsPrefix + Sym.Name).str(); 360f75da0c8SAlexey Lapshin }); 361f75da0c8SAlexey Lapshin 362f75da0c8SAlexey Lapshin // The purpose of this loop is to mark symbols referenced by sections 363f75da0c8SAlexey Lapshin // (like GroupSection or RelocationSection). This way, we know which 364f75da0c8SAlexey Lapshin // symbols are still 'needed' and which are not. 365f75da0c8SAlexey Lapshin if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() || 366f75da0c8SAlexey Lapshin !Config.OnlySection.empty()) { 367f75da0c8SAlexey Lapshin for (SectionBase &Sec : Obj.sections()) 368f75da0c8SAlexey Lapshin Sec.markSymbols(); 369f75da0c8SAlexey Lapshin } 370f75da0c8SAlexey Lapshin 371f75da0c8SAlexey Lapshin auto RemoveSymbolsPred = [&](const Symbol &Sym) { 372f75da0c8SAlexey Lapshin if (Config.SymbolsToKeep.matches(Sym.Name) || 373f75da0c8SAlexey Lapshin (ELFConfig.KeepFileSymbols && Sym.Type == STT_FILE)) 374f75da0c8SAlexey Lapshin return false; 375f75da0c8SAlexey Lapshin 376f75da0c8SAlexey Lapshin if (Config.SymbolsToRemove.matches(Sym.Name)) 377f75da0c8SAlexey Lapshin return true; 378f75da0c8SAlexey Lapshin 379f75da0c8SAlexey Lapshin if (Config.StripAll || Config.StripAllGNU) 380f75da0c8SAlexey Lapshin return true; 381f75da0c8SAlexey Lapshin 382f75da0c8SAlexey Lapshin if (isRequiredByABISymbol(Obj, Sym)) 383f75da0c8SAlexey Lapshin return false; 384f75da0c8SAlexey Lapshin 385f75da0c8SAlexey Lapshin if (Config.StripDebug && Sym.Type == STT_FILE) 386f75da0c8SAlexey Lapshin return true; 387f75da0c8SAlexey Lapshin 388f75da0c8SAlexey Lapshin if ((Config.DiscardMode == DiscardType::All || 389f75da0c8SAlexey Lapshin (Config.DiscardMode == DiscardType::Locals && 390586ecdf2SKazu Hirata StringRef(Sym.Name).starts_with(".L"))) && 391f75da0c8SAlexey Lapshin Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF && 392f75da0c8SAlexey Lapshin Sym.Type != STT_FILE && Sym.Type != STT_SECTION) 393f75da0c8SAlexey Lapshin return true; 394f75da0c8SAlexey Lapshin 395f75da0c8SAlexey Lapshin if ((Config.StripUnneeded || 396f75da0c8SAlexey Lapshin Config.UnneededSymbolsToRemove.matches(Sym.Name)) && 397f75da0c8SAlexey Lapshin (!Obj.isRelocatable() || isUnneededSymbol(Sym))) 398f75da0c8SAlexey Lapshin return true; 399f75da0c8SAlexey Lapshin 400f75da0c8SAlexey Lapshin // We want to remove undefined symbols if all references have been stripped. 401f75da0c8SAlexey Lapshin if (!Config.OnlySection.empty() && !Sym.Referenced && 402f75da0c8SAlexey Lapshin Sym.getShndx() == SHN_UNDEF) 403f75da0c8SAlexey Lapshin return true; 404f75da0c8SAlexey Lapshin 405f75da0c8SAlexey Lapshin return false; 406f75da0c8SAlexey Lapshin }; 407f75da0c8SAlexey Lapshin 408f75da0c8SAlexey Lapshin return Obj.removeSymbols(RemoveSymbolsPred); 409f75da0c8SAlexey Lapshin } 410f75da0c8SAlexey Lapshin 411f75da0c8SAlexey Lapshin static Error replaceAndRemoveSections(const CommonConfig &Config, 412f75da0c8SAlexey Lapshin const ELFConfig &ELFConfig, Object &Obj) { 413f75da0c8SAlexey Lapshin SectionPred RemovePred = [](const SectionBase &) { return false; }; 414f75da0c8SAlexey Lapshin 415f75da0c8SAlexey Lapshin // Removes: 416f75da0c8SAlexey Lapshin if (!Config.ToRemove.empty()) { 417f75da0c8SAlexey Lapshin RemovePred = [&Config](const SectionBase &Sec) { 418f75da0c8SAlexey Lapshin return Config.ToRemove.matches(Sec.Name); 419f75da0c8SAlexey Lapshin }; 420f75da0c8SAlexey Lapshin } 421f75da0c8SAlexey Lapshin 422f75da0c8SAlexey Lapshin if (Config.StripDWO) 423f75da0c8SAlexey Lapshin RemovePred = [RemovePred](const SectionBase &Sec) { 424f75da0c8SAlexey Lapshin return isDWOSection(Sec) || RemovePred(Sec); 425f75da0c8SAlexey Lapshin }; 426f75da0c8SAlexey Lapshin 427f75da0c8SAlexey Lapshin if (Config.ExtractDWO) 428f75da0c8SAlexey Lapshin RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 429f75da0c8SAlexey Lapshin return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec); 430f75da0c8SAlexey Lapshin }; 431f75da0c8SAlexey Lapshin 432f75da0c8SAlexey Lapshin if (Config.StripAllGNU) 433f75da0c8SAlexey Lapshin RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 434f75da0c8SAlexey Lapshin if (RemovePred(Sec)) 435f75da0c8SAlexey Lapshin return true; 436f75da0c8SAlexey Lapshin if ((Sec.Flags & SHF_ALLOC) != 0) 437f75da0c8SAlexey Lapshin return false; 438f75da0c8SAlexey Lapshin if (&Sec == Obj.SectionNames) 439f75da0c8SAlexey Lapshin return false; 440f75da0c8SAlexey Lapshin switch (Sec.Type) { 441f75da0c8SAlexey Lapshin case SHT_SYMTAB: 442f75da0c8SAlexey Lapshin case SHT_REL: 443f75da0c8SAlexey Lapshin case SHT_RELA: 444f75da0c8SAlexey Lapshin case SHT_STRTAB: 445f75da0c8SAlexey Lapshin return true; 446f75da0c8SAlexey Lapshin } 447f75da0c8SAlexey Lapshin return isDebugSection(Sec); 448f75da0c8SAlexey Lapshin }; 449f75da0c8SAlexey Lapshin 450f75da0c8SAlexey Lapshin if (Config.StripSections) { 451f75da0c8SAlexey Lapshin RemovePred = [RemovePred](const SectionBase &Sec) { 452f75da0c8SAlexey Lapshin return RemovePred(Sec) || Sec.ParentSegment == nullptr; 453f75da0c8SAlexey Lapshin }; 454f75da0c8SAlexey Lapshin } 455f75da0c8SAlexey Lapshin 456f75da0c8SAlexey Lapshin if (Config.StripDebug || Config.StripUnneeded) { 457f75da0c8SAlexey Lapshin RemovePred = [RemovePred](const SectionBase &Sec) { 458f75da0c8SAlexey Lapshin return RemovePred(Sec) || isDebugSection(Sec); 459f75da0c8SAlexey Lapshin }; 460f75da0c8SAlexey Lapshin } 461f75da0c8SAlexey Lapshin 462f75da0c8SAlexey Lapshin if (Config.StripNonAlloc) 463f75da0c8SAlexey Lapshin RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 464f75da0c8SAlexey Lapshin if (RemovePred(Sec)) 465f75da0c8SAlexey Lapshin return true; 466f75da0c8SAlexey Lapshin if (&Sec == Obj.SectionNames) 467f75da0c8SAlexey Lapshin return false; 468f75da0c8SAlexey Lapshin return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr; 469f75da0c8SAlexey Lapshin }; 470f75da0c8SAlexey Lapshin 471f75da0c8SAlexey Lapshin if (Config.StripAll) 472f75da0c8SAlexey Lapshin RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 473f75da0c8SAlexey Lapshin if (RemovePred(Sec)) 474f75da0c8SAlexey Lapshin return true; 475f75da0c8SAlexey Lapshin if (&Sec == Obj.SectionNames) 476f75da0c8SAlexey Lapshin return false; 477586ecdf2SKazu Hirata if (StringRef(Sec.Name).starts_with(".gnu.warning")) 478f75da0c8SAlexey Lapshin return false; 47911ca56eaSFelix Kellenbenz if (StringRef(Sec.Name).starts_with(".gnu_debuglink")) 48011ca56eaSFelix Kellenbenz return false; 481f75da0c8SAlexey Lapshin // We keep the .ARM.attribute section to maintain compatibility 482f75da0c8SAlexey Lapshin // with Debian derived distributions. This is a bug in their 483f75da0c8SAlexey Lapshin // patchset as documented here: 484f75da0c8SAlexey Lapshin // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798 485f75da0c8SAlexey Lapshin if (Sec.Type == SHT_ARM_ATTRIBUTES) 486f75da0c8SAlexey Lapshin return false; 487f75da0c8SAlexey Lapshin if (Sec.ParentSegment != nullptr) 488f75da0c8SAlexey Lapshin return false; 489f75da0c8SAlexey Lapshin return (Sec.Flags & SHF_ALLOC) == 0; 490f75da0c8SAlexey Lapshin }; 491f75da0c8SAlexey Lapshin 492f75da0c8SAlexey Lapshin if (Config.ExtractPartition || Config.ExtractMainPartition) { 493f75da0c8SAlexey Lapshin RemovePred = [RemovePred](const SectionBase &Sec) { 494f75da0c8SAlexey Lapshin if (RemovePred(Sec)) 495f75da0c8SAlexey Lapshin return true; 496f75da0c8SAlexey Lapshin if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR) 497f75da0c8SAlexey Lapshin return true; 498f75da0c8SAlexey Lapshin return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment; 499f75da0c8SAlexey Lapshin }; 500f75da0c8SAlexey Lapshin } 501f75da0c8SAlexey Lapshin 502f75da0c8SAlexey Lapshin // Explicit copies: 503f75da0c8SAlexey Lapshin if (!Config.OnlySection.empty()) { 504f75da0c8SAlexey Lapshin RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) { 505f75da0c8SAlexey Lapshin // Explicitly keep these sections regardless of previous removes. 506f75da0c8SAlexey Lapshin if (Config.OnlySection.matches(Sec.Name)) 507f75da0c8SAlexey Lapshin return false; 508f75da0c8SAlexey Lapshin 509f75da0c8SAlexey Lapshin // Allow all implicit removes. 510f75da0c8SAlexey Lapshin if (RemovePred(Sec)) 511f75da0c8SAlexey Lapshin return true; 512f75da0c8SAlexey Lapshin 513f75da0c8SAlexey Lapshin // Keep special sections. 514f75da0c8SAlexey Lapshin if (Obj.SectionNames == &Sec) 515f75da0c8SAlexey Lapshin return false; 516f75da0c8SAlexey Lapshin if (Obj.SymbolTable == &Sec || 517f75da0c8SAlexey Lapshin (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec)) 518f75da0c8SAlexey Lapshin return false; 519f75da0c8SAlexey Lapshin 520f75da0c8SAlexey Lapshin // Remove everything else. 521f75da0c8SAlexey Lapshin return true; 522f75da0c8SAlexey Lapshin }; 523f75da0c8SAlexey Lapshin } 524f75da0c8SAlexey Lapshin 525f75da0c8SAlexey Lapshin if (!Config.KeepSection.empty()) { 526f75da0c8SAlexey Lapshin RemovePred = [&Config, RemovePred](const SectionBase &Sec) { 527f75da0c8SAlexey Lapshin // Explicitly keep these sections regardless of previous removes. 528f75da0c8SAlexey Lapshin if (Config.KeepSection.matches(Sec.Name)) 529f75da0c8SAlexey Lapshin return false; 530f75da0c8SAlexey Lapshin // Otherwise defer to RemovePred. 531f75da0c8SAlexey Lapshin return RemovePred(Sec); 532f75da0c8SAlexey Lapshin }; 533f75da0c8SAlexey Lapshin } 534f75da0c8SAlexey Lapshin 535f75da0c8SAlexey Lapshin // This has to be the last predicate assignment. 536f75da0c8SAlexey Lapshin // If the option --keep-symbol has been specified 537f75da0c8SAlexey Lapshin // and at least one of those symbols is present 538f75da0c8SAlexey Lapshin // (equivalently, the updated symbol table is not empty) 539f75da0c8SAlexey Lapshin // the symbol table and the string table should not be removed. 540f75da0c8SAlexey Lapshin if ((!Config.SymbolsToKeep.empty() || ELFConfig.KeepFileSymbols) && 541f75da0c8SAlexey Lapshin Obj.SymbolTable && !Obj.SymbolTable->empty()) { 542f75da0c8SAlexey Lapshin RemovePred = [&Obj, RemovePred](const SectionBase &Sec) { 543f75da0c8SAlexey Lapshin if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab()) 544f75da0c8SAlexey Lapshin return false; 545f75da0c8SAlexey Lapshin return RemovePred(Sec); 546f75da0c8SAlexey Lapshin }; 547f75da0c8SAlexey Lapshin } 548f75da0c8SAlexey Lapshin 549f75da0c8SAlexey Lapshin if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred)) 550f75da0c8SAlexey Lapshin return E; 551f75da0c8SAlexey Lapshin 552122d368bSFangrui Song if (Error E = Obj.compressOrDecompressSections(Config)) 553122d368bSFangrui Song return E; 554f75da0c8SAlexey Lapshin 555f75da0c8SAlexey Lapshin return Error::success(); 556f75da0c8SAlexey Lapshin } 557f75da0c8SAlexey Lapshin 558f75da0c8SAlexey Lapshin // Add symbol to the Object symbol table with the specified properties. 559f75da0c8SAlexey Lapshin static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo, 560f75da0c8SAlexey Lapshin uint8_t DefaultVisibility) { 561f75da0c8SAlexey Lapshin SectionBase *Sec = Obj.findSection(SymInfo.SectionName); 562f75da0c8SAlexey Lapshin uint64_t Value = Sec ? Sec->Addr + SymInfo.Value : SymInfo.Value; 563f75da0c8SAlexey Lapshin 564f75da0c8SAlexey Lapshin uint8_t Bind = ELF::STB_GLOBAL; 565f75da0c8SAlexey Lapshin uint8_t Type = ELF::STT_NOTYPE; 566f75da0c8SAlexey Lapshin uint8_t Visibility = DefaultVisibility; 567f75da0c8SAlexey Lapshin 568f75da0c8SAlexey Lapshin for (SymbolFlag FlagValue : SymInfo.Flags) 569f75da0c8SAlexey Lapshin switch (FlagValue) { 570f75da0c8SAlexey Lapshin case SymbolFlag::Global: 571f75da0c8SAlexey Lapshin Bind = ELF::STB_GLOBAL; 572f75da0c8SAlexey Lapshin break; 573f75da0c8SAlexey Lapshin case SymbolFlag::Local: 574f75da0c8SAlexey Lapshin Bind = ELF::STB_LOCAL; 575f75da0c8SAlexey Lapshin break; 576f75da0c8SAlexey Lapshin case SymbolFlag::Weak: 577f75da0c8SAlexey Lapshin Bind = ELF::STB_WEAK; 578f75da0c8SAlexey Lapshin break; 579f75da0c8SAlexey Lapshin case SymbolFlag::Default: 580f75da0c8SAlexey Lapshin Visibility = ELF::STV_DEFAULT; 581f75da0c8SAlexey Lapshin break; 582f75da0c8SAlexey Lapshin case SymbolFlag::Hidden: 583f75da0c8SAlexey Lapshin Visibility = ELF::STV_HIDDEN; 584f75da0c8SAlexey Lapshin break; 585f75da0c8SAlexey Lapshin case SymbolFlag::Protected: 586f75da0c8SAlexey Lapshin Visibility = ELF::STV_PROTECTED; 587f75da0c8SAlexey Lapshin break; 588f75da0c8SAlexey Lapshin case SymbolFlag::File: 589f75da0c8SAlexey Lapshin Type = ELF::STT_FILE; 590f75da0c8SAlexey Lapshin break; 591f75da0c8SAlexey Lapshin case SymbolFlag::Section: 592f75da0c8SAlexey Lapshin Type = ELF::STT_SECTION; 593f75da0c8SAlexey Lapshin break; 594f75da0c8SAlexey Lapshin case SymbolFlag::Object: 595f75da0c8SAlexey Lapshin Type = ELF::STT_OBJECT; 596f75da0c8SAlexey Lapshin break; 597f75da0c8SAlexey Lapshin case SymbolFlag::Function: 598f75da0c8SAlexey Lapshin Type = ELF::STT_FUNC; 599f75da0c8SAlexey Lapshin break; 600f75da0c8SAlexey Lapshin case SymbolFlag::IndirectFunction: 601f75da0c8SAlexey Lapshin Type = ELF::STT_GNU_IFUNC; 602f75da0c8SAlexey Lapshin break; 603f75da0c8SAlexey Lapshin default: /* Other flag values are ignored for ELF. */ 604f75da0c8SAlexey Lapshin break; 605f75da0c8SAlexey Lapshin }; 606f75da0c8SAlexey Lapshin 607f75da0c8SAlexey Lapshin Obj.SymbolTable->addSymbol( 608f75da0c8SAlexey Lapshin SymInfo.SymbolName, Bind, Type, Sec, Value, Visibility, 609f75da0c8SAlexey Lapshin Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0); 610f75da0c8SAlexey Lapshin } 611f75da0c8SAlexey Lapshin 612*10772807SIgor Kudrin namespace { 613*10772807SIgor Kudrin struct RemoveNoteDetail { 614*10772807SIgor Kudrin struct DeletedRange { 615*10772807SIgor Kudrin uint64_t OldFrom; 616*10772807SIgor Kudrin uint64_t OldTo; 617*10772807SIgor Kudrin }; 618*10772807SIgor Kudrin 619*10772807SIgor Kudrin template <class ELFT> 620*10772807SIgor Kudrin static std::vector<DeletedRange> 621*10772807SIgor Kudrin findNotesToRemove(ArrayRef<uint8_t> Data, size_t Align, 622*10772807SIgor Kudrin ArrayRef<RemoveNoteInfo> NotesToRemove); 623*10772807SIgor Kudrin static std::vector<uint8_t> updateData(ArrayRef<uint8_t> OldData, 624*10772807SIgor Kudrin ArrayRef<DeletedRange> ToRemove); 625*10772807SIgor Kudrin }; 626*10772807SIgor Kudrin } // namespace 627*10772807SIgor Kudrin 628*10772807SIgor Kudrin template <class ELFT> 629*10772807SIgor Kudrin std::vector<RemoveNoteDetail::DeletedRange> 630*10772807SIgor Kudrin RemoveNoteDetail::findNotesToRemove(ArrayRef<uint8_t> Data, size_t Align, 631*10772807SIgor Kudrin ArrayRef<RemoveNoteInfo> NotesToRemove) { 632*10772807SIgor Kudrin using Elf_Nhdr = typename ELFT::Nhdr; 633*10772807SIgor Kudrin using Elf_Note = typename ELFT::Note; 634*10772807SIgor Kudrin std::vector<DeletedRange> ToRemove; 635*10772807SIgor Kudrin uint64_t CurPos = 0; 636*10772807SIgor Kudrin while (CurPos + sizeof(Elf_Nhdr) <= Data.size()) { 637*10772807SIgor Kudrin auto Nhdr = reinterpret_cast<const Elf_Nhdr *>(Data.data() + CurPos); 638*10772807SIgor Kudrin size_t FullSize = Nhdr->getSize(Align); 639*10772807SIgor Kudrin if (CurPos + FullSize > Data.size()) 640*10772807SIgor Kudrin break; 641*10772807SIgor Kudrin Elf_Note Note(*Nhdr); 642*10772807SIgor Kudrin bool ShouldRemove = 643*10772807SIgor Kudrin llvm::any_of(NotesToRemove, [&Note](const RemoveNoteInfo &NoteInfo) { 644*10772807SIgor Kudrin return NoteInfo.TypeId == Note.getType() && 645*10772807SIgor Kudrin (NoteInfo.Name.empty() || NoteInfo.Name == Note.getName()); 646*10772807SIgor Kudrin }); 647*10772807SIgor Kudrin if (ShouldRemove) 648*10772807SIgor Kudrin ToRemove.push_back({CurPos, CurPos + FullSize}); 649*10772807SIgor Kudrin CurPos += FullSize; 650*10772807SIgor Kudrin } 651*10772807SIgor Kudrin return ToRemove; 652*10772807SIgor Kudrin } 653*10772807SIgor Kudrin 654*10772807SIgor Kudrin std::vector<uint8_t> 655*10772807SIgor Kudrin RemoveNoteDetail::updateData(ArrayRef<uint8_t> OldData, 656*10772807SIgor Kudrin ArrayRef<DeletedRange> ToRemove) { 657*10772807SIgor Kudrin std::vector<uint8_t> NewData; 658*10772807SIgor Kudrin NewData.reserve(OldData.size()); 659*10772807SIgor Kudrin uint64_t CurPos = 0; 660*10772807SIgor Kudrin for (const DeletedRange &RemRange : ToRemove) { 661*10772807SIgor Kudrin if (CurPos < RemRange.OldFrom) { 662*10772807SIgor Kudrin auto Slice = OldData.slice(CurPos, RemRange.OldFrom - CurPos); 663*10772807SIgor Kudrin NewData.insert(NewData.end(), Slice.begin(), Slice.end()); 664*10772807SIgor Kudrin } 665*10772807SIgor Kudrin CurPos = RemRange.OldTo; 666*10772807SIgor Kudrin } 667*10772807SIgor Kudrin if (CurPos < OldData.size()) { 668*10772807SIgor Kudrin auto Slice = OldData.slice(CurPos); 669*10772807SIgor Kudrin NewData.insert(NewData.end(), Slice.begin(), Slice.end()); 670*10772807SIgor Kudrin } 671*10772807SIgor Kudrin return NewData; 672*10772807SIgor Kudrin } 673*10772807SIgor Kudrin 674*10772807SIgor Kudrin static Error removeNotes(Object &Obj, endianness Endianness, 675*10772807SIgor Kudrin ArrayRef<RemoveNoteInfo> NotesToRemove, 676*10772807SIgor Kudrin function_ref<Error(Error)> ErrorCallback) { 677*10772807SIgor Kudrin // TODO: Support note segments. 678*10772807SIgor Kudrin if (ErrorCallback) { 679*10772807SIgor Kudrin for (Segment &Seg : Obj.segments()) { 680*10772807SIgor Kudrin if (Seg.Type == PT_NOTE) { 681*10772807SIgor Kudrin if (Error E = ErrorCallback(createStringError( 682*10772807SIgor Kudrin errc::not_supported, "note segments are not supported"))) 683*10772807SIgor Kudrin return E; 684*10772807SIgor Kudrin break; 685*10772807SIgor Kudrin } 686*10772807SIgor Kudrin } 687*10772807SIgor Kudrin } 688*10772807SIgor Kudrin for (auto &Sec : Obj.sections()) { 689*10772807SIgor Kudrin if (Sec.Type != SHT_NOTE || !Sec.hasContents()) 690*10772807SIgor Kudrin continue; 691*10772807SIgor Kudrin // TODO: Support note sections in segments. 692*10772807SIgor Kudrin if (Sec.ParentSegment) { 693*10772807SIgor Kudrin if (ErrorCallback) 694*10772807SIgor Kudrin if (Error E = ErrorCallback(createStringError( 695*10772807SIgor Kudrin errc::not_supported, 696*10772807SIgor Kudrin "cannot remove note(s) from " + Sec.Name + 697*10772807SIgor Kudrin ": sections in segments are not supported"))) 698*10772807SIgor Kudrin return E; 699*10772807SIgor Kudrin continue; 700*10772807SIgor Kudrin } 701*10772807SIgor Kudrin ArrayRef<uint8_t> OldData = Sec.getContents(); 702*10772807SIgor Kudrin size_t Align = std::max<size_t>(4, Sec.Align); 703*10772807SIgor Kudrin // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the 704*10772807SIgor Kudrin // header, so the parsers are the same. 705*10772807SIgor Kudrin auto ToRemove = (Endianness == endianness::little) 706*10772807SIgor Kudrin ? RemoveNoteDetail::findNotesToRemove<ELF64LE>( 707*10772807SIgor Kudrin OldData, Align, NotesToRemove) 708*10772807SIgor Kudrin : RemoveNoteDetail::findNotesToRemove<ELF64BE>( 709*10772807SIgor Kudrin OldData, Align, NotesToRemove); 710*10772807SIgor Kudrin if (!ToRemove.empty()) { 711*10772807SIgor Kudrin if (Error E = Obj.updateSectionData( 712*10772807SIgor Kudrin Sec, RemoveNoteDetail::updateData(OldData, ToRemove))) 713*10772807SIgor Kudrin return E; 714*10772807SIgor Kudrin } 715*10772807SIgor Kudrin } 716*10772807SIgor Kudrin return Error::success(); 717*10772807SIgor Kudrin } 718*10772807SIgor Kudrin 719f75da0c8SAlexey Lapshin static Error 720a6f3fedcSAlexey Lapshin handleUserSection(const NewSectionInfo &NewSection, 721f75da0c8SAlexey Lapshin function_ref<Error(StringRef, ArrayRef<uint8_t>)> F) { 722a6f3fedcSAlexey Lapshin ArrayRef<uint8_t> Data(reinterpret_cast<const uint8_t *>( 723a6f3fedcSAlexey Lapshin NewSection.SectionData->getBufferStart()), 724a6f3fedcSAlexey Lapshin NewSection.SectionData->getBufferSize()); 725a6f3fedcSAlexey Lapshin return F(NewSection.SectionName, Data); 726f75da0c8SAlexey Lapshin } 727f75da0c8SAlexey Lapshin 728fb5a38bbSserge-sans-paille static Error verifyNoteSection(StringRef Name, endianness Endianness, 729fb5a38bbSserge-sans-paille ArrayRef<uint8_t> Data) { 730fb5a38bbSserge-sans-paille // An ELF note has the following structure: 731fb5a38bbSserge-sans-paille // Name Size: 4 bytes (integer) 732fb5a38bbSserge-sans-paille // Desc Size: 4 bytes (integer) 733fb5a38bbSserge-sans-paille // Type : 4 bytes 734fb5a38bbSserge-sans-paille // Name : variable size, padded to a 4 byte boundary 735fb5a38bbSserge-sans-paille // Desc : variable size, padded to a 4 byte boundary 736fb5a38bbSserge-sans-paille 737fb5a38bbSserge-sans-paille if (Data.empty()) 738fb5a38bbSserge-sans-paille return Error::success(); 739fb5a38bbSserge-sans-paille 740fb5a38bbSserge-sans-paille if (Data.size() < 12) { 741fb5a38bbSserge-sans-paille std::string msg; 742fb5a38bbSserge-sans-paille raw_string_ostream(msg) 743fb5a38bbSserge-sans-paille << Name << " data must be either empty or at least 12 bytes long"; 744fb5a38bbSserge-sans-paille return createStringError(errc::invalid_argument, msg); 745fb5a38bbSserge-sans-paille } 746fb5a38bbSserge-sans-paille if (Data.size() % 4 != 0) { 747fb5a38bbSserge-sans-paille std::string msg; 748fb5a38bbSserge-sans-paille raw_string_ostream(msg) 749fb5a38bbSserge-sans-paille << Name << " data size must be a multiple of 4 bytes"; 750fb5a38bbSserge-sans-paille return createStringError(errc::invalid_argument, msg); 751fb5a38bbSserge-sans-paille } 752fb5a38bbSserge-sans-paille ArrayRef<uint8_t> NameSize = Data.slice(0, 4); 753fb5a38bbSserge-sans-paille ArrayRef<uint8_t> DescSize = Data.slice(4, 4); 754fb5a38bbSserge-sans-paille 755fb5a38bbSserge-sans-paille uint32_t NameSizeValue = support::endian::read32(NameSize.data(), Endianness); 756fb5a38bbSserge-sans-paille uint32_t DescSizeValue = support::endian::read32(DescSize.data(), Endianness); 757fb5a38bbSserge-sans-paille 758fb5a38bbSserge-sans-paille uint64_t ExpectedDataSize = 759fb5a38bbSserge-sans-paille /*NameSize=*/4 + /*DescSize=*/4 + /*Type=*/4 + 760fb5a38bbSserge-sans-paille /*Name=*/alignTo(NameSizeValue, 4) + 761fb5a38bbSserge-sans-paille /*Desc=*/alignTo(DescSizeValue, 4); 762fb5a38bbSserge-sans-paille uint64_t ActualDataSize = Data.size(); 763fb5a38bbSserge-sans-paille if (ActualDataSize != ExpectedDataSize) { 764fb5a38bbSserge-sans-paille std::string msg; 765fb5a38bbSserge-sans-paille raw_string_ostream(msg) 766fb5a38bbSserge-sans-paille << Name 767fb5a38bbSserge-sans-paille << " data size is incompatible with the content of " 768fb5a38bbSserge-sans-paille "the name and description size fields:" 769fb5a38bbSserge-sans-paille << " expecting " << ExpectedDataSize << ", found " << ActualDataSize; 770fb5a38bbSserge-sans-paille return createStringError(errc::invalid_argument, msg); 771fb5a38bbSserge-sans-paille } 772fb5a38bbSserge-sans-paille 773fb5a38bbSserge-sans-paille return Error::success(); 774fb5a38bbSserge-sans-paille } 775fb5a38bbSserge-sans-paille 776f75da0c8SAlexey Lapshin // This function handles the high level operations of GNU objcopy including 777f75da0c8SAlexey Lapshin // handling command line options. It's important to outline certain properties 778f75da0c8SAlexey Lapshin // we expect to hold of the command line operations. Any operation that "keeps" 779f75da0c8SAlexey Lapshin // should keep regardless of a remove. Additionally any removal should respect 780f75da0c8SAlexey Lapshin // any previous removals. Lastly whether or not something is removed shouldn't 781f75da0c8SAlexey Lapshin // depend a) on the order the options occur in or b) on some opaque priority 782f75da0c8SAlexey Lapshin // system. The only priority is that keeps/copies overrule removes. 783f75da0c8SAlexey Lapshin static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig, 784fb5a38bbSserge-sans-paille ElfType OutputElfType, Object &Obj) { 785f75da0c8SAlexey Lapshin if (Config.OutputArch) { 78667ba5c50SFangrui Song Obj.Machine = Config.OutputArch->EMachine; 78767ba5c50SFangrui Song Obj.OSABI = Config.OutputArch->OSABI; 788f75da0c8SAlexey Lapshin } 789f75da0c8SAlexey Lapshin 790f75da0c8SAlexey Lapshin if (!Config.SplitDWO.empty() && Config.ExtractDWO) { 791f75da0c8SAlexey Lapshin return Obj.removeSections( 792f75da0c8SAlexey Lapshin ELFConfig.AllowBrokenLinks, 793f75da0c8SAlexey Lapshin [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); }); 794f75da0c8SAlexey Lapshin } 795f75da0c8SAlexey Lapshin 796f75da0c8SAlexey Lapshin // Dump sections before add/remove for compatibility with GNU objcopy. 797f75da0c8SAlexey Lapshin for (StringRef Flag : Config.DumpSection) { 798f75da0c8SAlexey Lapshin StringRef SectionName; 799f75da0c8SAlexey Lapshin StringRef FileName; 800f75da0c8SAlexey Lapshin std::tie(SectionName, FileName) = Flag.split('='); 801f75da0c8SAlexey Lapshin if (Error E = dumpSectionToFile(SectionName, FileName, Obj)) 802f75da0c8SAlexey Lapshin return E; 803f75da0c8SAlexey Lapshin } 804f75da0c8SAlexey Lapshin 805f75da0c8SAlexey Lapshin // It is important to remove the sections first. For example, we want to 806f75da0c8SAlexey Lapshin // remove the relocation sections before removing the symbols. That allows 807f75da0c8SAlexey Lapshin // us to avoid reporting the inappropriate errors about removing symbols 808f75da0c8SAlexey Lapshin // named in relocations. 809f75da0c8SAlexey Lapshin if (Error E = replaceAndRemoveSections(Config, ELFConfig, Obj)) 810f75da0c8SAlexey Lapshin return E; 811f75da0c8SAlexey Lapshin 812f75da0c8SAlexey Lapshin if (Error E = updateAndRemoveSymbols(Config, ELFConfig, Obj)) 813f75da0c8SAlexey Lapshin return E; 814f75da0c8SAlexey Lapshin 8157c03b7d6SFangrui Song if (!Config.SetSectionAlignment.empty()) { 8167c03b7d6SFangrui Song for (SectionBase &Sec : Obj.sections()) { 8177c03b7d6SFangrui Song auto I = Config.SetSectionAlignment.find(Sec.Name); 8187c03b7d6SFangrui Song if (I != Config.SetSectionAlignment.end()) 8197c03b7d6SFangrui Song Sec.Align = I->second; 8207c03b7d6SFangrui Song } 8217c03b7d6SFangrui Song } 8227c03b7d6SFangrui Song 82333200363SEleanor Bonnici if (Config.ChangeSectionLMAValAll != 0) { 82433200363SEleanor Bonnici for (Segment &Seg : Obj.segments()) { 82533200363SEleanor Bonnici if (Seg.FileSize > 0) { 82633200363SEleanor Bonnici if (Config.ChangeSectionLMAValAll > 0 && 82733200363SEleanor Bonnici Seg.PAddr > std::numeric_limits<uint64_t>::max() - 82833200363SEleanor Bonnici Config.ChangeSectionLMAValAll) { 82933200363SEleanor Bonnici return createStringError( 83033200363SEleanor Bonnici errc::invalid_argument, 83133200363SEleanor Bonnici "address 0x" + Twine::utohexstr(Seg.PAddr) + 83233200363SEleanor Bonnici " cannot be increased by 0x" + 83333200363SEleanor Bonnici Twine::utohexstr(Config.ChangeSectionLMAValAll) + 83433200363SEleanor Bonnici ". The result would overflow"); 83533200363SEleanor Bonnici } else if (Config.ChangeSectionLMAValAll < 0 && 83633200363SEleanor Bonnici Seg.PAddr < std::numeric_limits<uint64_t>::min() - 83733200363SEleanor Bonnici Config.ChangeSectionLMAValAll) { 83833200363SEleanor Bonnici return createStringError( 83933200363SEleanor Bonnici errc::invalid_argument, 84033200363SEleanor Bonnici "address 0x" + Twine::utohexstr(Seg.PAddr) + 84133200363SEleanor Bonnici " cannot be decreased by 0x" + 84233200363SEleanor Bonnici Twine::utohexstr(std::abs(Config.ChangeSectionLMAValAll)) + 84333200363SEleanor Bonnici ". The result would underflow"); 84433200363SEleanor Bonnici } 84533200363SEleanor Bonnici Seg.PAddr += Config.ChangeSectionLMAValAll; 84633200363SEleanor Bonnici } 84733200363SEleanor Bonnici } 84833200363SEleanor Bonnici } 84933200363SEleanor Bonnici 8502b2f4ae0SEleanor Bonnici if (!Config.ChangeSectionAddress.empty()) { 8512b2f4ae0SEleanor Bonnici if (Obj.Type != ELF::ET_REL) 8522b2f4ae0SEleanor Bonnici return createStringError( 8532b2f4ae0SEleanor Bonnici object_error::invalid_file_type, 8542b2f4ae0SEleanor Bonnici "cannot change section address in a non-relocatable file"); 8552b2f4ae0SEleanor Bonnici 8562b2f4ae0SEleanor Bonnici StringMap<AddressUpdate> SectionsToUpdateAddress; 8572b2f4ae0SEleanor Bonnici for (const SectionPatternAddressUpdate &PatternUpdate : 8582b2f4ae0SEleanor Bonnici make_range(Config.ChangeSectionAddress.rbegin(), 8592b2f4ae0SEleanor Bonnici Config.ChangeSectionAddress.rend())) { 8602b2f4ae0SEleanor Bonnici for (SectionBase &Sec : Obj.sections()) { 8612b2f4ae0SEleanor Bonnici if (PatternUpdate.SectionPattern.matches(Sec.Name) && 8622b2f4ae0SEleanor Bonnici SectionsToUpdateAddress.try_emplace(Sec.Name, PatternUpdate.Update) 8632b2f4ae0SEleanor Bonnici .second) { 8642b2f4ae0SEleanor Bonnici if (PatternUpdate.Update.Kind == AdjustKind::Subtract && 8652b2f4ae0SEleanor Bonnici Sec.Addr < PatternUpdate.Update.Value) { 8662b2f4ae0SEleanor Bonnici return createStringError( 8672b2f4ae0SEleanor Bonnici errc::invalid_argument, 8682b2f4ae0SEleanor Bonnici "address 0x" + Twine::utohexstr(Sec.Addr) + 8692b2f4ae0SEleanor Bonnici " cannot be decreased by 0x" + 8702b2f4ae0SEleanor Bonnici Twine::utohexstr(PatternUpdate.Update.Value) + 8712b2f4ae0SEleanor Bonnici ". The result would underflow"); 8722b2f4ae0SEleanor Bonnici } 8732b2f4ae0SEleanor Bonnici if (PatternUpdate.Update.Kind == AdjustKind::Add && 8742b2f4ae0SEleanor Bonnici Sec.Addr > std::numeric_limits<uint64_t>::max() - 8752b2f4ae0SEleanor Bonnici PatternUpdate.Update.Value) { 8762b2f4ae0SEleanor Bonnici return createStringError( 8772b2f4ae0SEleanor Bonnici errc::invalid_argument, 8782b2f4ae0SEleanor Bonnici "address 0x" + Twine::utohexstr(Sec.Addr) + 8792b2f4ae0SEleanor Bonnici " cannot be increased by 0x" + 8802b2f4ae0SEleanor Bonnici Twine::utohexstr(PatternUpdate.Update.Value) + 8812b2f4ae0SEleanor Bonnici ". The result would overflow"); 8822b2f4ae0SEleanor Bonnici } 8832b2f4ae0SEleanor Bonnici 8842b2f4ae0SEleanor Bonnici switch (PatternUpdate.Update.Kind) { 8852b2f4ae0SEleanor Bonnici case (AdjustKind::Set): 8862b2f4ae0SEleanor Bonnici Sec.Addr = PatternUpdate.Update.Value; 8872b2f4ae0SEleanor Bonnici break; 8882b2f4ae0SEleanor Bonnici case (AdjustKind::Subtract): 8892b2f4ae0SEleanor Bonnici Sec.Addr -= PatternUpdate.Update.Value; 8902b2f4ae0SEleanor Bonnici break; 8912b2f4ae0SEleanor Bonnici case (AdjustKind::Add): 8922b2f4ae0SEleanor Bonnici Sec.Addr += PatternUpdate.Update.Value; 8932b2f4ae0SEleanor Bonnici break; 8942b2f4ae0SEleanor Bonnici } 8952b2f4ae0SEleanor Bonnici } 8962b2f4ae0SEleanor Bonnici } 8972b2f4ae0SEleanor Bonnici } 8982b2f4ae0SEleanor Bonnici } 8992b2f4ae0SEleanor Bonnici 9007c03b7d6SFangrui Song if (Config.OnlyKeepDebug) 9017c03b7d6SFangrui Song for (auto &Sec : Obj.sections()) 9027c03b7d6SFangrui Song if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE) 9037c03b7d6SFangrui Song Sec.Type = SHT_NOBITS; 9047c03b7d6SFangrui Song 905fb5a38bbSserge-sans-paille endianness E = OutputElfType == ELFT_ELF32LE || OutputElfType == ELFT_ELF64LE 906fb5a38bbSserge-sans-paille ? endianness::little 907fb5a38bbSserge-sans-paille : endianness::big; 908fb5a38bbSserge-sans-paille 909*10772807SIgor Kudrin if (!ELFConfig.NotesToRemove.empty()) { 910*10772807SIgor Kudrin if (Error Err = 911*10772807SIgor Kudrin removeNotes(Obj, E, ELFConfig.NotesToRemove, Config.ErrorCallback)) 912*10772807SIgor Kudrin return Err; 913*10772807SIgor Kudrin } 914*10772807SIgor Kudrin 9157c03b7d6SFangrui Song for (const NewSectionInfo &AddedSection : Config.AddSection) { 916fb5a38bbSserge-sans-paille auto AddSection = [&](StringRef Name, ArrayRef<uint8_t> Data) -> Error { 9177c03b7d6SFangrui Song OwnedDataSection &NewSection = 9187c03b7d6SFangrui Song Obj.addSection<OwnedDataSection>(Name, Data); 919fb5a38bbSserge-sans-paille if (Name.starts_with(".note") && Name != ".note.GNU-stack") { 9207c03b7d6SFangrui Song NewSection.Type = SHT_NOTE; 921fb5a38bbSserge-sans-paille if (ELFConfig.VerifyNoteSections) 922fb5a38bbSserge-sans-paille return verifyNoteSection(Name, E, Data); 923fb5a38bbSserge-sans-paille } 9247c03b7d6SFangrui Song return Error::success(); 9257c03b7d6SFangrui Song }; 9267c03b7d6SFangrui Song if (Error E = handleUserSection(AddedSection, AddSection)) 9277c03b7d6SFangrui Song return E; 9287c03b7d6SFangrui Song } 9297c03b7d6SFangrui Song 9307c03b7d6SFangrui Song for (const NewSectionInfo &NewSection : Config.UpdateSection) { 9317c03b7d6SFangrui Song auto UpdateSection = [&](StringRef Name, ArrayRef<uint8_t> Data) { 9327c03b7d6SFangrui Song return Obj.updateSection(Name, Data); 9337c03b7d6SFangrui Song }; 9347c03b7d6SFangrui Song if (Error E = handleUserSection(NewSection, UpdateSection)) 9357c03b7d6SFangrui Song return E; 9367c03b7d6SFangrui Song } 9377c03b7d6SFangrui Song 9387c03b7d6SFangrui Song if (!Config.AddGnuDebugLink.empty()) 9397c03b7d6SFangrui Song Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink, 9407c03b7d6SFangrui Song Config.GnuDebugLinkCRC32); 9417c03b7d6SFangrui Song 9427c03b7d6SFangrui Song // If the symbol table was previously removed, we need to create a new one 9437c03b7d6SFangrui Song // before adding new symbols. 9447c03b7d6SFangrui Song if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty()) 9457c03b7d6SFangrui Song if (Error E = Obj.addNewSymbolTable()) 9467c03b7d6SFangrui Song return E; 9477c03b7d6SFangrui Song 9487c03b7d6SFangrui Song for (const NewSymbolInfo &SI : Config.SymbolsToAdd) 9497c03b7d6SFangrui Song addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility); 9507c03b7d6SFangrui Song 951b28412d5SFangrui Song // --set-section-{flags,type} work with sections added by --add-section. 952b28412d5SFangrui Song if (!Config.SetSectionFlags.empty() || !Config.SetSectionType.empty()) { 9537c03b7d6SFangrui Song for (auto &Sec : Obj.sections()) { 9547c03b7d6SFangrui Song const auto Iter = Config.SetSectionFlags.find(Sec.Name); 9557c03b7d6SFangrui Song if (Iter != Config.SetSectionFlags.end()) { 9567c03b7d6SFangrui Song const SectionFlagsUpdate &SFU = Iter->second; 9576f1395a1SThomas Köppe if (Error E = setSectionFlagsAndType(Sec, SFU.NewFlags, Obj.Machine)) 9586f1395a1SThomas Köppe return E; 9597c03b7d6SFangrui Song } 960b28412d5SFangrui Song auto It2 = Config.SetSectionType.find(Sec.Name); 961b28412d5SFangrui Song if (It2 != Config.SetSectionType.end()) 962c973123fSAlexey Karyakin setSectionType(Sec, It2->second); 9637c03b7d6SFangrui Song } 9647c03b7d6SFangrui Song } 9657c03b7d6SFangrui Song 966f75da0c8SAlexey Lapshin if (!Config.SectionsToRename.empty()) { 967f75da0c8SAlexey Lapshin std::vector<RelocationSectionBase *> RelocSections; 968f75da0c8SAlexey Lapshin DenseSet<SectionBase *> RenamedSections; 969f75da0c8SAlexey Lapshin for (SectionBase &Sec : Obj.sections()) { 970f75da0c8SAlexey Lapshin auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec); 971f75da0c8SAlexey Lapshin const auto Iter = Config.SectionsToRename.find(Sec.Name); 972f75da0c8SAlexey Lapshin if (Iter != Config.SectionsToRename.end()) { 973f75da0c8SAlexey Lapshin const SectionRename &SR = Iter->second; 974f75da0c8SAlexey Lapshin Sec.Name = std::string(SR.NewName); 9756f1395a1SThomas Köppe if (SR.NewFlags) { 9766f1395a1SThomas Köppe if (Error E = setSectionFlagsAndType(Sec, *SR.NewFlags, Obj.Machine)) 9776f1395a1SThomas Köppe return E; 9786f1395a1SThomas Köppe } 979f75da0c8SAlexey Lapshin RenamedSections.insert(&Sec); 980f75da0c8SAlexey Lapshin } else if (RelocSec && !(Sec.Flags & SHF_ALLOC)) 981f75da0c8SAlexey Lapshin // Postpone processing relocation sections which are not specified in 982f75da0c8SAlexey Lapshin // their explicit '--rename-section' commands until after their target 983f75da0c8SAlexey Lapshin // sections are renamed. 984f75da0c8SAlexey Lapshin // Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be 985f75da0c8SAlexey Lapshin // renamed only explicitly. Otherwise, renaming, for example, '.got.plt' 986f75da0c8SAlexey Lapshin // would affect '.rela.plt', which is not desirable. 987f75da0c8SAlexey Lapshin RelocSections.push_back(RelocSec); 988f75da0c8SAlexey Lapshin } 989f75da0c8SAlexey Lapshin 990f75da0c8SAlexey Lapshin // Rename relocation sections according to their target sections. 991f75da0c8SAlexey Lapshin for (RelocationSectionBase *RelocSec : RelocSections) { 992f75da0c8SAlexey Lapshin auto Iter = RenamedSections.find(RelocSec->getSection()); 993f75da0c8SAlexey Lapshin if (Iter != RenamedSections.end()) 994f75da0c8SAlexey Lapshin RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str(); 995f75da0c8SAlexey Lapshin } 996f75da0c8SAlexey Lapshin } 997f75da0c8SAlexey Lapshin 998f75da0c8SAlexey Lapshin // Add a prefix to allocated sections and their relocation sections. This 999f75da0c8SAlexey Lapshin // should be done after renaming the section by Config.SectionToRename to 1000f75da0c8SAlexey Lapshin // imitate the GNU objcopy behavior. 1001f75da0c8SAlexey Lapshin if (!Config.AllocSectionsPrefix.empty()) { 1002f75da0c8SAlexey Lapshin DenseSet<SectionBase *> PrefixedSections; 1003f75da0c8SAlexey Lapshin for (SectionBase &Sec : Obj.sections()) { 1004f75da0c8SAlexey Lapshin if (Sec.Flags & SHF_ALLOC) { 1005f75da0c8SAlexey Lapshin Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str(); 1006f75da0c8SAlexey Lapshin PrefixedSections.insert(&Sec); 1007f75da0c8SAlexey Lapshin } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) { 1008f75da0c8SAlexey Lapshin // Rename relocation sections associated to the allocated sections. 1009f75da0c8SAlexey Lapshin // For example, if we rename .text to .prefix.text, we also rename 1010f75da0c8SAlexey Lapshin // .rel.text to .rel.prefix.text. 1011f75da0c8SAlexey Lapshin // 1012f75da0c8SAlexey Lapshin // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled 1013f75da0c8SAlexey Lapshin // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not 1014f75da0c8SAlexey Lapshin // .rela.prefix.plt since GNU objcopy does so. 1015f75da0c8SAlexey Lapshin const SectionBase *TargetSec = RelocSec->getSection(); 1016f75da0c8SAlexey Lapshin if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) { 1017f75da0c8SAlexey Lapshin // If the relocation section comes *after* the target section, we 1018f75da0c8SAlexey Lapshin // don't add Config.AllocSectionsPrefix because we've already added 1019f75da0c8SAlexey Lapshin // the prefix to TargetSec->Name. Otherwise, if the relocation 1020f75da0c8SAlexey Lapshin // section comes *before* the target section, we add the prefix. 1021f75da0c8SAlexey Lapshin if (PrefixedSections.count(TargetSec)) 1022f75da0c8SAlexey Lapshin Sec.Name = (RelocSec->getNamePrefix() + TargetSec->Name).str(); 1023f75da0c8SAlexey Lapshin else 1024f75da0c8SAlexey Lapshin Sec.Name = (RelocSec->getNamePrefix() + Config.AllocSectionsPrefix + 1025f75da0c8SAlexey Lapshin TargetSec->Name) 1026f75da0c8SAlexey Lapshin .str(); 1027f75da0c8SAlexey Lapshin } 1028f75da0c8SAlexey Lapshin } 1029f75da0c8SAlexey Lapshin } 1030f75da0c8SAlexey Lapshin } 1031f75da0c8SAlexey Lapshin 1032f75da0c8SAlexey Lapshin if (ELFConfig.EntryExpr) 1033f75da0c8SAlexey Lapshin Obj.Entry = ELFConfig.EntryExpr(Obj.Entry); 1034f75da0c8SAlexey Lapshin return Error::success(); 1035f75da0c8SAlexey Lapshin } 1036f75da0c8SAlexey Lapshin 1037f75da0c8SAlexey Lapshin static Error writeOutput(const CommonConfig &Config, Object &Obj, 1038f75da0c8SAlexey Lapshin raw_ostream &Out, ElfType OutputElfType) { 1039f75da0c8SAlexey Lapshin std::unique_ptr<Writer> Writer = 1040f75da0c8SAlexey Lapshin createWriter(Config, Obj, Out, OutputElfType); 1041f75da0c8SAlexey Lapshin if (Error E = Writer->finalize()) 1042f75da0c8SAlexey Lapshin return E; 1043f75da0c8SAlexey Lapshin return Writer->write(); 1044f75da0c8SAlexey Lapshin } 1045f75da0c8SAlexey Lapshin 1046f75da0c8SAlexey Lapshin Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config, 1047f75da0c8SAlexey Lapshin const ELFConfig &ELFConfig, 1048f75da0c8SAlexey Lapshin MemoryBuffer &In, raw_ostream &Out) { 1049f75da0c8SAlexey Lapshin IHexReader Reader(&In); 1050f75da0c8SAlexey Lapshin Expected<std::unique_ptr<Object>> Obj = Reader.create(true); 1051f75da0c8SAlexey Lapshin if (!Obj) 1052f75da0c8SAlexey Lapshin return Obj.takeError(); 1053f75da0c8SAlexey Lapshin 1054f75da0c8SAlexey Lapshin const ElfType OutputElfType = 1055129b531cSKazu Hirata getOutputElfType(Config.OutputArch.value_or(MachineInfo())); 1056fb5a38bbSserge-sans-paille if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj)) 1057f75da0c8SAlexey Lapshin return E; 1058f75da0c8SAlexey Lapshin return writeOutput(Config, **Obj, Out, OutputElfType); 1059f75da0c8SAlexey Lapshin } 1060f75da0c8SAlexey Lapshin 1061f75da0c8SAlexey Lapshin Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config, 1062f75da0c8SAlexey Lapshin const ELFConfig &ELFConfig, 1063f75da0c8SAlexey Lapshin MemoryBuffer &In, 1064f75da0c8SAlexey Lapshin raw_ostream &Out) { 1065f75da0c8SAlexey Lapshin BinaryReader Reader(&In, ELFConfig.NewSymbolVisibility); 1066f75da0c8SAlexey Lapshin Expected<std::unique_ptr<Object>> Obj = Reader.create(true); 1067f75da0c8SAlexey Lapshin if (!Obj) 1068f75da0c8SAlexey Lapshin return Obj.takeError(); 1069f75da0c8SAlexey Lapshin 1070f75da0c8SAlexey Lapshin // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch 1071f75da0c8SAlexey Lapshin // (-B<arch>). 1072f75da0c8SAlexey Lapshin const ElfType OutputElfType = 1073129b531cSKazu Hirata getOutputElfType(Config.OutputArch.value_or(MachineInfo())); 1074fb5a38bbSserge-sans-paille if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj)) 1075f75da0c8SAlexey Lapshin return E; 1076f75da0c8SAlexey Lapshin return writeOutput(Config, **Obj, Out, OutputElfType); 1077f75da0c8SAlexey Lapshin } 1078f75da0c8SAlexey Lapshin 1079f75da0c8SAlexey Lapshin Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config, 1080f75da0c8SAlexey Lapshin const ELFConfig &ELFConfig, 1081f75da0c8SAlexey Lapshin object::ELFObjectFileBase &In, 1082f75da0c8SAlexey Lapshin raw_ostream &Out) { 1083f75da0c8SAlexey Lapshin ELFReader Reader(&In, Config.ExtractPartition); 1084f75da0c8SAlexey Lapshin Expected<std::unique_ptr<Object>> Obj = 1085f75da0c8SAlexey Lapshin Reader.create(!Config.SymbolsToAdd.empty()); 1086f75da0c8SAlexey Lapshin if (!Obj) 1087f75da0c8SAlexey Lapshin return Obj.takeError(); 1088f75da0c8SAlexey Lapshin // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input. 108967ba5c50SFangrui Song const ElfType OutputElfType = Config.OutputArch 109067ba5c50SFangrui Song ? getOutputElfType(*Config.OutputArch) 1091f75da0c8SAlexey Lapshin : getOutputElfType(In); 1092f75da0c8SAlexey Lapshin 1093fb5a38bbSserge-sans-paille if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj)) 1094f75da0c8SAlexey Lapshin return createFileError(Config.InputFilename, std::move(E)); 1095f75da0c8SAlexey Lapshin 1096f75da0c8SAlexey Lapshin if (Error E = writeOutput(Config, **Obj, Out, OutputElfType)) 1097f75da0c8SAlexey Lapshin return createFileError(Config.InputFilename, std::move(E)); 1098f75da0c8SAlexey Lapshin 1099f75da0c8SAlexey Lapshin return Error::success(); 1100f75da0c8SAlexey Lapshin } 1101