Index: llvm/trunk/test/tools/llvm-objcopy/ELF/prefix-alloc-sections-dynrelocsec.test =================================================================== --- llvm/trunk/test/tools/llvm-objcopy/ELF/prefix-alloc-sections-dynrelocsec.test +++ llvm/trunk/test/tools/llvm-objcopy/ELF/prefix-alloc-sections-dynrelocsec.test @@ -0,0 +1,5 @@ +# RUN: llvm-objcopy --prefix-alloc-sections=.prefix %p/Inputs/dynrel.elf %t +# RUN: llvm-readobj --sections %t | FileCheck %s + +# CHECK: Name: .prefix.rela.plt +# CHECK: Name: .prefix.plt Index: llvm/trunk/test/tools/llvm-objcopy/ELF/prefix-alloc-sections.test =================================================================== --- llvm/trunk/test/tools/llvm-objcopy/ELF/prefix-alloc-sections.test +++ llvm/trunk/test/tools/llvm-objcopy/ELF/prefix-alloc-sections.test @@ -0,0 +1,36 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objcopy --prefix-alloc-sections=.prefix %t %t2 +# RUN: llvm-readobj --sections %t2 | FileCheck %s + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Flags: [ ] + - Name: .prefix.already_prefixed + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + - Name: .rel.text + Type: SHT_REL + Info: .text + - Name: .rela.data + Type: SHT_RELA + Info: .data + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + +# CHECK: Name: .foo +# CHECK: Name: .prefix.prefix.already_prefixed +# CHECK: Name: .prefix.text +# CHECK: Name: .rel.prefix.text +# CHECK: Name: .rela.prefix.data +# CHECK: Name: .prefix.data Index: llvm/trunk/test/tools/llvm-objcopy/ELF/rename-section-and-prefix-alloc-sections.test =================================================================== --- llvm/trunk/test/tools/llvm-objcopy/ELF/rename-section-and-prefix-alloc-sections.test +++ llvm/trunk/test/tools/llvm-objcopy/ELF/rename-section-and-prefix-alloc-sections.test @@ -0,0 +1,32 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objcopy --rename-section=.text=.text2 --rename-section=.data=.data2 --prefix-alloc-sections=.prefix %t %t2 +# RUN: llvm-readobj --sections %t2 | FileCheck %s + +# .text/.rel.text and .data/.rela.data are the cases when the relocation section +# comes after/before its target section respectively. We handle them in different +# ways to perform both --rename-section and --prefix-alloc-sections in one pass. + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + - Name: .rel.text + Type: SHT_REL + Info: .text + - Name: .rela.data + Type: SHT_RELA + Info: .data + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + +# CHECK: Name: .prefix.text2 +# CHECK: Name: .rel.prefix.text2 +# CHECK: Name: .rela.prefix.data2 +# CHECK: Name: .prefix.data2 Index: llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp @@ -177,15 +177,15 @@ if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() || Config.BuildIdLinkInput || Config.BuildIdLinkOutput || !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() || - !Config.AddSection.empty() || !Config.DumpSection.empty() || - !Config.KeepSection.empty() || !Config.SymbolsToGlobalize.empty() || - !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() || - !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() || - !Config.SectionsToRename.empty() || !Config.SetSectionFlags.empty() || - !Config.SymbolsToRename.empty() || Config.ExtractDWO || - Config.KeepFileSymbols || Config.LocalizeHidden || Config.PreserveDates || - Config.StripDWO || Config.StripNonAlloc || Config.StripSections || - Config.Weaken || Config.DecompressDebugSections || + !Config.AllocSectionsPrefix.empty() || !Config.AddSection.empty() || + !Config.DumpSection.empty() || !Config.KeepSection.empty() || + !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() || + !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() || + !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || + !Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty() || + Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden || + Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc || + Config.StripSections || Config.Weaken || Config.DecompressDebugSections || Config.DiscardMode == DiscardType::Locals || !Config.SymbolsToAdd.empty() || Config.EntryExpr) { return createStringError(llvm::errc::invalid_argument, Index: llvm/trunk/tools/llvm-objcopy/CopyConfig.h =================================================================== --- llvm/trunk/tools/llvm-objcopy/CopyConfig.h +++ llvm/trunk/tools/llvm-objcopy/CopyConfig.h @@ -120,6 +120,7 @@ Optional BuildIdLinkOutput; StringRef SplitDWO; StringRef SymbolsPrefix; + StringRef AllocSectionsPrefix; DiscardType DiscardMode = DiscardType::None; // Repeated options Index: llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp +++ llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp @@ -499,6 +499,8 @@ InputArgs.getLastArgValue(OBJCOPY_build_id_link_output); Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols); + Config.AllocSectionsPrefix = + InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections); for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) { if (!StringRef(Arg->getValue()).contains('=')) Index: llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -13,6 +13,7 @@ #include "llvm-objcopy.h" #include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -580,7 +581,8 @@ if (Error E = updateAndRemoveSymbols(Config, Obj)) return E; - if (!Config.SectionsToRename.empty()) { + if (!Config.SectionsToRename.empty() || !Config.AllocSectionsPrefix.empty()) { + DenseSet PrefixedSections; for (auto &Sec : Obj.sections()) { const auto Iter = Config.SectionsToRename.find(Sec.Name); if (Iter != Config.SectionsToRename.end()) { @@ -589,6 +591,60 @@ 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(&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(); + } + } + } + } + } } } Index: llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td =================================================================== --- llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td +++ llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td @@ -238,6 +238,10 @@ : Eq<"prefix-symbols", "Add to the start of every symbol name">, MetaVarName<"prefix">; +defm prefix_alloc_sections + : Eq<"prefix-alloc-sections", "Add to the start of every allocated section name">, + MetaVarName<"prefix">; + def version : Flag<["--"], "version">, HelpText<"Print the version and exit.">; def V : Flag<["-"], "V">, Alias;