diff options
Diffstat (limited to 'tools/llvm-objcopy/ELF/ELFObjcopy.cpp')
-rw-r--r-- | tools/llvm-objcopy/ELF/ELFObjcopy.cpp | 169 |
1 files changed, 84 insertions, 85 deletions
diff --git a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/tools/llvm-objcopy/ELF/ELFObjcopy.cpp index b366c6e55987..8bf7e0f88010 100644 --- a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ b/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -136,16 +136,16 @@ static std::unique_ptr<Writer> createELFWriter(const CopyConfig &Config, // Depending on the initial ELFT and OutputFormat we need a different Writer. switch (OutputElfType) { case ELFT_ELF32LE: - return llvm::make_unique<ELFWriter<ELF32LE>>(Obj, Buf, + return std::make_unique<ELFWriter<ELF32LE>>(Obj, Buf, !Config.StripSections); case ELFT_ELF64LE: - return llvm::make_unique<ELFWriter<ELF64LE>>(Obj, Buf, + return std::make_unique<ELFWriter<ELF64LE>>(Obj, Buf, !Config.StripSections); case ELFT_ELF32BE: - return llvm::make_unique<ELFWriter<ELF32BE>>(Obj, Buf, + return std::make_unique<ELFWriter<ELF32BE>>(Obj, Buf, !Config.StripSections); case ELFT_ELF64BE: - return llvm::make_unique<ELFWriter<ELF64BE>>(Obj, Buf, + return std::make_unique<ELFWriter<ELF64BE>>(Obj, Buf, !Config.StripSections); } llvm_unreachable("Invalid output format"); @@ -156,9 +156,9 @@ static std::unique_ptr<Writer> createWriter(const CopyConfig &Config, ElfType OutputElfType) { switch (Config.OutputFormat) { case FileFormat::Binary: - return llvm::make_unique<BinaryWriter>(Obj, Buf); + return std::make_unique<BinaryWriter>(Obj, Buf); case FileFormat::IHex: - return llvm::make_unique<IHexWriter>(Obj, Buf); + return std::make_unique<IHexWriter>(Obj, Buf); default: return createELFWriter(Config, Obj, Buf, OutputElfType); } @@ -263,7 +263,7 @@ static Error linkToBuildIdDir(const CopyConfig &Config, StringRef ToLink, static Error splitDWOToFile(const CopyConfig &Config, const Reader &Reader, StringRef File, ElfType OutputElfType) { - auto DWOFile = Reader.create(); + auto DWOFile = Reader.create(false); auto OnlyKeepDWOPred = [&DWOFile](const SectionBase &Sec) { return onlyKeepDWOPred(*DWOFile, Sec); }; @@ -305,9 +305,9 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename, SecName.str().c_str()); } -static bool isCompressable(const SectionBase &Section) { - return !(Section.Flags & ELF::SHF_COMPRESSED) && - StringRef(Section.Name).startswith(".debug"); +static bool isCompressable(const SectionBase &Sec) { + return !(Sec.Flags & ELF::SHF_COMPRESSED) && + StringRef(Sec.Name).startswith(".debug"); } static void replaceDebugSections( @@ -356,7 +356,7 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) { if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF && ((Config.LocalizeHidden && (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || - is_contained(Config.SymbolsToLocalize, Sym.Name))) + Config.SymbolsToLocalize.matches(Sym.Name))) Sym.Binding = STB_LOCAL; // Note: these two globalize flags have very similar names but different @@ -370,16 +370,15 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) { // --keep-global-symbol. Because of that, make sure to check // --globalize-symbol second. if (!Config.SymbolsToKeepGlobal.empty() && - !is_contained(Config.SymbolsToKeepGlobal, Sym.Name) && + !Config.SymbolsToKeepGlobal.matches(Sym.Name) && Sym.getShndx() != SHN_UNDEF) Sym.Binding = STB_LOCAL; - if (is_contained(Config.SymbolsToGlobalize, Sym.Name) && + if (Config.SymbolsToGlobalize.matches(Sym.Name) && Sym.getShndx() != SHN_UNDEF) Sym.Binding = STB_GLOBAL; - if (is_contained(Config.SymbolsToWeaken, Sym.Name) && - Sym.Binding == STB_GLOBAL) + if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding == STB_GLOBAL) Sym.Binding = STB_WEAK; if (Config.Weaken && Sym.Binding == STB_GLOBAL && @@ -399,12 +398,12 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) { // symbols are still 'needed' and which are not. if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() || !Config.OnlySection.empty()) { - for (auto &Section : Obj.sections()) - Section.markSymbols(); + for (SectionBase &Sec : Obj.sections()) + Sec.markSymbols(); } auto RemoveSymbolsPred = [&](const Symbol &Sym) { - if (is_contained(Config.SymbolsToKeep, Sym.Name) || + if (Config.SymbolsToKeep.matches(Sym.Name) || (Config.KeepFileSymbols && Sym.Type == STT_FILE)) return false; @@ -418,12 +417,12 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) { if (Config.StripAll || Config.StripAllGNU) return true; - if (is_contained(Config.SymbolsToRemove, Sym.Name)) + if (Config.SymbolsToRemove.matches(Sym.Name)) return true; if ((Config.StripUnneeded || - is_contained(Config.UnneededSymbolsToRemove, Sym.Name)) && - isUnneededSymbol(Sym)) + Config.UnneededSymbolsToRemove.matches(Sym.Name)) && + (!Obj.isRelocatable() || isUnneededSymbol(Sym))) return true; // We want to remove undefined symbols if all references have been stripped. @@ -443,7 +442,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) { // Removes: if (!Config.ToRemove.empty()) { RemovePred = [&Config](const SectionBase &Sec) { - return is_contained(Config.ToRemove, Sec.Name); + return Config.ToRemove.matches(Sec.Name); }; } @@ -481,7 +480,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) { }; } - if (Config.StripDebug) { + if (Config.StripDebug || Config.StripUnneeded) { RemovePred = [RemovePred](const SectionBase &Sec) { return RemovePred(Sec) || isDebugSection(Sec); }; @@ -523,7 +522,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) { if (!Config.OnlySection.empty()) { RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) { // Explicitly keep these sections regardless of previous removes. - if (is_contained(Config.OnlySection, Sec.Name)) + if (Config.OnlySection.matches(Sec.Name)) return false; // Allow all implicit removes. @@ -545,7 +544,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) { if (!Config.KeepSection.empty()) { RemovePred = [&Config, RemovePred](const SectionBase &Sec) { // Explicitly keep these sections regardless of previous removes. - if (is_contained(Config.KeepSection, Sec.Name)) + if (Config.KeepSection.matches(Sec.Name)) return false; // Otherwise defer to RemovePred. return RemovePred(Sec); @@ -614,9 +613,8 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj, if (Error E = updateAndRemoveSymbols(Config, Obj)) return E; - if (!Config.SectionsToRename.empty() || !Config.AllocSectionsPrefix.empty()) { - DenseSet<SectionBase *> PrefixedSections; - for (auto &Sec : Obj.sections()) { + if (!Config.SectionsToRename.empty()) { + for (SectionBase &Sec : Obj.sections()) { const auto Iter = Config.SectionsToRename.find(Sec.Name); if (Iter != Config.SectionsToRename.end()) { const SectionRename &SR = Iter->second; @@ -624,63 +622,62 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj, if (SR.NewFlags.hasValue()) setSectionFlagsAndType(Sec, SR.NewFlags.getValue()); } + } + } - // Add a prefix to allocated sections and their relocation sections. This - // should be done after renaming the section by Config.SectionToRename to - // imitate the GNU objcopy behavior. - if (!Config.AllocSectionsPrefix.empty()) { - if (Sec.Flags & SHF_ALLOC) { - Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str(); - PrefixedSections.insert(&Sec); - - // Rename relocation sections associated to the allocated sections. - // For example, if we rename .text to .prefix.text, we also rename - // .rel.text to .rel.prefix.text. - // - // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled - // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not - // .rela.prefix.plt since GNU objcopy does so. - } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) { - auto *TargetSec = RelocSec->getSection(); - if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) { - StringRef prefix; - switch (Sec.Type) { - case SHT_REL: - prefix = ".rel"; - break; - case SHT_RELA: - prefix = ".rela"; - break; - default: - continue; - } - - // If the relocation section comes *after* the target section, we - // don't add Config.AllocSectionsPrefix because we've already added - // the prefix to TargetSec->Name. Otherwise, if the relocation - // section comes *before* the target section, we add the prefix. - if (PrefixedSections.count(TargetSec)) { - Sec.Name = (prefix + TargetSec->Name).str(); - } else { - const auto Iter = Config.SectionsToRename.find(TargetSec->Name); - if (Iter != Config.SectionsToRename.end()) { - // Both `--rename-section` and `--prefix-alloc-sections` are - // given but the target section is not yet renamed. - Sec.Name = - (prefix + Config.AllocSectionsPrefix + Iter->second.NewName) - .str(); - } else { - Sec.Name = - (prefix + Config.AllocSectionsPrefix + TargetSec->Name) - .str(); - } - } + // Add a prefix to allocated sections and their relocation sections. This + // should be done after renaming the section by Config.SectionToRename to + // imitate the GNU objcopy behavior. + if (!Config.AllocSectionsPrefix.empty()) { + DenseSet<SectionBase *> PrefixedSections; + for (SectionBase &Sec : Obj.sections()) { + if (Sec.Flags & SHF_ALLOC) { + Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str(); + PrefixedSections.insert(&Sec); + } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) { + // Rename relocation sections associated to the allocated sections. + // For example, if we rename .text to .prefix.text, we also rename + // .rel.text to .rel.prefix.text. + // + // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled + // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not + // .rela.prefix.plt since GNU objcopy does so. + const SectionBase *TargetSec = RelocSec->getSection(); + if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) { + StringRef prefix; + switch (Sec.Type) { + case SHT_REL: + prefix = ".rel"; + break; + case SHT_RELA: + prefix = ".rela"; + break; + default: + llvm_unreachable("not a relocation section"); } + + // If the relocation section comes *after* the target section, we + // don't add Config.AllocSectionsPrefix because we've already added + // the prefix to TargetSec->Name. Otherwise, if the relocation + // section comes *before* the target section, we add the prefix. + if (PrefixedSections.count(TargetSec)) + Sec.Name = (prefix + TargetSec->Name).str(); + else + Sec.Name = + (prefix + Config.AllocSectionsPrefix + TargetSec->Name).str(); } } } } + if (!Config.SetSectionAlignment.empty()) { + for (SectionBase &Sec : Obj.sections()) { + auto I = Config.SetSectionAlignment.find(Sec.Name); + if (I != Config.SetSectionAlignment.end()) + Sec.Align = I->second; + } + } + if (!Config.SetSectionFlags.empty()) { for (auto &Sec : Obj.sections()) { const auto Iter = Config.SetSectionFlags.find(Sec.Name); @@ -721,7 +718,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj, Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink, Config.GnuDebugLinkCRC32); - for (const NewSymbolInfo &SI : Config.SymbolsToAdd) { + for (const NewSymbolInfo &SI : Config.ELF->SymbolsToAdd) { SectionBase *Sec = Obj.findSection(SI.SectionName); uint64_t Value = Sec ? Sec->Addr + SI.Value : SI.Value; Obj.SymbolTable->addSymbol( @@ -746,9 +743,9 @@ static Error writeOutput(const CopyConfig &Config, Object &Obj, Buffer &Out, Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In, Buffer &Out) { IHexReader Reader(&In); - std::unique_ptr<Object> Obj = Reader.create(); + std::unique_ptr<Object> Obj = Reader.create(true); const ElfType OutputElfType = - getOutputElfType(Config.OutputArch.getValueOr(Config.BinaryArch)); + getOutputElfType(Config.OutputArch.getValueOr(MachineInfo())); if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType)) return E; return writeOutput(Config, *Obj, Out, OutputElfType); @@ -756,13 +753,15 @@ Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In, Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In, Buffer &Out) { - BinaryReader Reader(Config.BinaryArch, &In); - std::unique_ptr<Object> Obj = Reader.create(); + uint8_t NewSymbolVisibility = + Config.ELF->NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT); + BinaryReader Reader(&In, NewSymbolVisibility); + std::unique_ptr<Object> Obj = Reader.create(true); // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch // (-B<arch>). const ElfType OutputElfType = - getOutputElfType(Config.OutputArch.getValueOr(Config.BinaryArch)); + getOutputElfType(Config.OutputArch.getValueOr(MachineInfo())); if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType)) return E; return writeOutput(Config, *Obj, Out, OutputElfType); @@ -771,7 +770,7 @@ Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In, Error executeObjcopyOnBinary(const CopyConfig &Config, object::ELFObjectFileBase &In, Buffer &Out) { ELFReader Reader(&In, Config.ExtractPartition); - std::unique_ptr<Object> Obj = Reader.create(); + std::unique_ptr<Object> Obj = Reader.create(!Config.SymbolsToAdd.empty()); // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input. const ElfType OutputElfType = Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue()) |