Skip to content

Commit

Permalink
[yaml2obj] - Add a syntax to override e_phoff, e_phentsize and e_phnu…
Browse files Browse the repository at this point in the history
…m fields.

This adds `EPhOff`, `EPhEntSize` and `EPhNum` keys.
Will be useful for creating broken objects for testing llvm-readelf.

Differential revision: https://reviews.llvm.org/D83482
  • Loading branch information
Georgii Rymar committed Jul 14, 2020
1 parent 1d15bbb commit 3001569
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
4 changes: 4 additions & 0 deletions llvm/include/llvm/ObjectYAML/ELFYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ struct FileHeader {
ELF_EF Flags;
llvm::yaml::Hex64 Entry;

Optional<llvm::yaml::Hex64> EPhOff;
Optional<llvm::yaml::Hex16> EPhEntSize;
Optional<llvm::yaml::Hex16> EPhNum;

Optional<llvm::yaml::Hex16> SHEntSize;
Optional<llvm::yaml::Hex64> SHOff;
Optional<llvm::yaml::Hex16> SHNum;
Expand Down
24 changes: 21 additions & 3 deletions llvm/lib/ObjectYAML/ELFEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,11 +393,29 @@ void ELFState<ELFT>::writeELFHeader(raw_ostream &OS, uint64_t SHOff) {
Header.e_machine = Doc.Header.Machine;
Header.e_version = EV_CURRENT;
Header.e_entry = Doc.Header.Entry;
Header.e_phoff = Doc.ProgramHeaders.size() ? sizeof(Header) : 0;
Header.e_flags = Doc.Header.Flags;
Header.e_ehsize = sizeof(Elf_Ehdr);
Header.e_phentsize = Doc.ProgramHeaders.size() ? sizeof(Elf_Phdr) : 0;
Header.e_phnum = Doc.ProgramHeaders.size();

if (Doc.Header.EPhOff)
Header.e_phoff = *Doc.Header.EPhOff;
else if (!Doc.ProgramHeaders.empty())
Header.e_phoff = sizeof(Header);
else
Header.e_phoff = 0;

if (Doc.Header.EPhEntSize)
Header.e_phentsize = *Doc.Header.EPhEntSize;
else if (!Doc.ProgramHeaders.empty())
Header.e_phentsize = sizeof(Elf_Phdr);
else
Header.e_phentsize = 0;

if (Doc.Header.EPhNum)
Header.e_phnum = *Doc.Header.EPhNum;
else if (!Doc.ProgramHeaders.empty())
Header.e_phnum = Doc.ProgramHeaders.size();
else
Header.e_phnum = 0;

Header.e_shentsize =
Doc.Header.SHEntSize ? (uint16_t)*Doc.Header.SHEntSize : sizeof(Elf_Shdr);
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/ObjectYAML/ELFYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,13 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,
IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0));
IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));

// obj2yaml does not dump these fields.
assert(!IO.outputting() ||
(!FileHdr.EPhOff && !FileHdr.EPhEntSize && !FileHdr.EPhNum));
IO.mapOptional("EPhOff", FileHdr.EPhOff);
IO.mapOptional("EPhEntSize", FileHdr.EPhEntSize);
IO.mapOptional("EPhNum", FileHdr.EPhNum);

IO.mapOptional("SHEntSize", FileHdr.SHEntSize);
IO.mapOptional("SHOff", FileHdr.SHOff);
IO.mapOptional("SHNum", FileHdr.SHNum);
Expand Down
52 changes: 43 additions & 9 deletions llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
## In this test case we check that we can override the default values for
## e_shentsize, e_shoff, e_shnum and e_shstrndx fields in the YAML.
## ELF header fields in the YAML.

## First we check the default values.

# RUN: yaml2obj %s -o %t-default
# RUN: llvm-readelf --file-headers %t-default | FileCheck %s --check-prefix=DEFAULT

# DEFAULT: Start of section headers: 88 (bytes into file)
# DEFAULT: Size of section headers: 64 (bytes)
# DEFAULT: Number of section headers: 3
# DEFAULT: Section header string table index: 2
# DEFAULT: Start of program headers: 64 (bytes into file)
# DEFAULT: Start of section headers: 200 (bytes into file)
# DEFAULT: Size of program headers: 56 (bytes)
# DEFAULT: Number of program headers: 2
# DEFAULT: Size of section headers: 64 (bytes)
# DEFAULT: Number of section headers: 3
# DEFAULT: Section header string table index: 2

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
ProgramHeaders:
- Type: PT_LOAD
Sections: []
- Type: PT_LOAD
Sections: []

## Check we can override all default values using the same values
## and that this does not change the output.
Expand All @@ -29,10 +37,18 @@ FileHeader:
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
SHEntSize: [[SHENTSIZE=64]]
SHOff: [[SHOFF=88]]
SHNum: [[SHNUM=3]]
SHStrNdx: [[SHSTRNDX=2]]
SHEntSize: [[SHENTSIZE=64]]
SHOff: [[SHOFF=200]]
SHNum: [[SHNUM=3]]
SHStrNdx: [[SHSTRNDX=2]]
EPhOff: [[PHOFF=64]]
EPhEntSize: [[PHENTSIZE=56]]
EPhNum: [[PHNUM=2]]
ProgramHeaders:
- Type: PT_LOAD
Sections: []
- Type: PT_LOAD
Sections: []

## Override different fields to check the output produced.

Expand Down Expand Up @@ -63,3 +79,21 @@ FileHeader:
# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t-default | FileCheck %s --check-prefix=OLDSIZE
# NEWSIZE: 01
# OLDSIZE: 40

## Override the e_phoff field.
# RUN: yaml2obj --docnum=2 %s -DPHOFF=3 -o %t6
# RUN: llvm-readelf --file-headers %t6 | FileCheck %s --check-prefix=PHOFF

# PHOFF: Start of program headers: 3 (bytes into file){{$}}

## Override the e_phnum field.
# RUN: yaml2obj --docnum=2 %s -DPHNUM=1 -o %t7
# RUN: llvm-readelf --file-headers %t7 | FileCheck %s --check-prefix=PHNUM

# PHNUM: Number of program headers: 1{{$}}

## Override the e_phentsize field.
# RUN: yaml2obj --docnum=2 %s -DPHENTSIZE=1 -o %t8
# RUN: not llvm-readelf --file-headers %t8 2>&1 | FileCheck %s --check-prefix=PHENTSIZE

# PHENTSIZE: invalid e_phentsize: 1{{$}}
6 changes: 3 additions & 3 deletions llvm/tools/obj2yaml/elf2yaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ bool ELFDumper<ELFT>::shouldPrintSection(const ELFYAML::Section &S,
template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
auto Y = std::make_unique<ELFYAML::Object>();

// Dump header. We do not dump SHEntSize, SHOff, SHNum and SHStrNdx fields.
// When not explicitly set, the values are set by yaml2obj automatically
// and there is no need to dump them here.
// Dump header. We do not dump EPh* and SH* fields. When not explicitly set,
// the values are set by yaml2obj automatically and there is no need to dump
// them here.
Y->Header.Class = ELFYAML::ELF_ELFCLASS(Obj.getHeader()->getFileClass());
Y->Header.Data = ELFYAML::ELF_ELFDATA(Obj.getHeader()->getDataEncoding());
Y->Header.OSABI = Obj.getHeader()->e_ident[ELF::EI_OSABI];
Expand Down

0 comments on commit 3001569

Please sign in to comment.