Skip to content

Commit

Permalink
[yaml2obj][ELF] Add an optional Size field to the YAML section decl…
Browse files Browse the repository at this point in the history
…aration.

Now the only method to configure ELF section's content and size is to assign
a hexadecimal string to the `Content` field. Unfortunately this way is
completely useless when you need to declare a really large section.

To solve this problem this patch adds one more optional field `Size`
to the `RawContentSection` structure. When yaml2obj generates an ELF file
it uses the following algorithm:
1. If both `Content` and `Size` fields are missed create an empty section.
2. If only `Content` field is missed take section length from the `Size`
   field and fill the section by zero.
3. If only `Size` field is missed create a section using data from
   the `Content` field.
4. If both `Content` and `Size` fields are provided validate that the `Size`
   value is not less than size of `Content` data. Than take section length
   from the `Size`, fill beginning of the section by `Content` and the rest
   by zero.

Examples
--------
* Create a section 0x10000 bytes long filled by zero
  Name: .data
  Type: SHT_PROGBITS
  Flags: [ SHF_ALLOC ]
  Size: 0x10000

* Create a section 0x10000 bytes long starting from 'CA' 'FE' 'BA' 'BE'
  Name: .data
  Type: SHT_PROGBITS
  Flags: [ SHF_ALLOC ]
  Content: CAFEBABE
  Size: 0x10000

The patch reviewed by Michael Spencer.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208995 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
atanasyan committed May 16, 2014
1 parent b32cee5 commit 19ab8f8
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 2 deletions.
2 changes: 2 additions & 0 deletions include/llvm/Object/ELFYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct Section {
};
struct RawContentSection : Section {
object::yaml::BinaryRef Content;
llvm::yaml::Hex64 Size;
RawContentSection() : Section(SectionKind::RawContent) {}
static bool classof(const Section *S) {
return S->Kind == SectionKind::RawContent;
Expand Down Expand Up @@ -193,6 +194,7 @@ template <> struct MappingTraits<ELFYAML::Relocation> {
template <>
struct MappingTraits<std::unique_ptr<ELFYAML::Section>> {
static void mapping(IO &IO, std::unique_ptr<ELFYAML::Section> &Section);
static StringRef validate(IO &io, std::unique_ptr<ELFYAML::Section> &Section);
};

template <>
Expand Down
9 changes: 9 additions & 0 deletions lib/Object/ELFYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) {
static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) {
commonSectionMapping(IO, Section);
IO.mapOptional("Content", Section.Content);
IO.mapOptional("Size", Section.Size, Hex64(Section.Content.binary_size()));
}

static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) {
Expand Down Expand Up @@ -687,6 +688,14 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping(
}
}

StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate(
IO &io, std::unique_ptr<ELFYAML::Section> &Section) {
const auto *RawSection = dyn_cast<ELFYAML::RawContentSection>(Section.get());
if (!RawSection || RawSection->Size >= RawSection->Content.binary_size())
return StringRef();
return "Section size must be greater or equal to the content size";
}

void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO,
ELFYAML::Relocation &Rel) {
IO.mapRequired("Offset", Rel.Offset);
Expand Down
25 changes: 25 additions & 0 deletions test/Object/yaml2obj-elf-section-basic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ Sections:
Content: EBFE
AddressAlign: 2

- Name: .data
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
Address: 0xCAFECAFE
Content: FEBF
Size: 8
AddressAlign: 2

# CHECK: Section {
# CHECK: Index: 0
# CHECK: Type: SHT_NULL (0x0)
Expand All @@ -38,6 +46,23 @@ Sections:
# CHECK-NEXT: )
#
# CHECK: Section {
# CHECK: Name: .data
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x2)
# CHECK-NEXT: SHF_ALLOC (0x2)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0xCAFECAFE
# CHECK-NEXT: Offset: 0x1D0
# CHECK-NEXT: Size: 8
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 2
# CHECK-NEXT: EntrySize: 0
# CHECK-NEXT: SectionData (
# CHECK-NEXT: 0000: FEBF0000 00000000 |........|
# CHECK-NEXT: )
#
# CHECK: Section {
# CHECK: Name: .symtab (25)
# CHECK: Type: SHT_SYMTAB (0x2)
# CHECK: }
Expand Down
26 changes: 26 additions & 0 deletions test/Object/yaml2obj-elf-section-invalid-size.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# RUN: not yaml2obj -format=elf -o %t %s 2>&1 | FileCheck %s

!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: EBFE
AddressAlign: 2

- Name: .data
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
Content: 0000000000000000
Size: 2

# CHECK: YAML:17:5: error: Section size must be greater or equal to the content size
# CHECK-NEXT: - Name: .data
# CHECK-NEXT: ^
# CHECK-NEXT: yaml2obj: Failed to parse YAML file!
1 change: 1 addition & 0 deletions tools/obj2yaml/elf2yaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) {
if (error_code EC = ContentOrErr.getError())
return EC;
S->Content = object::yaml::BinaryRef(ContentOrErr.get());
S->Size = S->Content.binary_size();

return S.release();
}
Expand Down
9 changes: 7 additions & 2 deletions tools/yaml2obj/yaml2elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,14 @@ void
ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::RawContentSection &Section,
ContiguousBlobAccumulator &CBA) {
Section.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
assert(Section.Size >= Section.Content.binary_size() &&
"Section size and section content are inconsistent");
raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset);
Section.Content.writeAsBinary(OS);
for (auto i = Section.Content.binary_size(); i < Section.Size; ++i)
OS.write(0);
SHeader.sh_entsize = 0;
SHeader.sh_size = Section.Content.binary_size();
SHeader.sh_size = Section.Size;
}

template <class ELFT>
Expand Down

0 comments on commit 19ab8f8

Please sign in to comment.