Skip to content

Commit

Permalink
[yaml2obj/obj2yaml] - Make RawContentSection::Content and RawContentS…
Browse files Browse the repository at this point in the history
…ection::Size optional

This is a follow-up for D62809.

Content and Size fields should be optional as was discussed in comments
of the D62809's thread. With that, we can describe a specific string table and
symbol table sections in a more correct way and also show appropriate errors.

The patch adds lots of test cases where the behavior is described in details.

Differential revision: https://reviews.llvm.org/D62957

llvm-svn: 362931
  • Loading branch information
George Rimar committed Jun 10, 2019
1 parent 1f73bbb commit 1e41007
Show file tree
Hide file tree
Showing 11 changed files with 809 additions and 53 deletions.
4 changes: 2 additions & 2 deletions llvm/include/llvm/ObjectYAML/ELFYAML.h
Expand Up @@ -151,8 +151,8 @@ struct DynamicSection : Section {
};

struct RawContentSection : Section {
yaml::BinaryRef Content;
llvm::yaml::Hex64 Size;
Optional<yaml::BinaryRef> Content;
Optional<llvm::yaml::Hex64> Size;
llvm::yaml::Hex64 Info;

RawContentSection() : Section(SectionKind::RawContent) {}
Expand Down
11 changes: 7 additions & 4 deletions llvm/lib/ObjectYAML/ELFYAML.cpp
Expand Up @@ -914,7 +914,7 @@ static void sectionMapping(IO &IO, ELFYAML::DynamicSection &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()));
IO.mapOptional("Size", Section.Size);
IO.mapOptional("Info", Section.Info, Hex64(0));
}

Expand Down Expand Up @@ -1042,9 +1042,12 @@ 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";
if (!RawSection)
return {};
if (RawSection->Size && RawSection->Content &&
(uint64_t)(*RawSection->Size) < RawSection->Content->binary_size())
return "Section size must be greater than or equal to the content size";
return {};
}

