Index: test/tools/llvm-objcopy/rename-section-flag.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/rename-section-flag.test @@ -0,0 +1,103 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objcopy --rename-section=.foo=.bar,alloc %t %t.alloc +# RUN: llvm-readobj -sections %t.alloc | FileCheck %s --check-prefix=ALLOC +# RUN: llvm-objcopy --rename-section=.foo=.bar,load %t %t.load +# RUN: llvm-readobj -sections %t.load | FileCheck %s --check-prefix=LOAD +# RUN: llvm-objcopy --rename-section=.foo=.bar,noload %t %t.noload +# RUN: llvm-readobj -sections %t.noload | FileCheck %s --check-prefix=NOLOAD +# RUN: llvm-objcopy --rename-section=.foo=.bar,readonly %t %t.readonly +# RUN: llvm-readobj -sections %t.readonly | FileCheck %s --check-prefix=READONLY +# RUN: llvm-objcopy --rename-section=.foo=.bar,debug %t %t.debug +# RUN: llvm-readobj -sections %t.debug | FileCheck %s --check-prefix=DEBUG +# RUN: llvm-objcopy --rename-section=.foo=.bar,code %t %t.code +# RUN: llvm-readobj -sections %t.code | FileCheck %s --check-prefix=CODE +# RUN: llvm-objcopy --rename-section=.foo=.bar,data %t %t.data +# RUN: llvm-readobj -sections %t.data | FileCheck %s --check-prefix=DATA +# RUN: llvm-objcopy --rename-section=.foo=.bar,rom %t %t.rom +# RUN: llvm-readobj -sections %t.rom | FileCheck %s --check-prefix=ROM +# RUN: llvm-objcopy --rename-section=.foo=.bar,contents %t %t.contents +# RUN: llvm-readobj -sections %t.contents | FileCheck %s --check-prefix=CONTENTS +# RUN: llvm-objcopy --rename-section=.foo=.bar,merge %t %t.merge +# RUN: llvm-readobj -sections %t.merge | FileCheck %s --check-prefix=MERGE +# RUN: llvm-objcopy --rename-section=.foo=.bar,strings %t %t.strings +# RUN: llvm-readobj -sections %t.strings | FileCheck %s --check-prefix=STRINGS +# RUN: llvm-objcopy --rename-section=.foo=.bar,share %t %t.share +# RUN: llvm-readobj -sections %t.share | FileCheck %s --check-prefix=SHARE +# RUN: not llvm-objcopy --rename-section=.foo=.bar,xyzzy %t %t.xyzzy 2>&1 | FileCheck %s --check-prefix=BAD-FLAG + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Content: "c3c3c3c3" + +# ALLOC: Name: .bar +# ALLOC-NEXT: Type: SHT_PROGBITS +# ALLOC-NEXT: Flags [ (0x3) +# ALLOC-NEXT: SHF_ALLOC (0x2) +# ALLOC-NEXT: SHF_WRITE (0x1) +# ALLOC-NEXT: ] +# LOAD: Name: .bar +# LOAD-NEXT: Type: SHT_PROGBITS +# LOAD-NEXT: Flags [ (0x1) +# LOAD-NEXT: SHF_WRITE (0x1) +# LOAD-NEXT: ] +# NOLOAD: Name: .bar +# NOLOAD-NEXT: Type: SHT_PROGBITS +# NOLOAD-NEXT: Flags [ (0x1) +# NOLOAD-NEXT: SHF_WRITE (0x1) +# NOLOAD-NEXT: ] +# READONLY: Name: .bar +# READONLY-NEXT: Type: SHT_PROGBITS +# READONLY-NEXT: Flags [ (0x0) +# READONLY-NEXT: ] +# DEBUG: Name: .bar +# DEBUG-NEXT: Type: SHT_PROGBITS +# DEBUG-NEXT: Flags [ (0x1) +# DEBUG-NEXT: SHF_WRITE (0x1) +# DEBUG-NEXT: ] +# CODE: Name: .bar +# CODE-NEXT: Type: SHT_PROGBITS +# CODE-NEXT: Flags [ (0x5) +# CODE-NEXT: SHF_EXECINSTR (0x4) +# CODE-NEXT: SHF_WRITE (0x1) +# CODE-NEXT: ] +# DATA: Name: .bar +# DATA-NEXT: Type: SHT_PROGBITS +# DATA-NEXT: Flags [ (0x1) +# DATA-NEXT: SHF_WRITE (0x1) +# DATA-NEXT: ] +# ROM: Name: .bar +# ROM-NEXT: Type: SHT_PROGBITS +# ROM-NEXT: Flags [ (0x1) +# ROM-NEXT: SHF_WRITE (0x1) +# ROM-NEXT: ] +# CONTENTS: Name: .bar +# CONTENTS-NEXT: Type: SHT_PROGBITS +# CONTENTS-NEXT: Flags [ (0x1) +# CONTENTS-NEXT: SHF_WRITE (0x1) +# CONTENTS-NEXT: ] +# MERGE: Name: .bar +# MERGE-NEXT: Type: SHT_PROGBITS +# MERGE-NEXT: Flags [ (0x11) +# MERGE-NEXT: SHF_MERGE (0x10) +# MERGE-NEXT: SHF_WRITE (0x1) +# MERGE-NEXT: ] +# STRINGS: Name: .bar +# STRINGS-NEXT: Type: SHT_PROGBITS +# STRINGS-NEXT: Flags [ (0x21) +# STRINGS-NEXT: SHF_STRINGS (0x20) +# STRINGS-NEXT: SHF_WRITE (0x1) +# STRINGS-NEXT: ] +# SHARE: Name: .bar +# SHARE-NEXT: Type: SHT_PROGBITS +# SHARE-NEXT: Flags [ (0x1) +# SHARE-NEXT: SHF_WRITE (0x1) +# SHARE-NEXT: ] +# BAD-FLAG: Unknown flag type: xyzzy. Index: tools/llvm-objcopy/ObjcopyOpts.td =================================================================== --- tools/llvm-objcopy/ObjcopyOpts.td +++ tools/llvm-objcopy/ObjcopyOpts.td @@ -28,8 +28,8 @@ MetaVarName<"section">, HelpText<"Remove
">; defm rename_section : Eq<"rename-section">, - MetaVarName<"old=new">, - HelpText<"Renames a section from old to new">; + MetaVarName<"old=new[,flag1,...]">, + HelpText<"Renames a section from old to new, optionally with specified flags">; defm redefine_symbol : Eq<"redefine-sym">, MetaVarName<"old=new">, HelpText<"Change the name of a symbol old to new">; Index: tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- tools/llvm-objcopy/llvm-objcopy.cpp +++ tools/llvm-objcopy/llvm-objcopy.cpp @@ -9,7 +9,10 @@ #include "llvm-objcopy.h" #include "Object.h" +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/ELF.h" @@ -115,6 +118,11 @@ StripOptTable() : OptTable(StripInfoTable, true) {} }; +struct SectionRenameConfig { + StringRef NewName; + Optional NewFlags; +}; + struct CopyConfig { StringRef OutputFilename; StringRef InputFilename; @@ -133,7 +141,7 @@ std::vector SymbolsToWeaken; std::vector SymbolsToRemove; std::vector SymbolsToKeep; - StringMap SectionsToRename; + StringMap SectionsToRename; StringMap SymbolsToRename; bool StripAll = false; bool StripAllGNU = false; @@ -185,6 +193,40 @@ } // end namespace objcopy } // end namespace llvm +enum SectionFlag { + SecNone = 0, + SecAlloc = 1 << 0, + SecLoad = 1 << 1, + SecNoload = 1 << 2, + SecReadonly = 1 << 3, + SecDebug = 1 << 4, + SecCode = 1 << 5, + SecData = 1 << 6, + SecRom = 1 << 7, + SecMerge = 1 << 8, + SecStrings = 1 << 9, + SecContents = 1 << 10, + SecShare = 1 << 11, + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ SecShare) +}; + +static SectionFlag ParseSectionName(StringRef SectionName) { + return llvm::StringSwitch(SectionName) + .Case("alloc", SectionFlag::SecAlloc) + .Case("load", SectionFlag::SecLoad) + .Case("noload", SectionFlag::SecNoload) + .Case("readonly", SectionFlag::SecReadonly) + .Case("debug", SectionFlag::SecDebug) + .Case("code", SectionFlag::SecCode) + .Case("data", SectionFlag::SecData) + .Case("rom", SectionFlag::SecRom) + .Case("merge", SectionFlag::SecMerge) + .Case("strings", SectionFlag::SecStrings) + .Case("contents", SectionFlag::SecContents) + .Case("share", SectionFlag::SecShare) + .Default(SectionFlag::SecNone); +} + static bool IsDWOSection(const SectionBase &Sec) { return Sec.Name.endswith(".dwo"); } @@ -434,8 +476,12 @@ if (!Config.SectionsToRename.empty()) { for (auto &Sec : Obj.sections()) { const auto Iter = Config.SectionsToRename.find(Sec.Name); - if (Iter != Config.SectionsToRename.end()) - Sec.Name = Iter->second; + if (Iter != Config.SectionsToRename.end()) { + auto &SectionConfig = Iter->second; + Sec.Name = SectionConfig.NewName; + if (SectionConfig.NewFlags.hasValue()) + Sec.Flags = SectionConfig.NewFlags.getValue(); + } } } @@ -598,9 +644,40 @@ for (auto Arg : InputArgs.filtered(OBJCOPY_rename_section)) { if (!StringRef(Arg->getValue()).contains('=')) - error("Bad format for --rename-section"); + error("Bad format for --rename-section: expected '='"); + // Initial split: ".foo" = ".bar,f1,f2,..." auto Old2New = StringRef(Arg->getValue()).split('='); - if (!Config.SectionsToRename.insert(Old2New).second) + // Flags split: ".bar" "f1" "f2" ... + SmallVector NameAndFlags; + Old2New.second.split(NameAndFlags, ','); + SectionRenameConfig SectionConfig; + SectionConfig.NewName = NameAndFlags[0]; + + if (NameAndFlags.size() > 1) { + SectionFlag Flags = SectionFlag::SecNone; + for (int i = 1; i < (int)NameAndFlags.size(); ++i) { + SectionFlag Flag = ParseSectionName(NameAndFlags[i]); + if (Flag == SectionFlag::SecNone) + error("Unknown flag type: " + NameAndFlags[i]); + Flags |= Flag; + } + + uint64_t ElfFlags = 0; + if (Flags & SectionFlag::SecAlloc) + ElfFlags |= ELF::SHF_ALLOC; + if (!(Flags & SectionFlag::SecReadonly)) + ElfFlags |= ELF::SHF_WRITE; + if (Flags & SectionFlag::SecCode) + ElfFlags |= ELF::SHF_EXECINSTR; + if (Flags & SectionFlag::SecMerge) + ElfFlags |= ELF::SHF_MERGE; + if (Flags & SectionFlag::SecStrings) + ElfFlags |= ELF::SHF_STRINGS; + SectionConfig.NewFlags = ElfFlags; + } + if (!Config.SectionsToRename + .try_emplace(Old2New.first, std::move(SectionConfig)) + .second) error("Already have a section rename for " + Old2New.first); }