[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