diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp --- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp @@ -629,6 +629,63 @@ if (Error E = updateAndRemoveSymbols(Config, ELFConfig, Obj)) return E; + 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.OnlyKeepDebug) + for (auto &Sec : Obj.sections()) + if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE) + Sec.Type = SHT_NOBITS; + + for (const NewSectionInfo &AddedSection : Config.AddSection) { + auto AddSection = [&](StringRef Name, ArrayRef Data) { + OwnedDataSection &NewSection = + Obj.addSection(Name, Data); + if (Name.startswith(".note") && Name != ".note.GNU-stack") + NewSection.Type = SHT_NOTE; + return Error::success(); + }; + if (Error E = handleUserSection(AddedSection, AddSection)) + return E; + } + + for (const NewSectionInfo &NewSection : Config.UpdateSection) { + auto UpdateSection = [&](StringRef Name, ArrayRef Data) { + return Obj.updateSection(Name, Data); + }; + if (Error E = handleUserSection(NewSection, UpdateSection)) + return E; + } + + if (!Config.AddGnuDebugLink.empty()) + Obj.addSection(Config.AddGnuDebugLink, + Config.GnuDebugLinkCRC32); + + // If the symbol table was previously removed, we need to create a new one + // before adding new symbols. + if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty()) + if (Error E = Obj.addNewSymbolTable()) + return E; + + for (const NewSymbolInfo &SI : Config.SymbolsToAdd) + addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility); + + // --set-section-flags works with sections added by --add-section. + if (!Config.SetSectionFlags.empty()) { + for (auto &Sec : Obj.sections()) { + const auto Iter = Config.SetSectionFlags.find(Sec.Name); + if (Iter != Config.SetSectionFlags.end()) { + const SectionFlagsUpdate &SFU = Iter->second; + setSectionFlagsAndType(Sec, SFU.NewFlags); + } + } + } + if (!Config.SectionsToRename.empty()) { std::vector RelocSections; DenseSet RenamedSections; @@ -693,63 +750,6 @@ } } - 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.OnlyKeepDebug) - for (auto &Sec : Obj.sections()) - if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE) - Sec.Type = SHT_NOBITS; - - for (const NewSectionInfo &AddedSection : Config.AddSection) { - auto AddSection = [&](StringRef Name, ArrayRef Data) { - OwnedDataSection &NewSection = - Obj.addSection(Name, Data); - if (Name.startswith(".note") && Name != ".note.GNU-stack") - NewSection.Type = SHT_NOTE; - return Error::success(); - }; - if (Error E = handleUserSection(AddedSection, AddSection)) - return E; - } - - for (const NewSectionInfo &NewSection : Config.UpdateSection) { - auto UpdateSection = [&](StringRef Name, ArrayRef Data) { - return Obj.updateSection(Name, Data); - }; - if (Error E = handleUserSection(NewSection, UpdateSection)) - return E; - } - - if (!Config.AddGnuDebugLink.empty()) - Obj.addSection(Config.AddGnuDebugLink, - Config.GnuDebugLinkCRC32); - - // If the symbol table was previously removed, we need to create a new one - // before adding new symbols. - if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty()) - if (Error E = Obj.addNewSymbolTable()) - return E; - - for (const NewSymbolInfo &SI : Config.SymbolsToAdd) - addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility); - - // --set-section-flags works with sections added by --add-section. - if (!Config.SetSectionFlags.empty()) { - for (auto &Sec : Obj.sections()) { - const auto Iter = Config.SetSectionFlags.find(Sec.Name); - if (Iter != Config.SetSectionFlags.end()) { - const SectionFlagsUpdate &SFU = Iter->second; - setSectionFlagsAndType(Sec, SFU.NewFlags); - } - } - } - if (ELFConfig.EntryExpr) Obj.Entry = ELFConfig.EntryExpr(Obj.Entry); return Error::success(); diff --git a/llvm/test/tools/llvm-objcopy/ELF/rename-section-and-update.test b/llvm/test/tools/llvm-objcopy/ELF/rename-section-and-update.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/rename-section-and-update.test @@ -0,0 +1,29 @@ +## --add-section is handled before --rename-section. Note: GNU objcopy produces .foo2. +# RUN: yaml2obj %s -o %t +# RUN: llvm-objcopy --rename-section=.foo1=.foo2 --add-section=.foo1=/dev/null %t %t.1 +# RUN: llvm-readobj -S %t.1 | FileCheck %s + +# CHECK: Name: .foo2 +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] + +## --update-section is handled before --rename-section. +# RUN: echo 00 > %t.nop +# RUN: llvm-objcopy --rename-section=.text=.text2 --update-section=.text=%t.nop %t %t.2 +# RUN: llvm-readelf -x .text2 %t.2 | FileCheck %s --check-prefix=CHECK2 + +# CHECK2: Hex dump of section '.text2': +# CHECK2-NEXT: 0x00000000 30300a + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Content: "c3c3c3" diff --git a/llvm/test/tools/llvm-objcopy/ELF/set-section-attr-and-rename.test b/llvm/test/tools/llvm-objcopy/ELF/set-section-attr-and-rename.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/set-section-attr-and-rename.test @@ -0,0 +1,29 @@ +# RUN: yaml2obj %s -o %t + +# RUN: llvm-objcopy --rename-section=.foo=.bar --set-section-alignment=.foo=16 --set-section-flags=.foo=alloc %t %t.1 +# RUN: llvm-readobj -S %t.1 | FileCheck %s + +# CHECK: Name: .bar +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK: AddressAlignment: +# CHECK-SAME: {{^}} 16 + +# RUN: not llvm-objcopy --rename-section=.foo=.bar --set-section-flags=.bar=alloc %t %t.2 2>&1 | \ +# RUN: FileCheck %s --check-prefix=SET-BAR + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + +# SET-BAR: --set-section-flags=.bar conflicts with --rename-section=.foo=.bar diff --git a/llvm/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test b/llvm/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test deleted file mode 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test +++ /dev/null @@ -1,14 +0,0 @@ -# RUN: yaml2obj %s -o %t - -# RUN: not llvm-objcopy --rename-section=.foo=.bar --set-section-flags=.foo=alloc %t %t.2 2>&1 | FileCheck %s --check-prefix=SET-FOO -# RUN: not llvm-objcopy --rename-section=.foo=.bar --set-section-flags=.bar=alloc %t %t.2 2>&1 | FileCheck %s --check-prefix=SET-BAR - -!ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 - -# SET-FOO: --set-section-flags=.foo conflicts with --rename-section=.foo=.bar -# SET-BAR: --set-section-flags=.bar conflicts with --rename-section=.foo=.bar diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -810,15 +810,9 @@ SFU->Name.str().c_str()); } // Prohibit combinations of --set-section-flags when the section name is used - // by --rename-section, either as a source or a destination. + // as the destination of a --rename-section. for (const auto &E : Config.SectionsToRename) { const SectionRename &SR = E.second; - if (Config.SetSectionFlags.count(SR.OriginalName)) - return createStringError( - errc::invalid_argument, - "--set-section-flags=%s conflicts with --rename-section=%s=%s", - SR.OriginalName.str().c_str(), SR.OriginalName.str().c_str(), - SR.NewName.str().c_str()); if (Config.SetSectionFlags.count(SR.NewName)) return createStringError( errc::invalid_argument,