[llvm] 373e98a - [ObjectYAML][DWARF] Add DWARF entry in ELFYAML.

Xing GUO via llvm-commits llvm-commits at lists.llvm.org
Thu May 28 19:53:49 PDT 2020


Author: Xing GUO
Date: 2020-05-29T10:57:18+08:00
New Revision: 373e98a3a5f882661acf67c1f99e89b838aa2ad2

URL: https://github.com/llvm/llvm-project/commit/373e98a3a5f882661acf67c1f99e89b838aa2ad2
DIFF: https://github.com/llvm/llvm-project/commit/373e98a3a5f882661acf67c1f99e89b838aa2ad2.diff

LOG: [ObjectYAML][DWARF] Add DWARF entry in ELFYAML.

This patch adds a new DWARF entry in ELF YAML file.

Reviewed By: grimar

Differential Revision: https://reviews.llvm.org/D80203

Added: 
    llvm/test/tools/yaml2obj/ELF/DWARF/debug-str.yaml

Modified: 
    llvm/include/llvm/ObjectYAML/DWARFYAML.h
    llvm/include/llvm/ObjectYAML/ELFYAML.h
    llvm/lib/ObjectYAML/DWARFYAML.cpp
    llvm/lib/ObjectYAML/ELFEmitter.cpp
    llvm/lib/ObjectYAML/ELFYAML.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
index 11b41e13b8e2..806dd13715e5 100644
--- a/llvm/include/llvm/ObjectYAML/DWARFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_OBJECTYAML_DWARFYAML_H
 #define LLVM_OBJECTYAML_DWARFYAML_H
 
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/Support/YAMLTraits.h"
@@ -171,6 +172,8 @@ struct Data {
   std::vector<LineTable> DebugLines;
 
   bool isEmpty() const;
+
+  SetVector<StringRef> getUsedSectionNames() const;
 };
 
 } // end namespace DWARFYAML

diff  --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 5d3384925631..5b96283b786e 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -16,6 +16,7 @@
 #define LLVM_OBJECTYAML_ELFYAML_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ObjectYAML/DWARFYAML.h"
 #include "llvm/ObjectYAML/YAML.h"
 #include "llvm/Support/YAMLTraits.h"
 #include <cstdint>
