Index: test/tools/llvm-objcopy/prefix-sections.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/prefix-sections.test @@ -0,0 +1,58 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objcopy --prefix-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: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .bar + Type: SHT_DYNAMIC + Flags: [ SHF_WRITE ] + - Name: .foobar + Type: SHT_STRTAB + +# CHECK: Sections [ +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: Name: (0) +# CHECK-NEXT: Type: SHT_NULL +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 0 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Name: .prefix.foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_EXECINSTR +# CHECK-NEXT: ] +# CHECK: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 2 +# CHECK-NEXT: Name: .prefix.bar +# CHECK-NEXT: Type: SHT_DYNAMIC +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Name: .foobar +# CHECK-NEXT: Type: SHT_STRTAB +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] Index: tools/llvm-objcopy/ObjcopyOpts.td =================================================================== --- tools/llvm-objcopy/ObjcopyOpts.td +++ tools/llvm-objcopy/ObjcopyOpts.td @@ -102,3 +102,6 @@ HelpText<"Remove all symbols not needed by relocations">; def keep_file_symbols : Flag<["-", "--"], "keep-file-symbols">, HelpText<"Do not remove file symbols">; +defm prefix_sections : Eq<"prefix-sections">, + MetaVarName<"prefix">, + HelpText<"Add to the start of every section name">; Index: tools/llvm-objcopy/Object.h =================================================================== --- tools/llvm-objcopy/Object.h +++ tools/llvm-objcopy/Object.h @@ -233,7 +233,7 @@ class SectionBase { public: - StringRef Name; + std::string Name; Segment *ParentSegment = nullptr; uint64_t HeaderOffset; uint64_t OriginalOffset = std::numeric_limits::max(); Index: tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- tools/llvm-objcopy/llvm-objcopy.cpp +++ tools/llvm-objcopy/llvm-objcopy.cpp @@ -133,6 +133,7 @@ StringRef SplitDWO; StringRef AddGnuDebugLink; + StringRef SectionsPrefix; std::vector ToRemove; std::vector Keep; std::vector OnlyKeep; @@ -270,13 +271,17 @@ return SR; } +static inline bool StartsWith(std::string S1, StringRef S2) { + return std::equal(S2.begin(), S2.end(), S1.begin()); +} + static bool IsDebugSection(const SectionBase &Sec) { - return Sec.Name.startswith(".debug") || Sec.Name.startswith(".zdebug") || + return StartsWith(Sec.Name, ".debug") || StartsWith(Sec.Name, ".zdebug") || Sec.Name == ".gdb_index"; } static bool IsDWOSection(const SectionBase &Sec) { - return Sec.Name.endswith(".dwo"); + return StringRef(Sec.Name).endswith(".dwo"); } static bool OnlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) { @@ -465,7 +470,7 @@ return true; if (&Sec == Obj.SectionNames) return false; - if (Sec.Name.startswith(".gnu.warning")) + if (StartsWith(Sec.Name, ".gnu.warning")) return false; return (Sec.Flags & SHF_ALLOC) == 0; }; @@ -557,6 +562,13 @@ if (!Config.AddGnuDebugLink.empty()) Obj.addSection(Config.AddGnuDebugLink); + + if (!Config.SectionsPrefix.empty()) { + for (auto &Sec : Obj.sections()) { + if (Sec.Type != SHT_STRTAB && Sec.Type != SHT_SYMTAB) + Sec.Name = Config.SectionsPrefix.str() + Sec.Name; + } + } } static void ExecuteElfObjcopyOnBinary(const CopyConfig &Config, Binary &Binary, @@ -688,6 +700,7 @@ Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); + Config.SectionsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_sections); for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) { if (!StringRef(Arg->getValue()).contains('='))