mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[obj2yaml] - Dump section offsets in some cases.
Currently we never dump the `sh_offset` key. Though it sometimes an important information. To reduce the noise this patch implements the following logic: 1) The "Offset" key for the first section is always emitted. 2) If we can derive the offset for a next section naturally, then the "Offset" key is omitted. By "naturally" I mean that section[X] offset is expected to be: ``` offsetOf(section[X]) == alignTo(section[X - 1].sh_offset + section[X - 1].sh_size, section[X].sh_addralign) ``` So, when it has the expected value, we omit it from the output. Differential revision: https://reviews.llvm.org/D91152
This commit is contained in:
parent
ffd843aa95
commit
ab0f993654
@ -658,6 +658,9 @@ struct Object {
|
||||
unsigned getMachine() const;
|
||||
};
|
||||
|
||||
bool shouldAllocateFileSpace(ArrayRef<ProgramHeader> Phdrs,
|
||||
const NoBitsSection &S);
|
||||
|
||||
} // end namespace ELFYAML
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -1135,8 +1135,8 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
|
||||
}
|
||||
}
|
||||
|
||||
static bool shouldAllocateFileSpace(ArrayRef<ELFYAML::ProgramHeader> Phdrs,
|
||||
const ELFYAML::NoBitsSection &S) {
|
||||
bool llvm::ELFYAML::shouldAllocateFileSpace(
|
||||
ArrayRef<ELFYAML::ProgramHeader> Phdrs, const ELFYAML::NoBitsSection &S) {
|
||||
for (const ELFYAML::ProgramHeader &PH : Phdrs) {
|
||||
auto It = llvm::find_if(
|
||||
PH.Chunks, [&](ELFYAML::Chunk *C) { return C->Name == S.Name; });
|
||||
|
@ -362,6 +362,7 @@
|
||||
# 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
|
||||
@ -385,6 +386,7 @@
|
||||
# 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 ]
|
||||
@ -482,6 +484,7 @@
|
||||
# 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
|
||||
@ -490,6 +493,7 @@
|
||||
# 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 ]
|
||||
|
260
test/tools/obj2yaml/ELF/offset.yaml
Normal file
260
test/tools/obj2yaml/ELF/offset.yaml
Normal file
@ -0,0 +1,260 @@
|
||||
## Check how the "Offset" field is dumped by obj2yaml.
|
||||
## For each section we calulate the expected offset.
|
||||
## When it does not match the actual offset, we emit the "Offset" key.
|
||||
|
||||
# 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
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Sections:
|
||||
## The offset of .foo1 by default is 0x40, because it is placed right
|
||||
## after the ELF header. In this case we don't dump the "Offset" key,
|
||||
## because the file offset is naturally expected.
|
||||
- Name: .foo1
|
||||
Type: SHT_PROGBITS
|
||||
Size: 1
|
||||
Offset: [[FIRSTOFF=<none>]]
|
||||
AddressAlign: [[FIRSTADDRALIGN=0]]
|
||||
## Offset of .foo2 == offset of .foo1 + size of .foo1.
|
||||
## We don't dump the "Offset" key in this case.
|
||||
## sh_offset of .foo2 is 0x41.
|
||||
- Name: .foo2
|
||||
Type: SHT_PROGBITS
|
||||
Size: 1
|
||||
## Offset of .foo3 == offset of .foo2 + size of .foo2,
|
||||
## We don't dump the "Offset" key in this case.
|
||||
## sh_offset of .foo3 is 0x42.
|
||||
- Name: .foo3
|
||||
Type: SHT_PROGBITS
|
||||
Size: 1
|
||||
## Offset of .bar1 != offset of .foo3 + size of .foo3.
|
||||
## We dump the "Offset" key in this case.
|
||||
## sh_offset of .bar1 is 0x100.
|
||||
- Name: .bar1
|
||||
Type: SHT_PROGBITS
|
||||
Offset: 0x100
|
||||
Size: 1
|
||||
## [Offset of .bar1 + size of .bar1] aligned by 0x10 is equal to the offset
|
||||
## of .bar2. We don't dump the "Offset" key in this case.
|
||||
## sh_offset of .bar2 is 0x110.
|
||||
- Name: .bar2
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x10
|
||||
Offset: 0x110
|
||||
Size: 1
|
||||
## [Offset of .bar2 + size of .bar2] aligned by 0x10 is not equal to the offset
|
||||
## of .bar3. We dump the "Offset" key in this case.
|
||||
## sh_offset of .bar3 is 0x200.
|
||||
- Name: .bar3
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x10
|
||||
Offset: 0x200
|
||||
|
||||
## Show we dump the "Offset" key for the first section when
|
||||
## it has an unexpected file offset.
|
||||
|
||||
# RUN: yaml2obj %s -DFIRSTOFF=0x40 -o %t2a.o
|
||||
# RUN: obj2yaml %t2a.o | FileCheck %s --check-prefix=BASIC
|
||||
# RUN: yaml2obj %s -DFIRSTOFF=0x41 -o %t2b.o
|
||||
# RUN: obj2yaml %t2b.o | FileCheck %s --check-prefix=FIRSTSEC
|
||||
|
||||
# FIRSTSEC: Sections:
|
||||
# FIRSTSEC-NEXT: - Name: .foo1
|
||||
# FIRSTSEC-NEXT: Type: SHT_PROGBITS
|
||||
# FIRSTSEC-NEXT: Offset: 0x41
|
||||
# FIRSTSEC-NEXT: Content: '00'
|
||||
|
||||
## Test that we take the alignment of the first section into account
|
||||
## when calculating the expected offset for it. In this case we don't
|
||||
## dump the "Offset", because it is expected.
|
||||
|
||||
# RUN: yaml2obj %s -DFIRSTOFF=0x80 -DFIRSTADDRALIGN=0x80 -o %t3.o
|
||||
# RUN: obj2yaml %t3.o | FileCheck %s --check-prefix=FIRSTSECALIGN
|
||||
|
||||
# FIRSTSECALIGN: - Name: .foo1
|
||||
# FIRSTSECALIGN-NEXT: Type: SHT_PROGBITS
|
||||
# FIRSTSECALIGN-NEXT: AddressAlign: 0x80
|
||||
# FIRSTSECALIGN-NEXT: Content: '00'
|
||||
# FIRSTSECALIGN-NEXT: - Name:
|
||||
|
||||
## Test that we take the program headers offset and size into account when calculating
|
||||
## the expected file offset of the first section.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=2 -o %t4a.o
|
||||
# RUN: obj2yaml %t4a.o | FileCheck %s --check-prefix=FIRSTSECPHDRS
|
||||
## The expected file offset of the first section is:
|
||||
## 0x40 (start of program headers) + 0x38 (size of program headers) * 2(number of program headers) = 0xB0
|
||||
# RUN: yaml2obj %s --docnum=2 -DFIRSTOFF=0xB0 -o %t4b.o
|
||||
# RUN: obj2yaml %t4b.o | FileCheck %s --check-prefix=FIRSTSECPHDRS
|
||||
# RUN: yaml2obj %s --docnum=2 -DFIRSTOFF=0xB1 -o %t4c.o
|
||||
# RUN: obj2yaml %t4c.o | FileCheck %s --check-prefixes=FIRSTSECPHDRS,FIRSTSECPHDRSOFFSET
|
||||
|
||||
# FIRSTSECPHDRS: Sections:
|
||||
# FIRSTSECPHDRS-NEXT: - Name: .foo
|
||||
# FIRSTSECPHDRS-NEXT: Type: SHT_PROGBITS
|
||||
# FIRSTSECPHDRSOFFSET-NEXT: Offset: 0xB1
|
||||
# FIRSTSECPHDRS-NEXT: ...
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Sections:
|
||||
- Name: .foo
|
||||
Type: SHT_PROGBITS
|
||||
Offset: [[FIRSTOFF=<none>]]
|
||||
ProgramHeaders:
|
||||
- Type: PT_LOAD
|
||||
- Type: PT_LOAD
|
||||
|
||||
## Test that when there are no program headers in the file, we don't take SHT_NOBITS
|
||||
## section sizes into account, but respect their alignment when calculating the expected
|
||||
## section offsets.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=3 -o %t5.o
|
||||
# RUN: obj2yaml %t5.o | FileCheck %s --check-prefix=NOBITS
|
||||
|
||||
# NOBITS: Sections:
|
||||
# NOBITS-NEXT: - Name: .progbits1
|
||||
# NOBITS-NEXT: Type: SHT_PROGBITS
|
||||
# NOBITS-NEXT: Content: '00'
|
||||
# NOBITS-NEXT: - Name: .nobits1
|
||||
# NOBITS-NEXT: Type: SHT_NOBITS
|
||||
# NOBITS-NEXT: Size: 0x10
|
||||
# NOBITS-NEXT: - Name: .progbits2
|
||||
# NOBITS-NEXT: Type: SHT_PROGBITS
|
||||
# NOBITS-NEXT: Content: '0000'
|
||||
# NOBITS-NEXT: - Name: .nobits2
|
||||
# NOBITS-NEXT: Type: SHT_NOBITS
|
||||
# NOBITS-NEXT: AddressAlign: 0x100
|
||||
# NOBITS-NEXT: Size: 0x100
|
||||
# NOBITS-NEXT: - Name: .progbits3
|
||||
# NOBITS-NEXT: Type: SHT_PROGBITS
|
||||
# NOBITS-NEXT: Content: '000000'
|
||||
# NOBITS-NEXT: ...
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Sections:
|
||||
## sh_offset == 0x40.
|
||||
- Name: .progbits1
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x1
|
||||
## sh_offset == 0x41.
|
||||
- Name: .nobits1
|
||||
Type: SHT_NOBITS
|
||||
Size: 0x10
|
||||
## sh_offset == 0x41.
|
||||
- Name: .progbits2
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x2
|
||||
## sh_offset == 0x100.
|
||||
- Name: .nobits2
|
||||
Type: SHT_NOBITS
|
||||
Size: 0x100
|
||||
AddressAlign: 0x100
|
||||
## sh_offset == 0x100.
|
||||
- Name: .progbits3
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x3
|
||||
|
||||
## Check that we might take sizes of SHT_NOBITS sections into account when calculating
|
||||
## the expected offsets when there are program headers in the file. The rule is the following:
|
||||
## we assume that the file space is allocated for the SHT_NOBITS section when there are
|
||||
## other non-nobits sections in the same segment that follows it.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=4 -o %t6.o
|
||||
# RUN: obj2yaml %t6.o | FileCheck %s --check-prefix=NOBITS-PHDRS
|
||||
|
||||
# NOBITS-PHDRS: Sections:
|
||||
# NOBITS-PHDRS-NEXT: - Name: .nobits1
|
||||
# NOBITS-PHDRS-NEXT: Type: SHT_NOBITS
|
||||
# NOBITS-PHDRS-NEXT: Size: 0x1
|
||||
# NOBITS-PHDRS-NEXT: - Name: .progbits
|
||||
# NOBITS-PHDRS-NEXT: Type: SHT_PROGBITS
|
||||
# NOBITS-PHDRS-NEXT: Content: '0000'
|
||||
# NOBITS-PHDRS-NEXT: - Name: .nobits3
|
||||
# NOBITS-PHDRS-NEXT: Type: SHT_NOBITS
|
||||
# NOBITS-PHDRS-NEXT: Size: 0x100
|
||||
# NOBITS-PHDRS-NEXT: - Name: .nobits4
|
||||
# NOBITS-PHDRS-NEXT: Type: SHT_NOBITS
|
||||
# NOBITS-PHDRS-NEXT: Size: 0x200
|
||||
# NOBITS-PHDRS-NEXT: - Name: .nobits5
|
||||
# NOBITS-PHDRS-NEXT: Type: SHT_NOBITS
|
||||
# NOBITS-PHDRS-NEXT: Offset: 0x100
|
||||
# NOBITS-PHDRS-NEXT: Size: 0x300
|
||||
# NOBITS-PHDRS-NEXT: ...
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Sections:
|
||||
## sh_offset == 0xe8.
|
||||
- Name: .nobits1
|
||||
Type: SHT_NOBITS
|
||||
Size: 0x1
|
||||
## sh_offset == 0xe9.
|
||||
- Name: .progbits
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x2
|
||||
## sh_offset == 0xeb.
|
||||
- Name: .nobits3
|
||||
Type: SHT_NOBITS
|
||||
Size: 0x100
|
||||
## sh_offset == 0xeb.
|
||||
- Name: .nobits4
|
||||
Type: SHT_NOBITS
|
||||
Size: 0x200
|
||||
## sh_offset == 0x100.
|
||||
- Name: .nobits5
|
||||
Type: SHT_NOBITS
|
||||
Size: 0x300
|
||||
Offset: 0x100
|
||||
ProgramHeaders:
|
||||
- Type: PT_LOAD
|
||||
FirstSec: .nobits1
|
||||
LastSec: .progbits
|
||||
- Type: PT_LOAD
|
||||
FirstSec: .nobits3
|
||||
LastSec: .nobits4
|
||||
- Type: PT_LOAD
|
||||
FirstSec: .nobits5
|
||||
LastSec: .nobits5
|
@ -232,6 +232,40 @@ bool ELFDumper<ELFT>::shouldPrintSection(const ELFYAML::Section &S,
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
static void dumpSectionOffsets(const typename ELFT::Ehdr &Header,
|
||||
ArrayRef<ELFYAML::ProgramHeader> Phdrs,
|
||||
std::vector<std::unique_ptr<ELFYAML::Chunk>> &V,
|
||||
ArrayRef<typename ELFT::Shdr> S) {
|
||||
uint64_t ExpectedOffset;
|
||||
if (Header.e_phoff > 0)
|
||||
ExpectedOffset = Header.e_phoff + Header.e_phentsize * Header.e_phnum;
|
||||
else
|
||||
ExpectedOffset = sizeof(typename ELFT::Ehdr);
|
||||
|
||||
for (const std::unique_ptr<ELFYAML::Chunk> &C :
|
||||
makeArrayRef(V).drop_front()) {
|
||||
ELFYAML::Section &Sec = *cast<ELFYAML::Section>(C.get());
|
||||
const typename ELFT::Shdr &SecHdr = S[Sec.OriginalSecNdx];
|
||||
|
||||
ExpectedOffset =
|
||||
alignTo(ExpectedOffset, SecHdr.sh_addralign ? SecHdr.sh_addralign : 1);
|
||||
|
||||
// We only set the "Offset" field when it can't be naturally derived
|
||||
// from the offset and size of the previous section. This reduces
|
||||
// the noise in the YAML output.
|
||||
if (SecHdr.sh_offset != ExpectedOffset)
|
||||
Sec.Offset = (yaml::Hex64)SecHdr.sh_offset;
|
||||
|
||||
if (Sec.Type == ELF::SHT_NOBITS &&
|
||||
!ELFYAML::shouldAllocateFileSpace(Phdrs,
|
||||
*cast<ELFYAML::NoBitsSection>(&Sec)))
|
||||
ExpectedOffset = SecHdr.sh_offset;
|
||||
else
|
||||
ExpectedOffset = SecHdr.sh_offset + SecHdr.sh_size;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
auto Y = std::make_unique<ELFYAML::Object>();
|
||||
|
||||
@ -321,6 +355,9 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
|
||||
return PhdrsOrErr.takeError();
|
||||
Y->ProgramHeaders = std::move(*PhdrsOrErr);
|
||||
|
||||
dumpSectionOffsets<ELFT>(Obj.getHeader(), Y->ProgramHeaders, Chunks,
|
||||
Sections);
|
||||
|
||||
// Dump DWARF sections.
|
||||
Y->DWARF = dumpDWARFSections(Chunks);
|
||||
|
||||
@ -397,6 +434,7 @@ ELFDumper<ELFT>::dumpProgramHeaders(
|
||||
if (!PH.FirstSec)
|
||||
PH.FirstSec = S.Name;
|
||||
PH.LastSec = S.Name;
|
||||
PH.Chunks.push_back(C.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user