@@ -529,6 +530,7 @@ struct Object {
   // being a single SHT_SYMTAB section are upheld.
   Optional<std::vector<Symbol>> Symbols;
   Optional<std::vector<Symbol>> DynamicSymbols;
+  Optional<DWARFYAML::Data> DWARF;
 
   std::vector<Section *> getSections() {
     std::vector<Section *> Ret;

diff  --git a/llvm/lib/ObjectYAML/DWARFYAML.cpp b/llvm/lib/ObjectYAML/DWARFYAML.cpp
index 7ba73783cf63..4805f727e0ce 100644
--- a/llvm/lib/ObjectYAML/DWARFYAML.cpp
+++ b/llvm/lib/ObjectYAML/DWARFYAML.cpp
@@ -23,6 +23,13 @@ bool DWARFYAML::Data::isEmpty() const {
          DebugLines.empty();
 }
 
+SetVector<StringRef> DWARFYAML::Data::getUsedSectionNames() const {
+  SetVector<StringRef> SecNames;
+  if (!DebugStrings.empty())
+    SecNames.insert("debug_str");
+  return SecNames;
+}
+
 namespace yaml {
 
 void MappingTraits<DWARFYAML::Data>::mapping(IO &IO, DWARFYAML::Data &DWARF) {

diff  --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 2b7bad674fa4..254cbef2f60a 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -13,10 +13,13 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/ObjectYAML/DWARFEmitter.h"
+#include "llvm/ObjectYAML/DWARFYAML.h"
 #include "llvm/ObjectYAML/ELFYAML.h"
 #include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Support/EndianStream.h"
@@ -149,6 +152,9 @@ template <class ELFT> class ELFState {
                                StringTableBuilder &STB,
                                ContiguousBlobAccumulator &CBA,
                                ELFYAML::Section *YAMLSec);
+  void initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
+                              ContiguousBlobAccumulator &CBA,
+                              ELFYAML::Section *YAMLSec);
   void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
                               std::vector<Elf_Shdr> &SHeaders);
 
@@ -274,6 +280,11 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
     ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"});
   if (Doc.Symbols)
     ImplicitSections.push_back(".symtab");
+  if (Doc.DWARF)
+    for (StringRef DebugSecName : Doc.DWARF->getUsedSectionNames()) {
+      std::string SecName = ("." + DebugSecName).str();
+      ImplicitSections.push_back(StringRef(SecName).copy(StringAlloc));
+    }
   ImplicitSections.insert(ImplicitSections.end(), {".strtab", ".shstrtab"});
 
   // Insert placeholders for implicit sections that are not
@@ -447,7 +458,13 @@ bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA,
     initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
   else if (SecName == ".dynstr")
     initStrtabSectionHeader(Header, SecName, DotDynstr, CBA, YAMLSec);
-  else
+  else if (SecName.startswith(".debug_")) {
+    // If a ".debug_*" section's type is a preserved one, e.g., SHT_DYNAMIC, we
+    // will not treat it as a debug section.
+    if (YAMLSec && !isa<ELFYAML::RawContentSection>(YAMLSec))
+      return false;
+    initDWARFSectionHeader(Header, SecName, CBA, YAMLSec);
+  } else
     return false;
 
   LocationCounter += Header.sh_size;
@@ -791,6 +808,69 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
   assignSectionAddress(SHeader, YAMLSec);
 }
 
+static bool shouldEmitDWARF(DWARFYAML::Data &DWARF, StringRef Name) {
+  SetVector<StringRef> DebugSecNames = DWARF.getUsedSectionNames();
+  return Name.consume_front(".") && DebugSecNames.count(Name);
+}
+
+template <class ELFT>
+uint64_t emitDWARF(typename ELFT::Shdr &SHeader, StringRef Name,
+                   const DWARFYAML::Data &DWARF, raw_ostream &OS) {
+  uint64_t BeginOffset = OS.tell();
+  if (Name == ".debug_str")
+    DWARFYAML::EmitDebugStr(OS, DWARF);
+  else
+    llvm_unreachable("unexpected emitDWARF() call");
+
+  return OS.tell() - BeginOffset;
+}
+
+template <class ELFT>
+void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
+                                            ContiguousBlobAccumulator &CBA,
+                                            ELFYAML::Section *YAMLSec) {
+  zero(SHeader);
+  SHeader.sh_name = DotShStrtab.getOffset(ELFYAML::dropUniqueSuffix(Name));
+  SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_PROGBITS;
+  SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;
+  SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign,
+                                    YAMLSec ? YAMLSec->Offset : None);
+
+  ELFYAML::RawContentSection *RawSec =
+      dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);
+  if (Doc.DWARF && shouldEmitDWARF(*Doc.DWARF, Name)) {
+    if (RawSec && (RawSec->Content || RawSec->Size))
+      reportError("cannot specify section '" + Name +
+                  "' contents in the 'DWARF' entry and the 'Content' "
+                  "or 'Size' in the 'Sections' entry at the same time");
+    else
+      SHeader.sh_size = emitDWARF<ELFT>(SHeader, Name, *Doc.DWARF, CBA.getOS());
+  } else if (RawSec)
+    SHeader.sh_size = writeContent(CBA.getOS(), RawSec->Content, RawSec->Size);
+  else
+    llvm_unreachable("debug sections can only be initialized via the 'DWARF' "
+                     "entry or a RawContentSection");
+
+  if (YAMLSec && YAMLSec->EntSize)
+    SHeader.sh_entsize = *YAMLSec->EntSize;
+  else if (Name == ".debug_str")
+    SHeader.sh_entsize = 1;
+
+  if (RawSec && RawSec->Info)
+    SHeader.sh_info = *RawSec->Info;
+
+  if (YAMLSec && YAMLSec->Flags)
+    SHeader.sh_flags = *YAMLSec->Flags;
+  else if (Name == ".debug_str")
+    SHeader.sh_flags = ELF::SHF_MERGE | ELF::SHF_STRINGS;
+
+  unsigned Link = 0;
+  if (YAMLSec && !YAMLSec->Link.empty() && SN2I.lookup(YAMLSec->Link, Link))
+    SHeader.sh_link = Link;
+
+  assignSectionAddress(SHeader, YAMLSec);
+}
+
 template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {
   ErrHandler(Msg);
   HasError = true;

diff  --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index d3e4d2ee3bd8..250f97d7bac5 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -1653,6 +1653,7 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
   IO.mapOptional("Sections", Object.Chunks);
   IO.mapOptional("Symbols", Object.Symbols);
   IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
+  IO.mapOptional("DWARF", Object.DWARF);
   IO.setContext(nullptr);
 }
 

