Index: llvm/test/tools/llvm-objcopy/ELF/rename-section-relocsec.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objcopy/ELF/rename-section-relocsec.test @@ -0,0 +1,110 @@ +# RUN: yaml2obj %s -o %t + +## When a section is renamed, its relocation section should be renamed similarly. +# RUN: llvm-objcopy %t - --rename-section=.text=.foo --rename-section=.data=.bar | \ +# RUN: llvm-readobj --sections - | \ +# RUN: FileCheck %s --check-prefix=TEST1 +# TEST1: Name: .foo +# TEST1: Name: .rel.foo +# TEST1: Name: .rela.bar +# TEST1: Name: .bar + +## A relocation section should be renamed when its target section is renamed +## even if its name does not follow the typical pattern. +## Note that in the input file, '.rel.fn' targets '.sub', not '.fn'. +# RUN: llvm-objcopy %t - --rename-section=.sub=.func | \ +# RUN: llvm-readobj --sections - | \ +# RUN: FileCheck %s --check-prefix=TEST2 +# TEST2: Name: .fn +# TEST2: Name: .func +# TEST2: Name: .rel.func + +## A relocation section should not be renamed if an unrelated section with +## the same common name is related. +## Note that in the input file, 'rel.fn' does not target 'fn'. +# RUN: llvm-objcopy %t - --rename-section=.fn=.foo | \ +# RUN: llvm-readobj --sections - | \ +# RUN: FileCheck %s --check-prefix=TEST3 +# TEST3: Name: .foo +# TEST3: Name: .sub +# TEST3: Name: .rel.fn + +## A relocation section can be renamed with an explicit --rename-section command. +# RUN: llvm-objcopy %t - --rename-section=.rel.text=.rel.foo --rename-section=.rela.data=.rela.bar | \ +# RUN: llvm-readobj --sections - | \ +# RUN: FileCheck %s --check-prefix=TEST4 +# TEST4: Name: .text +# TEST4: Name: .rel.foo +# TEST4: Name: .rela.bar +# TEST4: Name: .data + +## Explicit renaming is preferred. +# RUN: llvm-objcopy %t - --rename-section=.text=.foo --rename-section=.data=.bar --rename-section=.sub=.func \ +# RUN: --rename-section=.rel.text=.rel.baz --rename-section=.rela.data=.rela.qux --rename-section=.rel.fn=.funcrelocs | \ +# RUN: llvm-readobj --sections - | \ +# RUN: FileCheck %s --check-prefix=TEST5 +# TEST5: Name: .foo +# TEST5: Name: .rel.baz +# TEST5: Name: .rela.qux +# TEST5: Name: .bar +# TEST5: Name: .fn +# TEST5: Name: .func +# TEST5: Name: .funcrelocs + +## Should not rename a relocation section if it or its target are not specified in --rename-section. +## Note that this diverges from GNU objcopy. +# RUN: llvm-objcopy %t - --rename-section=.text=.foo | \ +# RUN: llvm-readobj --sections - | \ +# RUN: FileCheck %s --check-prefix=TEST6 +# TEST6: Name: .fn +# TEST6: Name: .sub +# TEST6: Name: .rel.fn + +## A dynamic relocation section should not be renamed together with its target section +# RUN: llvm-objcopy %t - --rename-section=.got.plt=.foo | \ +# RUN: llvm-readobj --sections - | \ +# RUN: FileCheck %s --check-prefix=TEST7 +# TEST7: Name: .rela.plt +# TEST7: Name: .foo + +## A dynamic relocation section can be renamed with an explicit --rename-section command. +# RUN: llvm-objcopy %t - --rename-section=.rela.plt=.rela.baz | \ +# RUN: llvm-readobj --sections - | \ +# RUN: FileCheck %s --check-prefix=TEST8 +# TEST8: Name: .rela.baz +# TEST8: Name: .got.plt + +!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 ] + - Name: .fn + Type: SHT_PROGBITS + - Name: .sub + Type: SHT_PROGBITS + - Name: .rel.fn + Type: SHT_REL +## Note: '.rel.fn' targets '.sub', not '.fn' + Info: .sub + - Name: .rela.plt + Type: SHT_RELA + Flags: [ SHF_ALLOC ] + Info: .got.plt + - Name: .got.plt + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_WRITE ] Index: llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp =================================================================== --- llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -588,14 +588,31 @@ return E; if (!Config.SectionsToRename.empty()) { + std::vector RelocSections; + DenseSet RenamedSections; for (SectionBase &Sec : Obj.sections()) { + auto *RelocSec = dyn_cast(&Sec); const auto Iter = Config.SectionsToRename.find(Sec.Name); if (Iter != Config.SectionsToRename.end()) { const SectionRename &SR = Iter->second; Sec.Name = std::string(SR.NewName); if (SR.NewFlags.hasValue()) setSectionFlagsAndType(Sec, SR.NewFlags.getValue()); - } + RenamedSections.insert(&Sec); + } else if (RelocSec && !(Sec.Flags & SHF_ALLOC)) + // Postpone processing relocation sections which are not specified in + // their explicit '--rename-section' commands untile after their target + // sections are renamed, + // Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be + // renamed only explicitly. Otherwise, renaming, for example, 'got.plt' + // would affect '.rela.plt', which is not desirable. + RelocSections.push_back(RelocSec); + } + // Rename relocation sections according to their target sections. + for (RelocationSectionBase *RelocSec : RelocSections) { + auto Iter = RenamedSections.find(RelocSec->getSection()); + if (Iter != RenamedSections.end()) + RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str(); } }