[llvm-objcopy] Add --prefix-alloc-sections

This patch adds support for --prefix-alloc-sections, which adds a prefix
to every allocated section names.

It adds a prefix after renaming section names by --rename-section as GNU
objcopy does.

Fixes PR41266: https://bugs.llvm.org/show_bug.cgi?id=41266

Differential Revision: https://reviews.llvm.org/D60042

Patch by Seiya Nuta.

llvm-svn: 360233
This commit is contained in:
James Henderson 2019-05-08 09:49:35 +00:00
parent cf5cd7dbe8
commit 5f4b241a54
8 changed files with 146 additions and 10 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -177,15 +177,15 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
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,

View File

@ -499,6 +499,8 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
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('='))

View File

@ -120,6 +120,7 @@ struct CopyConfig {
Optional<StringRef> BuildIdLinkOutput;
StringRef SplitDWO;
StringRef SymbolsPrefix;
StringRef AllocSectionsPrefix;
DiscardType DiscardMode = DiscardType::None;
// Repeated options

View File

@ -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 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
if (Error E = updateAndRemoveSymbols(Config, Obj))
return E;
if (!Config.SectionsToRename.empty()) {
if (!Config.SectionsToRename.empty() || !Config.AllocSectionsPrefix.empty()) {
DenseSet<SectionBase *> PrefixedSections;
for (auto &Sec : Obj.sections()) {
const auto Iter = Config.SectionsToRename.find(Sec.Name);
if (Iter != Config.SectionsToRename.end()) {
@ -589,6 +591,60 @@ 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();
}
}
}
}
}
}
}

View File

@ -238,6 +238,10 @@ defm prefix_symbols
: Eq<"prefix-symbols", "Add <prefix> to the start of every symbol name">,
MetaVarName<"prefix">;
defm prefix_alloc_sections
: Eq<"prefix-alloc-sections", "Add <prefix> 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<version>;