forked from OSchip/llvm-project
[obj2yaml] - Teach tool to emit the "SectionHeaderTable" key and sort sections by file offset.
Currently when we dump sections, we dump them in the order, which is specified in the sections header table. With that the order in the output might not match the order in the file. This patch starts sorting them by by file offsets when dumping. When the order in the section header table doesn't match the order in the file, we should emit the "SectionHeaderTable" key. This patch does it. Differential revision: https://reviews.llvm.org/D91249
This commit is contained in:
parent
398b729243
commit
ea8c8a5097
|
@ -1648,12 +1648,12 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
|
|||
IO.setContext(&Object);
|
||||
IO.mapTag("!ELF", true);
|
||||
IO.mapRequired("FileHeader", Object.Header);
|
||||
IO.mapOptional("SectionHeaderTable", Object.SectionHeaders);
|
||||
IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
|
||||
IO.mapOptional("Sections", Object.Chunks);
|
||||
IO.mapOptional("Symbols", Object.Symbols);
|
||||
IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
|
||||
IO.mapOptional("DWARF", Object.DWARF);
|
||||
IO.mapOptional("SectionHeaderTable", Object.SectionHeaders);
|
||||
if (Object.DWARF) {
|
||||
Object.DWARF->IsLittleEndian =
|
||||
Object.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
# RUN: obj2yaml %t.o | FileCheck %s
|
||||
|
||||
# CHECK: Sections:
|
||||
# CHECK: - Name: .text.foo{{$}}
|
||||
# CHECK: - Name: '.text.foo (1)'
|
||||
# CHECK: - Name: .group{{$}}
|
||||
# CHECK: Members:
|
||||
# CHECK: - SectionOrType: .text.foo{{$}}
|
||||
# CHECK: - SectionOrType: .rela.text.foo{{$}}
|
||||
# CHECK: - Name: .text.foo{{$}}
|
||||
# CHECK: - Name: .rela.text.foo{{$}}
|
||||
# CHECK: Info: .text.foo{{$}}
|
||||
# CHECK: - Name: '.group (1)'
|
||||
# CHECK: Members:
|
||||
# CHECK: - SectionOrType: '.text.foo (1)'
|
||||
# CHECK: - SectionOrType: '.rela.text.foo (1)'
|
||||
# CHECK: - Name: '.text.foo (1)'
|
||||
# CHECK: - Name: .rela.text.foo{{$}}
|
||||
# CHECK: Info: .text.foo{{$}}
|
||||
# CHECK: - Name: '.rela.text.foo (1)'
|
||||
# CHECK: Info: '.text.foo (1)'
|
||||
# CHECK: Symbols:
|
||||
|
|
|
@ -358,35 +358,10 @@
|
|||
# ELF-MIPSEL-NEXT: Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
# ELF-MIPSEL-NEXT: AddressAlign: 0x4
|
||||
# ELF-MIPSEL-NEXT: Content: 0000023C00004224E8FFBD271400BFAF1000B0AF218059000000018E000024240000198E09F8200321E000020000198E09F8200321E00002000002241000B08F1400BF8F0800E0031800BD27
|
||||
# ELF-MIPSEL-NEXT: - Name: .rel.text
|
||||
# ELF-MIPSEL-NEXT: Type: SHT_REL
|
||||
# ELF-MIPSEL-NEXT: Link: .symtab
|
||||
# ELF-MIPSEL-NEXT: AddressAlign: 0x4
|
||||
# ELF-MIPSEL-NEXT: Offset: 0x434
|
||||
# ELF-MIPSEL-NEXT: Info: .text
|
||||
# ELF-MIPSEL-NEXT: Relocations:
|
||||
# ELF-MIPSEL-NEXT: - Symbol: _gp_disp
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_HI16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x4
|
||||
# ELF-MIPSEL-NEXT: Symbol: _gp_disp
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_LO16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x18
|
||||
# ELF-MIPSEL-NEXT: Symbol: '$.str'
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_GOT16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x1C
|
||||
# ELF-MIPSEL-NEXT: Symbol: '$.str'
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_LO16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x20
|
||||
# ELF-MIPSEL-NEXT: Symbol: puts
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_CALL16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x2C
|
||||
# ELF-MIPSEL-NEXT: Symbol: SomeOtherFunction
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_CALL16
|
||||
# ELF-MIPSEL-NEXT: - Name: .data
|
||||
# ELF-MIPSEL-NEXT: Type: SHT_PROGBITS
|
||||
# ELF-MIPSEL-NEXT: Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
# ELF-MIPSEL-NEXT: AddressAlign: 0x4
|
||||
# ELF-MIPSEL-NEXT: Offset: 0x80
|
||||
# ELF-MIPSEL-NEXT: - Name: .bss
|
||||
# ELF-MIPSEL-NEXT: Type: SHT_NOBITS
|
||||
# ELF-MIPSEL-NEXT: Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
|
@ -416,6 +391,29 @@
|
|||
# ELF-MIPSEL-NEXT: GPRSize: REG_32
|
||||
# ELF-MIPSEL-NEXT: CPR1Size: REG_32
|
||||
# ELF-MIPSEL-NEXT: Flags1: [ ODDSPREG ]
|
||||
# ELF-MIPSEL-NEXT: - Name: .rel.text
|
||||
# ELF-MIPSEL-NEXT: Type: SHT_REL
|
||||
# ELF-MIPSEL-NEXT: Link: .symtab
|
||||
# ELF-MIPSEL-NEXT: AddressAlign: 0x4
|
||||
# ELF-MIPSEL-NEXT: Info: .text
|
||||
# ELF-MIPSEL-NEXT: Relocations:
|
||||
# ELF-MIPSEL-NEXT: - Symbol: _gp_disp
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_HI16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x4
|
||||
# ELF-MIPSEL-NEXT: Symbol: _gp_disp
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_LO16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x18
|
||||
# ELF-MIPSEL-NEXT: Symbol: '$.str'
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_GOT16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x1C
|
||||
# ELF-MIPSEL-NEXT: Symbol: '$.str'
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_LO16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x20
|
||||
# ELF-MIPSEL-NEXT: Symbol: puts
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_CALL16
|
||||
# ELF-MIPSEL-NEXT: - Offset: 0x2C
|
||||
# ELF-MIPSEL-NEXT: Symbol: SomeOtherFunction
|
||||
# ELF-MIPSEL-NEXT: Type: R_MIPS_CALL16
|
||||
# ELF-MIPSEL-NEXT: Symbols:
|
||||
# ELF-MIPSEL-NEXT: - Name: trivial.ll
|
||||
# ELF-MIPSEL-NEXT: Type: STT_FILE
|
||||
|
@ -461,6 +459,20 @@
|
|||
# ELF-MIPSEL-NEXT: Binding: STB_GLOBAL
|
||||
# ELF-MIPSEL-NEXT: - Name: puts
|
||||
# ELF-MIPSEL-NEXT: Binding: STB_GLOBAL
|
||||
# ELF-MIPSEL-NEXT: SectionHeaderTable:
|
||||
# ELF-MIPSEL-NEXT: Sections:
|
||||
# ELF-MIPSEL-NEXT: - Name: .text
|
||||
# ELF-MIPSEL-NEXT: - Name: .rel.text
|
||||
# ELF-MIPSEL-NEXT: - Name: .data
|
||||
# ELF-MIPSEL-NEXT: - Name: .bss
|
||||
# ELF-MIPSEL-NEXT: - Name: .mdebug.abi32
|
||||
# ELF-MIPSEL-NEXT: - Name: .rodata.str1.1
|
||||
# ELF-MIPSEL-NEXT: - Name: .reginfo
|
||||
# ELF-MIPSEL-NEXT: - Name: .MIPS.abiflags
|
||||
# ELF-MIPSEL-NEXT: - Name: .shstrtab
|
||||
# ELF-MIPSEL-NEXT: - Name: .symtab
|
||||
# ELF-MIPSEL-NEXT: - Name: .strtab
|
||||
# ELF-MIPSEL-NEXT: ...
|
||||
|
||||
# RUN: obj2yaml %p/Inputs/trivial-object-test.elf-mips64el | FileCheck %s --check-prefix ELF-MIPS64EL
|
||||
|
||||
|
@ -480,20 +492,10 @@
|
|||
# ELF-MIPS64EL-NEXT: Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
# ELF-MIPS64EL-NEXT: AddressAlign: 0x10
|
||||
# ELF-MIPS64EL-NEXT: Content: '00000000000000000000000000000000'
|
||||
# ELF-MIPS64EL-NEXT: - Name: .rela.data
|
||||
# ELF-MIPS64EL-NEXT: Type: SHT_RELA
|
||||
# ELF-MIPS64EL-NEXT: Link: .symtab
|
||||
# ELF-MIPS64EL-NEXT: AddressAlign: 0x8
|
||||
# ELF-MIPS64EL-NEXT: Offset: 0x410
|
||||
# ELF-MIPS64EL-NEXT: Info: .data
|
||||
# ELF-MIPS64EL-NEXT: Relocations:
|
||||
# ELF-MIPS64EL-NEXT: - Symbol: zed
|
||||
# ELF-MIPS64EL-NEXT: Type: R_MIPS_64
|
||||
# ELF-MIPS64EL-NEXT: - Name: .bss
|
||||
# ELF-MIPS64EL-NEXT: Type: SHT_NOBITS
|
||||
# ELF-MIPS64EL-NEXT: Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
# ELF-MIPS64EL-NEXT: AddressAlign: 0x10
|
||||
# ELF-MIPS64EL-NEXT: Offset: 0x50
|
||||
# ELF-MIPS64EL-NEXT: - Name: .MIPS.options
|
||||
# ELF-MIPS64EL-NEXT: Type: SHT_MIPS_OPTIONS
|
||||
# ELF-MIPS64EL-NEXT: Flags: [ SHF_ALLOC, SHF_MIPS_NOSTRIP ]
|
||||
|
@ -503,6 +505,14 @@
|
|||
# ELF-MIPS64EL-NEXT: - Name: .pdr
|
||||
# ELF-MIPS64EL-NEXT: Type: SHT_PROGBITS
|
||||
# ELF-MIPS64EL-NEXT: AddressAlign: 0x4
|
||||
# ELF-MIPS64EL-NEXT: - Name: .rela.data
|
||||
# ELF-MIPS64EL-NEXT: Type: SHT_RELA
|
||||
# ELF-MIPS64EL-NEXT: Link: .symtab
|
||||
# ELF-MIPS64EL-NEXT: AddressAlign: 0x8
|
||||
# ELF-MIPS64EL-NEXT: Info: .data
|
||||
# ELF-MIPS64EL-NEXT: Relocations:
|
||||
# ELF-MIPS64EL-NEXT: - Symbol: zed
|
||||
# ELF-MIPS64EL-NEXT: Type: R_MIPS_64
|
||||
# ELF-MIPS64EL-NEXT: Symbols:
|
||||
# ELF-MIPS64EL-NEXT: - Name: .text
|
||||
# ELF-MIPS64EL-NEXT: Type: STT_SECTION
|
||||
|
@ -523,6 +533,18 @@
|
|||
# ELF-MIPS64EL-NEXT: Section: .pdr
|
||||
# ELF-MIPS64EL-NEXT: - Name: zed
|
||||
# ELF-MIPS64EL-NEXT: Binding: STB_GLOBAL
|
||||
# ELF-MIPS64EL-NEXT: SectionHeaderTable:
|
||||
# ELF-MIPS64EL-NEXT: Sections:
|
||||
# ELF-MIPS64EL-NEXT: - Name: .text
|
||||
# ELF-MIPS64EL-NEXT: - Name: .data
|
||||
# ELF-MIPS64EL-NEXT: - Name: .rela.data
|
||||
# ELF-MIPS64EL-NEXT: - Name: .bss
|
||||
# ELF-MIPS64EL-NEXT: - Name: .MIPS.options
|
||||
# ELF-MIPS64EL-NEXT: - Name: .pdr
|
||||
# ELF-MIPS64EL-NEXT: - Name: .shstrtab
|
||||
# ELF-MIPS64EL-NEXT: - Name: .symtab
|
||||
# ELF-MIPS64EL-NEXT: - Name: .strtab
|
||||
# ELF-MIPS64EL-NEXT: ...
|
||||
|
||||
# RUN: yaml2obj %s -o %t-x86-64
|
||||
# RUN: obj2yaml %t-x86-64 | FileCheck %s --check-prefix ELF-X86-64
|
||||
|
|
|
@ -5,37 +5,49 @@
|
|||
# RUN: yaml2obj %s -o %t1.o
|
||||
# RUN: obj2yaml %t1.o | FileCheck %s --check-prefix=BASIC
|
||||
|
||||
# BASIC: --- !ELF
|
||||
# BASIC-NEXT: FileHeader:
|
||||
# BASIC-NEXT: Class: ELFCLASS64
|
||||
# BASIC-NEXT: Data: ELFDATA2LSB
|
||||
# BASIC-NEXT: Type: ET_REL
|
||||
# BASIC-NEXT: Sections:
|
||||
# BASIC-NEXT: - Name: .foo1
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .foo2
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .foo3
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .bar1
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: Offset: 0x100
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .bar2
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: AddressAlign: 0x10
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .bar3
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: AddressAlign: 0x10
|
||||
# BASIC-NEXT: Offset: 0x200
|
||||
# BASIC-NEXT: - Name: .bar4
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: AddressAlign: 0x100000000
|
||||
# BASIC-NEXT: Offset: 0x210
|
||||
# BASIC: --- !ELF
|
||||
# BASIC-NEXT: FileHeader:
|
||||
# BASIC-NEXT: Class: ELFCLASS64
|
||||
# BASIC-NEXT: Data: ELFDATA2LSB
|
||||
# BASIC-NEXT: Type: ET_REL
|
||||
# BASIC-NEXT: Sections:
|
||||
# BASIC-NEXT: - Name: .foo1
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .foo2
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .foo3
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .bar1
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: Offset: 0x100
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .bar2
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: AddressAlign: 0x10
|
||||
# BASIC-NEXT: Content: '00'
|
||||
# BASIC-NEXT: - Name: .bar3
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: AddressAlign: 0x10
|
||||
# BASIC-NEXT: Offset: 0x200
|
||||
# BASIC-NEXT: - Name: .bar4
|
||||
# BASIC-NEXT: Type: SHT_PROGBITS
|
||||
# BASIC-NEXT: AddressAlign: 0x100000000
|
||||
# BASIC-NEXT: Offset: 0x210
|
||||
# HEADERS-NEXT: SectionHeaderTable:
|
||||
# HEADERS-NEXT: Sections:
|
||||
# HEADERS-NEXT: - Name: .bar4
|
||||
# HEADERS-NEXT: - Name: .bar3
|
||||
# HEADERS-NEXT: - Name: .bar2
|
||||
# HEADERS-NEXT: - Name: .bar1
|
||||
# HEADERS-NEXT: - Name: .foo3
|
||||
# HEADERS-NEXT: - Name: .foo2
|
||||
# HEADERS-NEXT: - Name: .foo1
|
||||
# HEADERS-NEXT: - Name: .strtab
|
||||
# HEADERS-NEXT: - Name: .shstrtab
|
||||
# BASIC-NEXT: ...
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
|
@ -91,6 +103,25 @@ Sections:
|
|||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x100000000
|
||||
Offset: 0x210
|
||||
SectionHeaderTable:
|
||||
Sections:
|
||||
## By default we have the same order of sections as defined by the "Sections" key.
|
||||
- Name: [[SEC1=.foo1]]
|
||||
- Name: [[SEC2=.foo2]]
|
||||
- Name: [[SEC3=.foo3]]
|
||||
- Name: [[SEC4=.bar1]]
|
||||
- Name: [[SEC5=.bar2]]
|
||||
- Name: [[SEC6=.bar3]]
|
||||
- Name: [[SEC7=.bar4]]
|
||||
- Name: .strtab
|
||||
- Name: .shstrtab
|
||||
|
||||
## In this case we change the order of sections in the section header table.
|
||||
## Check that we still dump offsets correctly.
|
||||
|
||||
# RUN: yaml2obj %s -DSEC1=.bar4 -DSEC2=.bar3 -DSEC3=.bar2 \
|
||||
# RUN: -DSEC4=.bar1 -DSEC5=.foo3 -DSEC6=.foo2 -DSEC7=.foo1 -o %t1-sechdr.o
|
||||
# RUN: obj2yaml %t1-sechdr.o | FileCheck --check-prefixes=BASIC,HEADERS %s
|
||||
|
||||
## Show we dump the "Offset" key for the first section when
|
||||
## it has an unexpected file offset.
|
||||
|
|
|
@ -359,6 +359,20 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
|||
return ChunksOrErr.takeError();
|
||||
std::vector<std::unique_ptr<ELFYAML::Chunk>> Chunks = std::move(*ChunksOrErr);
|
||||
|
||||
std::vector<ELFYAML::Section *> OriginalOrder;
|
||||
if (!Chunks.empty())
|
||||
for (const std::unique_ptr<ELFYAML::Chunk> &C :
|
||||
makeArrayRef(Chunks).drop_front())
|
||||
OriginalOrder.push_back(cast<ELFYAML::Section>(C.get()));
|
||||
|
||||
// Sometimes the order of sections in the section header table does not match
|
||||
// their actual order. Here we sort sections by the file offset.
|
||||
llvm::stable_sort(Chunks, [&](const std::unique_ptr<ELFYAML::Chunk> &A,
|
||||
const std::unique_ptr<ELFYAML::Chunk> &B) {
|
||||
return Sections[cast<ELFYAML::Section>(A.get())->OriginalSecNdx].sh_offset <
|
||||
Sections[cast<ELFYAML::Section>(B.get())->OriginalSecNdx].sh_offset;
|
||||
});
|
||||
|
||||
// Dump program headers.
|
||||
Expected<std::vector<ELFYAML::ProgramHeader>> PhdrsOrErr =
|
||||
dumpProgramHeaders(Chunks);
|
||||
|
@ -372,6 +386,21 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
|||
// Dump DWARF sections.
|
||||
Y->DWARF = dumpDWARFSections(Chunks);
|
||||
|
||||
// We emit the "SectionHeaderTable" key when the order of sections in the
|
||||
// sections header table doesn't match the file order.
|
||||
const bool SectionsSorted =
|
||||
llvm::is_sorted(Chunks, [&](const std::unique_ptr<ELFYAML::Chunk> &A,
|
||||
const std::unique_ptr<ELFYAML::Chunk> &B) {
|
||||
return cast<ELFYAML::Section>(A.get())->OriginalSecNdx <
|
||||
cast<ELFYAML::Section>(B.get())->OriginalSecNdx;
|
||||
});
|
||||
if (!SectionsSorted) {
|
||||
Y->SectionHeaders.emplace();
|
||||
Y->SectionHeaders->Sections.emplace();
|
||||
for (ELFYAML::Section *S : OriginalOrder)
|
||||
Y->SectionHeaders->Sections->push_back({S->Name});
|
||||
}
|
||||
|
||||
llvm::erase_if(Chunks, [this, &Y](const std::unique_ptr<ELFYAML::Chunk> &C) {
|
||||
const ELFYAML::Section &S = cast<ELFYAML::Section>(*C.get());
|
||||
return !shouldPrintSection(S, Sections[S.OriginalSecNdx], Y->DWARF);
|
||||
|
|
Loading…
Reference in New Issue