diff  --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-str.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-str.yaml
new file mode 100644
index 000000000000..62d86639ad86
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-str.yaml
@@ -0,0 +1,238 @@
+## Test that yaml2obj emits .debug_str section.
+
+## a) Generate the .debug_str section from the "DWARF" entry.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1.o
+# RUN: llvm-readelf --string-dump=.debug_str %t1.o | FileCheck %s --check-prefix=DWARF-DEFAULT
+
+#      DWARF-DEFAULT: String dump of section '.debug_str':
+# DWARF-DEFAULT-NEXT: [     0] a
+# DWARF-DEFAULT-NEXT: [     2] b
+# DWARF-DEFAULT-NEXT: [     4] c
+
+## Check the default sh_type, sh_entsize, sh_info, sh_flags and sh_addralign of the
+## .debug_str section header.
+
+# RUN: llvm-readelf -S %t1.o | FileCheck %s --check-prefix=SHDRS-DEFAULT
+
+#                Name       Type     Address          Offset Size   ES Flg Lk Inf Al
+# SHDRS-DEFAULT: .debug_str PROGBITS 0000000000000000 000040 000006 01 MS  0  0   1
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+DWARF:
+  debug_str:
+    - a
+    - b
+    - c
+
+## b) Generate the .debug_str section from the raw section content.
+
+# RUN: yaml2obj --docnum=2 %s -o %t2.o
+# RUN: llvm-readelf --string-dump=.debug_str %t2.o | FileCheck %s --check-prefix=DWARF-DEFAULT
+# RUN: llvm-readelf -S %t2.o | FileCheck %s --check-prefix=SHDRS
+
+#        Name       Type     Address          Offset Size   ES Flg Lk Inf Al
+# SHDRS: .debug_str PROGBITS 0000000000000000 000040 000006 01 MS  0  0   0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:    .debug_str
+    Type:    SHT_PROGBITS
+    Content: "610062006300"
+
+## c) Generate the .debug_str section when the "Size" is specified.
+
+# RUN: yaml2obj --docnum=3 %s -o %t3.o
+# RUN: llvm-readelf -S %t3.o | FileCheck %s --check-prefix=SIZE
+# RUN: llvm-readelf --hex-dump=.debug_str %t3.o | FileCheck %s --check-prefix=SIZE-CONTENT
+
+#       Name       Type     Address          Offset Size   ES Flg Lk Inf Al
+# SIZE: .debug_str PROGBITS 0000000000000000 000040 000010 01 MS  0  0   0
+
+#       SIZE-CONTENT: Hex dump of section '.debug_str':
+#  SIZE-CONTENT-NEXT: 0x00000000 00000000 00000000 00000000 00000000 ................
+# SIZE-CONTENT-EMPTY:
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:  .debug_str
+    Type:  SHT_PROGBITS
+    Size:  0x10
+
+## d) Test that yaml2obj emits an error message when both the "Size" and the
+## "debug_str" entry are specified at the same time.
+
+# RUN: not yaml2obj --docnum=4 %s -o %t4.o 2>&1 | FileCheck %s --check-prefix=ERROR
+
+# ERROR: yaml2obj: error: cannot specify section '.debug_str' contents in the 'DWARF' entry and the 'Content' or 'Size' in the 'Sections' entry at the same time
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:  .debug_str
+    Type:  SHT_PROGBITS
+    Size:  0x10
+DWARF:
+  debug_str:
+    - a
+
+## e) Test that yaml2obj emits an error message when both the "Content" and the
+## "debug_str" entry are specified at the same time.
+
+# RUN: not yaml2obj --docnum=5 %s -o %t5.o 2>&1 | FileCheck %s --check-prefix=ERROR
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:    .debug_str
+    Type:    SHT_PROGBITS
+    Content: "6100"
+DWARF:
+  debug_str:
+    - a
+
+## f) Test that all the properties can be overridden by the section header when
+## the "debug_str" entry doesn't exist.
+
+# RUN: yaml2obj --docnum=6 %s -o %t6.o
+# RUN: llvm-readelf -S %t6.o | FileCheck %s --check-prefix=OVERRIDDEN
+
+#             Index Name       Type   Address          Offset Size   ES Flg Lk Inf Al
+# OVERRIDDEN: [ 1]  .sec       STRTAB 0000000000000000 000040 000000 00     0  0   0
+# OVERRIDDEN: [ 2]  .debug_str STRTAB 0000000000002020 000050 000006 02 A   1  1   2
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:         .sec               # Linked by .debug_str.
+    Type:         SHT_STRTAB
+  - Name:         .debug_str
+    Type:         SHT_STRTAB         # SHT_PROGBITS by default.
+    Flags:        [SHF_ALLOC]        # [SHF_STRINGS, SHF_MERGE] by default.
+    Link:         .sec               # 0 by default.
+    EntSize:      2                  # 1 by default.
+    Info:         1                  # 0 by default.
+    AddressAlign: 2                  # 0 by default.
+    Address:      0x0000000000002020 # 0x00 by default.
+    Offset:       0x00000050         # 0x40 for the first section.
+    Size:         6                  # Set the "Size" so that we can reuse the check tag "OVERRIEDDEN"
+
+## g) Test that all the properties can be overridden by the section header when
+## the "debug_str" entry is used.
+
+# RUN: yaml2obj --docnum=7 %s -o %t7.o
+# RUN: llvm-readelf --string-dump=.debug_str %t7.o | FileCheck %s --check-prefix=DWARF-DEFAULT
+# RUN: llvm-readelf -S %t7.o | FileCheck %s --check-prefix=OVERRIDDEN
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:         .sec               # Linked by .debug_str.
+    Type:         SHT_STRTAB
+  - Name:         .debug_str
+    Type:         SHT_STRTAB         # SHT_PROGBITS by default.
+    Flags:        [SHF_ALLOC]        # [SHF_STRINGS, SHF_MERGE] by default.
+    Link:         .sec               # 0 by default.
+    EntSize:      2                  # 1 by default.
+    Info:         1                  # 0 by default.
+    AddressAlign: 2                  # 1 by default.
+    Address:      0x0000000000002020 # 0x00 by default.
+    Offset:       0x00000050         # 0x40 for the first section.
+DWARF:
+  debug_str:
+    - a
+    - b
+    - c
+
+## h) Test that yaml2obj will not generate the .debug_str section when the "DWARF" entry exists
+## but the "debug_str" entry doesn't exist in the "DWARF" entry or the "Sections" entry.
+
+# RUN: yaml2obj --docnum=8 %s -o %t8.o
+# RUN: llvm-readelf -S %t8.o | FileCheck /dev/null --implicit-check-not=.debug_str
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+DWARF:
+
+## i) Test that if we try to initialize the .debug_str section with a preserved "Type", e.g.,
+## SHT_DYNAMIC, yaml2obj will treat it as a dynamic section and discard the content in the
+## "DWARF" entry.
+
+# RUN: yaml2obj --docnum=9 %s -o %t9.o
+# RUN: llvm-readelf -S %t9.o | FileCheck %s --check-prefix=DYN-SHDR
+# RUN: llvm-readelf -d %t9.o | FileCheck %s --check-prefix=DYNAMIC
+
+# RUN: yaml2obj --docnum=10 %s -o %t10.o
+# RUN: llvm-readelf -S %t10.o | FileCheck %s --check-prefix=DYN-SHDR
+# RUN: llvm-readelf -d %t10.o | FileCheck %s --check-prefix=DYNAMIC
+
+#           Name       Type    Address          Offset Size   ES Flg Lk Inf Al
+# DYN-SHDR: .debug_str DYNAMIC 0000000000000000 000040 000010 10      0   0  0
+
+#      DYNAMIC: Dynamic section at offset 0x40 contains 1 entries:
+# DYNAMIC-NEXT:  Tag                Type   Name/Value
+# DYNAMIC-NEXT:  0x0000000000000000 (NULL) 0x0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name: .debug_str
+    Type: SHT_DYNAMIC
+    Entries:
+      - Tag:   DT_NULL
+        Value: 0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name: .debug_str
+    Type: SHT_DYNAMIC
+    Entries:
+      - Tag:   DT_NULL
+        Value: 0
+DWARF:
+  debug_str:
+    - a


        


More information about the llvm-commits mailing list