namespace {
Expand Down
7 changes: 0 additions & 7 deletions llvm/test/Object/obj2yaml.test
Expand Up @@ -389,7 +389,6 @@ ELF-MIPSEL-NEXT: - Name: .data
ELF-MIPSEL-NEXT: Type: SHT_PROGBITS
ELF-MIPSEL-NEXT: Flags: [ SHF_WRITE, SHF_ALLOC ]
ELF-MIPSEL-NEXT: AddressAlign: 0x0000000000000004
ELF-MIPSEL-NEXT: Content: ''
ELF-MIPSEL-NEXT: - Name: .bss
ELF-MIPSEL-NEXT: Type: SHT_NOBITS
ELF-MIPSEL-NEXT: Flags: [ SHF_WRITE, SHF_ALLOC ]
Expand All @@ -398,7 +397,6 @@ ELF-MIPSEL-NEXT: Size: 0x0000000000000004
ELF-MIPSEL-NEXT: - Name: .mdebug.abi32
ELF-MIPSEL-NEXT: Type: SHT_PROGBITS
ELF-MIPSEL-NEXT: AddressAlign: 0x0000000000000001
ELF-MIPSEL-NEXT: Content: ''
ELF-MIPSEL-NEXT: - Name: .rodata.str1.1
ELF-MIPSEL-NEXT: Type: SHT_PROGBITS
ELF-MIPSEL-NEXT: Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
Expand Down Expand Up @@ -477,7 +475,6 @@ ELF-MIPS64EL-NEXT: - Name: .text
ELF-MIPS64EL-NEXT: Type: SHT_PROGBITS
ELF-MIPS64EL-NEXT: Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
ELF-MIPS64EL-NEXT: AddressAlign: 0x0000000000000010
ELF-MIPS64EL-NEXT: Content: ''
ELF-MIPS64EL-NEXT: - Name: .data
ELF-MIPS64EL-NEXT: Type: SHT_PROGBITS
ELF-MIPS64EL-NEXT: Flags: [ SHF_WRITE, SHF_ALLOC ]
Expand Down Expand Up @@ -506,7 +503,6 @@ ELF-MIPS64EL-NEXT: Content: '012800000000000000000000000000000000000
ELF-MIPS64EL-NEXT: - Name: .pdr
ELF-MIPS64EL-NEXT: Type: SHT_PROGBITS
ELF-MIPS64EL-NEXT: AddressAlign: 0x0000000000000004
ELF-MIPS64EL-NEXT: Content: ''
ELF-MIPS64EL-NEXT: Symbols:
ELF-MIPS64EL-NEXT: - Name: .text
ELF-MIPS64EL-NEXT: Type: STT_SECTION
Expand Down Expand Up @@ -550,7 +546,6 @@ ELF-X86-64-NEXT: - Name: .note.GNU-stack
ELF-X86-64-NEXT: Type: SHT_PROGBITS
ELF-X86-64-NEXT: Address: 0x0000000000000033
ELF-X86-64-NEXT: AddressAlign: 0x0000000000000001
ELF-X86-64-NEXT: Content: ''
ELF-X86-64-NEXT: - Name: .rela.text
ELF-X86-64-NEXT: Type: SHT_RELA
ELF-X86-64-NEXT: Address: 0x0000000000000038
Expand Down Expand Up @@ -610,7 +605,6 @@ ELF-AVR-NEXT: Type: SHT_PROGBITS
ELF-AVR-NEXT: Flags: [ SHF_WRITE, SHF_ALLOC ]
ELF-AVR-NEXT: Address: 0x0000000000800060
ELF-AVR-NEXT: AddressAlign: 0x0000000000000001
ELF-AVR-NEXT: Content: ''
ELF-AVR-NEXT: Symbols:
ELF-AVR-NEXT: - Name: .text
ELF-AVR-NEXT: Type: STT_SECTION
Expand Down Expand Up @@ -706,7 +700,6 @@ ELF-X86-64-UNWIND: - Name: .eh_frame
ELF-X86-64-UNWIND-NEXT: Type: SHT_X86_64_UNWIND
ELF-X86-64-UNWIND-NEXT: Flags: [ SHF_ALLOC ]
ELF-X86-64-UNWIND-NEXT: AddressAlign: 0x0000000000000001
ELF-X86-64-UNWIND-NEXT: Content: ''

RUN: not obj2yaml %t.blah 2>&1 | FileCheck --check-prefix=ENOENT %s
ENOENT: Error reading file: {{.*}}.blah: {{[Nn]}}o such file or directory
2 changes: 1 addition & 1 deletion llvm/test/Object/yaml2obj-elf-section-invalid-size.yaml
Expand Up @@ -20,7 +20,7 @@ Sections:
Content: 0000000000000000
Size: 2

# CHECK: YAML:17:5: error: Section size must be greater or equal to the content size
# CHECK: YAML:17:5: error: Section size must be greater than or equal to the content size
# CHECK-NEXT: - Name: .data
# CHECK-NEXT: ^
# CHECK-NEXT: yaml2obj: Failed to parse YAML file!
1 change: 0 additions & 1 deletion llvm/test/tools/obj2yaml/elf-shinfo.yaml
Expand Up @@ -5,7 +5,6 @@

# CHECK: - Name: .test
# CHECK-NEXT: Type: SHT_PROGBITS
# CHECK-NEXT: Content: ''
# CHECK-NEXT: Info: 0x000000000000002A

--- !ELF
Expand Down
222 changes: 222 additions & 0 deletions llvm/test/tools/yaml2obj/dynsymtab-implicit-sections-size-content.yaml
@@ -0,0 +1,222 @@
## For implicit dynamic symbol table sections, `Size` and/or `Content`
## fields can also be specified in YAML. Here we test the behavior in
## different cases.

## When no `Size` or `Content` is specified for a dynamic symbol table section,
## yaml2obj writes the default content.

# RUN: yaml2obj --docnum=1 %s -o %t1
# RUN: llvm-readelf %t1 --dyn-symbols | FileCheck %s --check-prefix=CASE1

# CASE1: Symbol table '.dynsym' contains 2 entries:
# CASE1-NEXT: Num: Value Size Type Bind Vis Ndx Name
# CASE1-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
# CASE1-NEXT: 1: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND foo
# CASE1-EMPTY:

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .dynsym
Type: SHT_DYNSYM
DynamicSymbols:
- Name: foo
Binding: STB_GLOBAL

## Specifying both `Size` and symbols at the same time is not allowed.
# RUN: not yaml2obj --docnum=2 %s -o %t2 2>&1 | FileCheck %s --check-prefix=CASE2

# CASE2: error: Cannot specify both `Size` and `DynamicSymbols` for symbol table section '.dynsym'.

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .dynsym
Type: SHT_DYNSYM
Size: 0x100
DynamicSymbols:
- Name: foo
Binding: STB_GLOBAL

## Specifying both `Content` and symbols at the same time is not allowed.
# RUN: not yaml2obj --docnum=3 %s -o %t3 2>&1 | FileCheck %s --check-prefix=CASE3

# CASE3: error: Cannot specify both `Content` and `DynamicSymbols` for symbol table section '.dynsym'.

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .dynsym
Type: SHT_DYNSYM
Content: "00"
DynamicSymbols:
- Name: foo
Binding: STB_GLOBAL

## Check we can use just `Content` to emit custom data in the symbol table section.
# RUN: yaml2obj --docnum=4 %s -o %t4
# RUN: llvm-readobj --section-data -S %t4 | FileCheck %s --check-prefix=CASE4

# CASE4: Name: .dynsym
# CASE4-NEXT: Type: SHT_DYNSYM
# CASE4-NEXT: Flags [
# CASE4-NEXT: SHF_ALLOC
# CASE4-NEXT: ]
# CASE4-NEXT: Address: 0x0
# CASE4-NEXT: Offset: 0x1C0
# CASE4-NEXT: Size: 2
# CASE4-NEXT: Link: 2
# CASE4-NEXT: Info: 0
# CASE4-NEXT: AddressAlignment: 0
# CASE4-NEXT: EntrySize: 24
# CASE4-NEXT: SectionData (
# CASE4-NEXT: 0000: 0123
# CASE4-NEXT: )

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .dynsym
Type: SHT_DYNSYM
Content: "0123"
## TODO: .dynstr here is needed to set a proper Link for .dynsym.
## Without this, llvm-readobj reports an error.
## See https://bugs.llvm.org/show_bug.cgi?id=42215.
- Name: .dynstr
Type: SHT_STRTAB
Content: "00"

## Check we can use just `Size` to emit custom data filled with zeroes
## in the symbol table section.
# RUN: yaml2obj --docnum=5 %s -o %t5
# RUN: llvm-readobj --section-data -S %t5 | FileCheck %s --check-prefix=CASE5

# CASE5: Name: .dynsym
# CASE5-NEXT: Type: SHT_DYNSYM
# CASE5-NEXT: Flags [
# CASE5-NEXT: SHF_ALLOC
# CASE5-NEXT: ]
# CASE5-NEXT: Address: 0x0
# CASE5-NEXT: Offset: 0x1C0
# CASE5-NEXT: Size: 5
# CASE5-NEXT: Link: 2
# CASE5-NEXT: Info: 0
# CASE5-NEXT: AddressAlignment: 0
# CASE5-NEXT: EntrySize: 24
# CASE5-NEXT: SectionData (
# CASE5-NEXT: 0000: 00000000 00
# CASE5-NEXT: )

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .dynsym
Type: SHT_DYNSYM
Size: 5
## TODO: .dynstr here is needed to set a proper Link for .dynsym.
## Without this, llvm-readobj reports an error.
## See https://bugs.llvm.org/show_bug.cgi?id=42215.
- Name: .dynstr
Type: SHT_STRTAB
Content: "00"

## Check we can specify both `Size` and `Content` when size is greater
## than content size. In this case zeroes are added as padding
## after after the specified content.

# RUN: yaml2obj --docnum=6 %s -o %t6
# RUN: llvm-readobj %t6 --section-data -S | FileCheck %s --check-prefix=CASE6

# CASE6: Name: .dynsym
# CASE6-NEXT: Type: SHT_DYNSYM
# CASE6-NEXT: Flags [
# CASE6-NEXT: SHF_ALLOC
# CASE6-NEXT: ]
# CASE6-NEXT: Address: 0x0
# CASE6-NEXT: Offset: 0x1C0
# CASE6-NEXT: Size: 4
# CASE6-NEXT: Link: 2
# CASE6-NEXT: Info: 0
# CASE6-NEXT: AddressAlignment: 0
# CASE6-NEXT: EntrySize: 24
# CASE6-NEXT: SectionData (
# CASE6-NEXT: 0000: 01230000
# CASE6-NEXT: )

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .dynsym
Type: SHT_DYNSYM
Content: "0123"
Size: 4
## TODO: .dynstr here is needed to set a proper Link for .dynsym.
## Without this, llvm-readobj reports an error.
## See https://bugs.llvm.org/show_bug.cgi?id=42215.
- Name: .dynstr
Type: SHT_STRTAB
Content: "00"

## Check we can specify both `Size` and `Content` when size is
## equal to content size.

# RUN: yaml2obj --docnum=7 %s -o %t7
# RUN: llvm-readobj --section-data -S %t7 | FileCheck %s --check-prefix=CASE7

# CASE7: Name: .dynsym
# CASE7-NEXT: Type: SHT_DYNSYM
# CASE7-NEXT: Flags [
# CASE7-NEXT: SHF_ALLOC
# CASE7-NEXT: ]
# CASE7-NEXT: Address: 0x0
# CASE7-NEXT: Offset: 0x1C0
# CASE7-NEXT: Size: 2
# CASE7-NEXT: Link: 2
# CASE7-NEXT: Info: 0
# CASE7-NEXT: AddressAlignment: 0
# CASE7-NEXT: EntrySize: 24
# CASE7-NEXT: SectionData (
# CASE7-NEXT: 0000: 0123
# CASE7-NEXT: )

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .dynsym
Type: SHT_DYNSYM
Content: "0123"
Size: 2
## TODO: .dynstr here is needed to set a proper Link for .dynsym.
## Without this, llvm-readobj reports an error.
## See https://bugs.llvm.org/show_bug.cgi?id=42215.
- Name: .dynstr
Type: SHT_STRTAB
Content: "00"

0 comments on commit 1e41007

Please sign in to comment.