[llvm-objcopy][ELF] Allow --set-section-flags src=... and --rename-section src=tst
* GNU objcopy supports --set-section-flags src=... --rename-section src=tst and --set-section-flags runs first. * GNU objcopy processes --update-section before --rename-section. To match the two behaviors, postpone --rename-section and allow its use together with --set-section-flags. As a side effect, --rename-section=.foo1=.foo2 --add-section=.foo1=/dev/null leads to .foo2 while GNU objcopy surprisingly produces .foo1 (so --set-section-flags --add-section --rename-section do not form a total order). I think the deviation is fine as a total order makes more sense. Rename set-section-flags-and-rename.test to set-section-attr-and-rename.test and additionally test --set-section-alignment Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D129336
This commit is contained in:
parent
0af2680596
commit
7c03b7d668
|
@ -233,6 +233,8 @@ Changes to the LLVM tools
|
|||
filter :doc:`Symbolizer Markup </SymbolizerMarkupFormat>` into human-readable
|
||||
form.
|
||||
* :doc:`llvm-objcopy <CommandGuide/llvm-objcopy>` has removed support for the legacy ``zlib-gnu`` format.
|
||||
* :doc:`llvm-objcopy <CommandGuide/llvm-objcopy>` now allows ``--set-section-flags src=... --rename-section src=tst``.
|
||||
``--add-section=.foo1=... --rename-section=.foo1=.foo2`` now adds ``.foo1`` instead of ``.foo2``.
|
||||
|
||||
Changes to LLDB
|
||||
---------------------------------
|
||||
|
|
|
@ -629,6 +629,63 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
|
|||
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<uint8_t> Data) {
|
||||
OwnedDataSection &NewSection =
|
||||
Obj.addSection<OwnedDataSection>(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<uint8_t> Data) {
|
||||
return Obj.updateSection(Name, Data);
|
||||
};
|
||||
if (Error E = handleUserSection(NewSection, UpdateSection))
|
||||
return E;
|
||||
}
|
||||
|
||||
if (!Config.AddGnuDebugLink.empty())
|
||||
Obj.addSection<GnuDebugLinkSection>(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<RelocationSectionBase *> RelocSections;
|
||||
DenseSet<SectionBase *> RenamedSections;
|
||||
|
@ -693,63 +750,6 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
|
|||
}
|
||||
}
|
||||
|
||||
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<uint8_t> Data) {
|
||||
OwnedDataSection &NewSection =
|
||||
Obj.addSection<OwnedDataSection>(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<uint8_t> Data) {
|
||||
return Obj.updateSection(Name, Data);
|
||||
};
|
||||
if (Error E = handleUserSection(NewSection, UpdateSection))
|
||||
return E;
|
||||
}
|
||||
|
||||
if (!Config.AddGnuDebugLink.empty())
|
||||
Obj.addSection<GnuDebugLinkSection>(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();
|
||||
|
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -810,15 +810,9 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
|
|||
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,
|
||||
|
|
Loading…
Reference in New Issue