[llvm] r372762 - [yaml2obj/obj2yaml] - Add support for .stack_sizes sections.
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 24 07:22:38 PDT 2019
Author: grimar
Date: Tue Sep 24 07:22:37 2019
New Revision: 372762
URL: http://llvm.org/viewvc/llvm-project?rev=372762&view=rev
Log:
[yaml2obj/obj2yaml] - Add support for .stack_sizes sections.
.stack_sizes is a SHT_PROGBITS section that contains pairs of
<address (4/8 bytes), stack size (uleb128)>.
This patch teach tools to parse and dump it.
Differential revision: https://reviews.llvm.org/D67757
Added:
llvm/trunk/test/tools/obj2yaml/elf-stack-sizes.yaml
llvm/trunk/test/tools/yaml2obj/elf-stack-sizes.yaml
Modified:
llvm/trunk/include/llvm/Object/ELF.h
llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h
llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp
llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
llvm/trunk/test/tools/llvm-readobj/stack-sizes.test
llvm/trunk/tools/obj2yaml/elf2yaml.cpp
Modified: llvm/trunk/include/llvm/Object/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=372762&r1=372761&r2=372762&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELF.h (original)
+++ llvm/trunk/include/llvm/Object/ELF.h Tue Sep 24 07:22:37 2019
@@ -150,15 +150,16 @@ public:
static Expected<ELFFile> create(StringRef Object);
+ bool isLE() const {
+ return getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
+ }
+
bool isMipsELF64() const {
return getHeader()->e_machine == ELF::EM_MIPS &&
getHeader()->getFileClass() == ELF::ELFCLASS64;
}
- bool isMips64EL() const {
- return isMipsELF64() &&
- getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
- }
+ bool isMips64EL() const { return isMipsELF64() && isLE(); }
Expected<Elf_Shdr_Range> sections() const;
Modified: llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h?rev=372762&r1=372761&r2=372762&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h Tue Sep 24 07:22:37 2019
@@ -117,6 +117,11 @@ struct DynamicEntry {
llvm::yaml::Hex64 Val;
};
+struct StackSizeEntry {
+ llvm::yaml::Hex64 Address;
+ llvm::yaml::Hex64 Size;
+};
+
struct Section {
enum class SectionKind {
Dynamic,
@@ -126,6 +131,7 @@ struct Section {
NoBits,
Verdef,
Verneed,
+ StackSizes,
SymtabShndxSection,
Symver,
MipsABIFlags
@@ -163,6 +169,21 @@ struct Section {
Optional<llvm::yaml::Hex64> ShSize;
};
+struct StackSizesSection : Section {
+ Optional<yaml::BinaryRef> Content;
+ Optional<std::vector<StackSizeEntry>> Entries;
+
+ StackSizesSection() : Section(SectionKind::StackSizes) {}
+
+ static bool classof(const Section *S) {
+ return S->Kind == SectionKind::StackSizes;
+ }
+
+ static bool nameMatches(StringRef Name) {
+ return Name == ".stack_sizes";
+ }
+};
+
struct DynamicSection : Section {
std::vector<DynamicEntry> Entries;
Optional<yaml::BinaryRef> Content;
@@ -326,6 +347,7 @@ struct Object {
} // end namespace ELFYAML
} // end namespace llvm
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
@@ -461,6 +483,10 @@ struct MappingTraits<ELFYAML::Symbol> {
static StringRef validate(IO &IO, ELFYAML::Symbol &Symbol);
};
+template <> struct MappingTraits<ELFYAML::StackSizeEntry> {
+ static void mapping(IO &IO, ELFYAML::StackSizeEntry &Rel);
+};
+
template <> struct MappingTraits<ELFYAML::DynamicEntry> {
static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel);
};
Modified: llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp?rev=372762&r1=372761&r2=372762&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp Tue Sep 24 07:22:37 2019
@@ -19,6 +19,7 @@
#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/YAMLTraits.h"
@@ -167,6 +168,9 @@ template <class ELFT> class ELFState {
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::DynamicSection &Section,
ContiguousBlobAccumulator &CBA);
+ void writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::StackSizesSection &Section,
+ ContiguousBlobAccumulator &CBA);
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
public:
@@ -411,6 +415,8 @@ void ELFState<ELFT>::initSectionHeaders(
writeSectionContent(SHeader, *S, CBA);
} else if (auto S = dyn_cast<ELFYAML::VerdefSection>(Sec)) {
writeSectionContent(SHeader, *S, CBA);
+ } else if (auto S = dyn_cast<ELFYAML::StackSizesSection>(Sec)) {
+ writeSectionContent(SHeader, *S, CBA);
} else {
llvm_unreachable("Unknown section type");
}
@@ -782,6 +788,26 @@ void ELFState<ELFT>::writeSectionContent
}
template <class ELFT>
+void ELFState<ELFT>::writeSectionContent(
+ Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section,
+ ContiguousBlobAccumulator &CBA) {
+ using uintX_t = typename ELFT::uint;
+ raw_ostream &OS =
+ CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
+
+ if (Section.Content) {
+ Section.Content->writeAsBinary(OS);
+ SHeader.sh_size = Section.Content->binary_size();
+ return;
+ }
+
+ for (const ELFYAML::StackSizeEntry &E : *Section.Entries) {
+ support::endian::write<uintX_t>(OS, E.Address, ELFT::TargetEndianness);
+ SHeader.sh_size += sizeof(uintX_t) + encodeULEB128(E.Size, OS);
+ }
+}
+
+template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::VerdefSection &Section,
ContiguousBlobAccumulator &CBA) {
Modified: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFYAML.cpp?rev=372762&r1=372761&r2=372762&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp Tue Sep 24 07:22:37 2019
@@ -1017,6 +1017,12 @@ static void sectionMapping(IO &IO, ELFYA
IO.mapOptional("Info", Section.Info);
}
+static void sectionMapping(IO &IO, ELFYAML::StackSizesSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Content", Section.Content);
+ IO.mapOptional("Entries", Section.Entries);
+}
+
static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) {
commonSectionMapping(IO, Section);
IO.mapOptional("Size", Section.Size, Hex64(0));
@@ -1142,20 +1148,40 @@ void MappingTraits<std::unique_ptr<ELFYA
sectionMapping(IO, *cast<ELFYAML::SymtabShndxSection>(Section.get()));
break;
default:
- if (!IO.outputting())
- Section.reset(new ELFYAML::RawContentSection());
- sectionMapping(IO, *cast<ELFYAML::RawContentSection>(Section.get()));
+ if (!IO.outputting()) {
+ StringRef Name;
+ IO.mapOptional("Name", Name, StringRef());
+
+ if (ELFYAML::StackSizesSection::nameMatches(Name))
+ Section = std::make_unique<ELFYAML::StackSizesSection>();
+ else
+ Section = std::make_unique<ELFYAML::RawContentSection>();
+ }
+
+ if (auto S = dyn_cast<ELFYAML::RawContentSection>(Section.get()))
+ sectionMapping(IO, *S);
+ else
+ sectionMapping(IO, *cast<ELFYAML::StackSizesSection>(Section.get()));
}
}
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)
+ if (const auto *RawSection =
+ dyn_cast<ELFYAML::RawContentSection>(Section.get())) {
+ 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 {};
+ }
+
+ if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(Section.get())) {
+ if (SS->Content && SS->Entries)
+ return ".stack_sizes: Content and Entries cannot be used together";
+ if (!SS->Content && !SS->Entries)
+ return ".stack_sizes: either Content or Entries tag must be specified";
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 {};
}
@@ -1184,6 +1210,13 @@ struct NormalizedMips64RelType {
} // end anonymous namespace
+void MappingTraits<ELFYAML::StackSizeEntry>::mapping(
+ IO &IO, ELFYAML::StackSizeEntry &E) {
+ assert(IO.getContext() && "The IO context is not initialized");
+ IO.mapOptional("Address", E.Address, Hex64(0));
+ IO.mapRequired("Size", E.Size);
+}
+
void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO,
ELFYAML::DynamicEntry &Rel) {
assert(IO.getContext() && "The IO context is not initialized");
Modified: llvm/trunk/test/tools/llvm-readobj/stack-sizes.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/stack-sizes.test?rev=372762&r1=372761&r2=372762&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/stack-sizes.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/stack-sizes.test Tue Sep 24 07:22:37 2019
@@ -163,7 +163,7 @@ Sections:
Size: 16
- Name: .stack_sizes
Type: SHT_PROGBITS
- Size: 1
+ Content: "00"
Link: .text
- Name: .rela.stack_sizes
Type: SHT_RELA
@@ -468,7 +468,8 @@ Sections:
Size: 16
- Name: .stack_sizes
Type: SHT_PROGBITS
- Size: 9
+ Entries:
+ - Size: 0
Link: .text
- Name: .rela.stack_sizes
Type: SHT_RELA
@@ -504,8 +505,8 @@ Sections:
Size: 8
- Name: .stack_sizes
Type: SHT_PROGBITS
- Size: 16
Link: .text
+ Entries: []
- Name: .rela.stack_sizes
Type: SHT_RELA
Info: .stack_sizes
Added: llvm/trunk/test/tools/obj2yaml/elf-stack-sizes.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/obj2yaml/elf-stack-sizes.yaml?rev=372762&view=auto
==============================================================================
--- llvm/trunk/test/tools/obj2yaml/elf-stack-sizes.yaml (added)
+++ llvm/trunk/test/tools/obj2yaml/elf-stack-sizes.yaml Tue Sep 24 07:22:37 2019
@@ -0,0 +1,88 @@
+## Check how obj2yaml produces YAML .stack_sizes descriptions.
+
+## Check that obj2yaml uses the "Entries" tag to describe a .stack_sizes section
+## when it can extract <address, size> pairs.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=VALID
+
+# VALID: --- !ELF
+# VALID-NEXT: FileHeader:
+# VALID-NEXT: Class: ELFCLASS64
+# VALID-NEXT: Data: ELFDATA2LSB
+# VALID-NEXT: Type: ET_EXEC
+# VALID-NEXT: Machine: EM_X86_64
+# VALID-NEXT: Sections:
+# VALID-NEXT: - Name: .stack_sizes
+# VALID-NEXT: Type: SHT_PROGBITS
+# VALID-NEXT: Entries:
+# VALID-NEXT: - Address: 0x0000000000000010
+# VALID-NEXT: Size: 0x0000000000000020
+# VALID-NEXT: - Address: 0x0000000000000030
+# VALID-NEXT: Size: 0x0000000000000040
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Content: "100000000000000020300000000000000040"
+
+## Check that obj2yaml uses the "Content" tag to describe a .stack_sizes section
+## when it can't extract the entries, for example, when section data is truncated.
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=INVALID
+
+# INVALID: --- !ELF
+# INVALID-NEXT: FileHeader:
+# INVALID-NEXT: Class: ELFCLASS64
+# INVALID-NEXT: Data: ELFDATA2LSB
+# INVALID-NEXT: Type: ET_EXEC
+# INVALID-NEXT: Machine: EM_X86_64
+# INVALID-NEXT: Sections:
+# INVALID-NEXT: - Name: .stack_sizes
+# INVALID-NEXT: Type: SHT_PROGBITS
+# INVALID-NEXT: Content: '1000000000000000203000000000000000'
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Content: "1000000000000000203000000000000000"
+
+## Check obj2yaml can dump empty .stack_sizes.
+
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=EMPTY
+
+# EMPTY: --- !ELF
+# EMPTY-NEXT: FileHeader:
+# EMPTY-NEXT: Class: ELFCLASS64
+# EMPTY-NEXT: Data: ELFDATA2LSB
+# EMPTY-NEXT: Type: ET_EXEC
+# EMPTY-NEXT: Machine: EM_X86_64
+# EMPTY-NEXT: Sections:
+# EMPTY-NEXT: - Name: .stack_sizes
+# EMPTY-NEXT: Type: SHT_PROGBITS
+# EMPTY-NEXT: Content: ''
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Content: ""
Added: llvm/trunk/test/tools/yaml2obj/elf-stack-sizes.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/elf-stack-sizes.yaml?rev=372762&view=auto
==============================================================================
--- llvm/trunk/test/tools/yaml2obj/elf-stack-sizes.yaml (added)
+++ llvm/trunk/test/tools/yaml2obj/elf-stack-sizes.yaml Tue Sep 24 07:22:37 2019
@@ -0,0 +1,229 @@
+## Check how yaml2obj produces .stack_sizes sections.
+
+## Test the following cases when the .stack_sizes Content field is specified:
+## 1) We can produce a .stack_sizes section from a description with
+## a valid section content.
+## 2) We can produce an incorrect .stack_sizes section from a description with
+## a broken (truncated) section content.
+## 3) We can produce an empty .stack_sizes section from a description with
+## empty section content.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-readobj --sections --section-data %t1 | FileCheck %s
+
+## Case 1: valid content.
+# CHECK: Section {
+# CHECK: Index: 1
+# CHECK-NEXT: Name: .stack_sizes (1)
+# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x40
+# CHECK-NEXT: Size: 9
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 0
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 10000000 00000000 20
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+
+## Case 2: truncated content.
+# CHECK: Name: .stack_sizes
+# CHECK: Size:
+# CHECK-SAME: 8
+# CHECK: SectionData (
+# CHECK-NEXT: 0000: 10000000 00000000
+
+## Case 3: empty content.
+# CHECK: Name: .stack_sizes
+# CHECK: Size:
+# CHECK-SAME: 0
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+## Valid.
+ - Name: '.stack_sizes [1]'
+ Type: SHT_PROGBITS
+ Content: "100000000000000020"
+## Truncated.
+ - Name: '.stack_sizes [2]'
+ Type: SHT_PROGBITS
+ Content: "1000000000000000"
+## Empty.
+ - Name: '.stack_sizes [3]'
+ Type: SHT_PROGBITS
+ Content: ""
+
+## Check we can describe .stack_sizes section using <address, size> pairs.
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefix=ENTRIES-LE64-BOTH
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-readobj --sections --section-data %t3 | FileCheck %s --check-prefix=ENTRIES-BE64-BOTH
+# RUN: yaml2obj --docnum=4 %s -o %t4
+# RUN: llvm-readobj --sections --section-data %t4 | FileCheck %s --check-prefix=ENTRIES-LE32-BOTH
+# RUN: yaml2obj --docnum=5 %s -o %t5
+# RUN: llvm-readobj --sections --section-data %t5 | FileCheck %s --check-prefix=ENTRIES-BE32-BOTH
+
+# ENTRIES-LE64-BOTH: Name: .stack_sizes
+# ENTRIES-LE64-BOTH: SectionData (
+# ENTRIES-LE64-BOTH-NEXT: 0000: 10000000 00000000 20300000 00000000 |
+# ENTRIES-LE64-BOTH-NEXT: 0010: 0040 |
+
+# ENTRIES-BE64-BOTH: Name: .stack_sizes
+# ENTRIES-BE64-BOTH: SectionData (
+# ENTRIES-BE64-BOTH-NEXT: 0000: 00000000 00000010 20000000 00000000 |
+# ENTRIES-BE64-BOTH-NEXT: 0010: 3040
+
+# ENTRIES-LE32-BOTH: Name: .stack_sizes
+# ENTRIES-LE32-BOTH: SectionData (
+# ENTRIES-LE32-BOTH-NEXT: 0000: 10000000 20300000 0040 |
+
+# ENTRIES-BE32-BOTH: Name: .stack_sizes
+# ENTRIES-BE32-BOTH: SectionData (
+# ENTRIES-BE32-BOTH-NEXT: 0000: 00000010 20000000 3040 |
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Entries:
+ - Address: 0x10
+ Size: 0x20
+ - Address: 0x30
+ Size: 0x40
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2MSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Entries:
+ - Address: 0x10
+ Size: 0x20
+ - Address: 0x30
+ Size: 0x40
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_386
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Entries:
+ - Address: 0x10
+ Size: 0x20
+ - Address: 0x30
+ Size: 0x40
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2MSB
+ Type: ET_EXEC
+ Machine: EM_386
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Entries:
+ - Address: 0x10
+ Size: 0x20
+ - Address: 0x30
+ Size: 0x40
+
+## Check we can omit the "Address" tag. In this case the address will be zero.
+
+# RUN: yaml2obj --docnum=6 %s -o %t6
+# RUN: llvm-readobj --sections --section-data %t6 | FileCheck %s --check-prefix=ENTRIES-NOADDR
+
+# ENTRIES-NOADDR: Name: .stack_sizes
+# ENTRIES-NOADDR: SectionData (
+# ENTRIES-NOADDR-NEXT: 0000: 00000000 00000000 10000000 00000000 |
+# ENTRIES-NOADDR-NEXT: 0010: 0020 |
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Entries:
+ - Size: 0x10
+ - Size: 0x20
+
+## Check that "Size" tag is mandatory when we describe .stack_sizes using "Entries".
+
+# RUN: not yaml2obj --docnum=7 %s 2>&1 | FileCheck %s --check-prefix=ENTRIES-NOSIZE
+
+# ENTRIES-NOSIZE: error: missing required key 'Size'
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Entries:
+ - Address: 0x10
+
+## Check we can't use both "Content" and "Entries" tags at the same time.
+
+# RUN: not yaml2obj --docnum=8 %s 2>&1 | FileCheck %s --check-prefix=ENTRIES-AND-CONTENT
+
+# ENTRIES-AND-CONTENT: error: .stack_sizes: Content and Entries cannot be used together
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
+ Content: "00"
+ Entries:
+ - Address: 0x10
+ Size: 0x20
+
+## Check we must specify either "Content" or "Entries" tag when describing .stack_sizes.
+
+# RUN: not yaml2obj --docnum=9 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS
+
+# NO-TAGS: error: .stack_sizes: either Content or Entries tag must be specified
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .stack_sizes
+ Type: SHT_PROGBITS
Modified: llvm/trunk/tools/obj2yaml/elf2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/elf2yaml.cpp?rev=372762&r1=372761&r2=372762&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/elf2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/elf2yaml.cpp Tue Sep 24 07:22:37 2019
@@ -11,6 +11,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/ObjectYAML/ELFYAML.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/YAMLTraits.h"
@@ -67,6 +68,10 @@ class ELFDumper {
Expected<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr);
Expected<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr);
Expected<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr);
+ Expected<ELFYAML::StackSizesSection *>
+ dumpStackSizesSection(const Elf_Shdr *Shdr);
+
+ Expected<ELFYAML::Section *> dumpSpecialSection(const Elf_Shdr *Shdr);
public:
ELFDumper(const object::ELFFile<ELFT> &O);
@@ -284,6 +289,17 @@ template <class ELFT> Expected<ELFYAML::
LLVM_FALLTHROUGH;
}
default: {
+ // Recognize some special SHT_PROGBITS sections by name.
+ if (Sec.sh_type == ELF::SHT_PROGBITS) {
+ Expected<ELFYAML::Section *> SpecialSecOrErr = dumpSpecialSection(&Sec);
+ if (!SpecialSecOrErr)
+ return SpecialSecOrErr.takeError();
+ if (*SpecialSecOrErr) {
+ Y->Sections.emplace_back(*SpecialSecOrErr);
+ break;
+ }
+ }
+
Expected<ELFYAML::RawContentSection *> SecOrErr =
dumpContentSection(&Sec);
if (!SecOrErr)
@@ -433,6 +449,18 @@ Error ELFDumper<ELFT>::dumpCommonSection
}
template <class ELFT>
+Expected<ELFYAML::Section *>
+ELFDumper<ELFT>::dumpSpecialSection(const Elf_Shdr *Shdr) {
+ auto NameOrErr = getUniquedSectionName(Shdr);
+ if (!NameOrErr)
+ return NameOrErr.takeError();
+
+ if (ELFYAML::StackSizesSection::nameMatches(*NameOrErr))
+ return dumpStackSizesSection(Shdr);
+ return nullptr;
+}
+
+template <class ELFT>
Error ELFDumper<ELFT>::dumpCommonRelocationSection(
const Elf_Shdr *Shdr, ELFYAML::RelocationSection &S) {
if (Error E = dumpCommonSection(Shdr, S))
@@ -451,6 +479,39 @@ Error ELFDumper<ELFT>::dumpCommonRelocat
}
template <class ELFT>
+Expected<ELFYAML::StackSizesSection *>
+ELFDumper<ELFT>::dumpStackSizesSection(const Elf_Shdr *Shdr) {
+ auto S = std::make_unique<ELFYAML::StackSizesSection>();
+ if (Error E = dumpCommonSection(Shdr, *S))
+ return std::move(E);
+
+ auto ContentOrErr = Obj.getSectionContents(Shdr);
+ if (!ContentOrErr)
+ return ContentOrErr.takeError();
+
+ ArrayRef<uint8_t> Content = *ContentOrErr;
+ DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4);
+
+ std::vector<ELFYAML::StackSizeEntry> Entries;
+ DataExtractor::Cursor Cur(0);
+ while (Cur && Cur.tell() < Content.size()) {
+ uint64_t Address = Data.getAddress(Cur);
+ uint64_t Size = Data.getULEB128(Cur);
+ Entries.push_back({Address, Size});
+ }
+
+ if (Content.empty() || !Cur) {
+ // If .stack_sizes cannot be decoded, we dump it as an array of bytes.
+ consumeError(Cur.takeError());
+ S->Content = yaml::BinaryRef(Content);
+ } else {
+ S->Entries = std::move(Entries);
+ }
+
+ return S.release();
+}
+
+template <class ELFT>
Expected<ELFYAML::DynamicSection *>
ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) {
auto S = std::make_unique<ELFYAML::DynamicSection>();
More information about the llvm-commits
mailing list