[llvm] 7157264 - [DebugInfo] Add error-handling to DWARFAbbreviationDeclarationSet

Alex Langford via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 8 11:16:56 PDT 2023


Author: Alex Langford
Date: 2023-06-08T11:16:42-07:00
New Revision: 715726429ec4fc4f0f5f0f2e3dc6c3c31ce8f3a6

URL: https://github.com/llvm/llvm-project/commit/715726429ec4fc4f0f5f0f2e3dc6c3c31ce8f3a6
DIFF: https://github.com/llvm/llvm-project/commit/715726429ec4fc4f0f5f0f2e3dc6c3c31ce8f3a6.diff

LOG: [DebugInfo] Add error-handling to DWARFAbbreviationDeclarationSet

This commit aims to improve error handling in the
DWARFAbbreviationDeclarationSet class. Specifically, we change the return type
of DWARFAbbreviationDeclarationSet::extract to an llvm::Error. In doing
so, we propagate the error from DWARFAbbreviationDeclaration::extract
another layer upward.

I have built on the previous unittest for DWARFDebugAbbrev that I
wrote a few days prior.
Namely, I am verifying that the following should give an error:
- An invalid tag following a non-null code
- An invalid attribute with a valid form
- A valid attribute with an invalid form
- An incorrectly terminated DWARFAbbreviationDeclaration

Additionally, I uncovered some invalid DWARF in an unrelated dsymutil
test. Namely the last Abbreviation Decl was missing a code.
This test has been updated accordingly. However, this commit does
not fix the underlying issue: llvm-dwarfdump does not correctly
verify the debug abbreviation section to catch these kinds of
mistakes. I have updated DWARFVerifier to not dereference a
pointer without first checking it and left a FIXME for future
contributors.

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

Added: 
    

Modified: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
    llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
    llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
    llvm/test/DebugInfo/ARM/dwarfdump-rela.yaml
    llvm/test/DebugInfo/X86/dwarfdump-header-64.s
    llvm/test/DebugInfo/X86/dwarfdump-rela-dwo.s
    llvm/test/tools/dsymutil/Inputs/empty-CU.s
    llvm/test/tools/dsymutil/Inputs/swift-interface.s
    llvm/test/tools/dsymutil/X86/empty-CU.test
    llvm/test/tools/llvm-dwarfdump/X86/debug-abbrev.s
    llvm/test/tools/llvm-dwarfdump/X86/no_debug_addr.s
    llvm/test/tools/llvm-dwarfdump/X86/verify_strings.s
    llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s
    llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp

Removed: 
    llvm/test/tools/dsymutil/Inputs/empty-CU.o


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
index aa3885d7a9d6b..76833cc33142b 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
@@ -34,7 +34,7 @@ class DWARFAbbreviationDeclarationSet {
 
   uint64_t getOffset() const { return Offset; }
   void dump(raw_ostream &OS) const;
-  bool extract(DataExtractor Data, uint64_t *OffsetPtr);
+  Error extract(DataExtractor Data, uint64_t *OffsetPtr);
 
   const DWARFAbbreviationDeclaration *
   getAbbreviationDeclaration(uint32_t AbbrCode) const;

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
index a8df634d6a63d..54093dd032af0 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
@@ -25,21 +25,18 @@ void DWARFAbbreviationDeclarationSet::clear() {
   Decls.clear();
 }
 
-bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
-                                              uint64_t *OffsetPtr) {
+Error DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
+                                               uint64_t *OffsetPtr) {
   clear();
   const uint64_t BeginOffset = *OffsetPtr;
   Offset = BeginOffset;
   DWARFAbbreviationDeclaration AbbrDecl;
   uint32_t PrevAbbrCode = 0;
   while (true) {
-    llvm::Expected<DWARFAbbreviationDeclaration::ExtractState> ES =
+    Expected<DWARFAbbreviationDeclaration::ExtractState> ES =
         AbbrDecl.extract(Data, OffsetPtr);
-    if (!ES) {
-      // FIXME: We should propagate the error upwards.
-      llvm::consumeError(ES.takeError());
-      break;
-    }
+    if (!ES)
+      return ES.takeError();
 
     if (*ES == DWARFAbbreviationDeclaration::ExtractState::Complete)
       break;
@@ -53,7 +50,7 @@ bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
     PrevAbbrCode = AbbrDecl.getCode();
     Decls.push_back(std::move(AbbrDecl));
   }
-  return BeginOffset != *OffsetPtr;
+  return Error::success();
 }
 
 void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
@@ -127,8 +124,11 @@ void DWARFDebugAbbrev::parse() const {
       ++I;
     uint64_t CUAbbrOffset = Offset;
     DWARFAbbreviationDeclarationSet AbbrDecls;
-    if (!AbbrDecls.extract(*Data, &Offset))
+    if (Error Err = AbbrDecls.extract(*Data, &Offset)) {
+      // FIXME: We should propagate the error upwards.
+      consumeError(std::move(Err));
       break;
+    }
     AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls)));
   }
   Data = std::nullopt;
@@ -164,8 +164,11 @@ DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {
   if (Data && CUAbbrOffset < Data->getData().size()) {
     uint64_t Offset = CUAbbrOffset;
     DWARFAbbreviationDeclarationSet AbbrDecls;
-    if (!AbbrDecls.extract(*Data, &Offset))
+    if (Error Err = AbbrDecls.extract(*Data, &Offset)) {
+      // FIXME: We should propagate the error upwards.
+      consumeError(std::move(Err));
       return nullptr;
+    }
     PrevAbbrOffsetPos =
         AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls)))
             .first;

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index e0f2fdd718b3a..54591447d449c 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -299,20 +299,27 @@ unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
 }
 
 unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
+  if (!Abbrev)
+    return 0;
+
+  const DWARFAbbreviationDeclarationSet *AbbrDecls =
+      Abbrev->getAbbreviationDeclarationSet(0);
+  // FIXME: If we failed to get a DWARFAbbreviationDeclarationSet, it's possible
+  // that there are errors. We need to propagate the error from
+  // getAbbreviationDeclarationSet.
+  if (!AbbrDecls)
+    return 0;
+
   unsigned NumErrors = 0;
-  if (Abbrev) {
-    const DWARFAbbreviationDeclarationSet *AbbrDecls =
-        Abbrev->getAbbreviationDeclarationSet(0);
-    for (auto AbbrDecl : *AbbrDecls) {
-      SmallDenseSet<uint16_t> AttributeSet;
-      for (auto Attribute : AbbrDecl.attributes()) {
-        auto Result = AttributeSet.insert(Attribute.Attr);
-        if (!Result.second) {
-          error() << "Abbreviation declaration contains multiple "
-                  << AttributeString(Attribute.Attr) << " attributes.\n";
-          AbbrDecl.dump(OS);
-          ++NumErrors;
-        }
+  for (auto AbbrDecl : *AbbrDecls) {
+    SmallDenseSet<uint16_t> AttributeSet;
+    for (auto Attribute : AbbrDecl.attributes()) {
+      auto Result = AttributeSet.insert(Attribute.Attr);
+      if (!Result.second) {
+        error() << "Abbreviation declaration contains multiple "
+                << AttributeString(Attribute.Attr) << " attributes.\n";
+        AbbrDecl.dump(OS);
+        ++NumErrors;
       }
     }
   }

diff  --git a/llvm/test/DebugInfo/ARM/dwarfdump-rela.yaml b/llvm/test/DebugInfo/ARM/dwarfdump-rela.yaml
index 9e307f4665cd2..f65e56a196bde 100644
--- a/llvm/test/DebugInfo/ARM/dwarfdump-rela.yaml
+++ b/llvm/test/DebugInfo/ARM/dwarfdump-rela.yaml
@@ -24,7 +24,7 @@ Sections:
     Content:         17000000050001040000000001A000000000000000020000000000
   - Name:            .debug_abbrev
     Type:            SHT_PROGBITS
-    Content:         011101030E49130000022400030E0000
+    Content:         011101030E49130000022400030E000000
   - Name:            .debug_str
     Type:            SHT_PROGBITS
   - Name:            .rela.debug_info

diff  --git a/llvm/test/DebugInfo/X86/dwarfdump-header-64.s b/llvm/test/DebugInfo/X86/dwarfdump-header-64.s
index 6f3cf691dc340..a8f250a5a2818 100644
--- a/llvm/test/DebugInfo/X86/dwarfdump-header-64.s
+++ b/llvm/test/DebugInfo/X86/dwarfdump-header-64.s
@@ -41,6 +41,7 @@ abbrev:
         .byte   0x17    # DW_FORM_sec_offset
         .byte   0x00    # EOM(1)
         .byte   0x00    # EOM(2)
+        .byte   0x00    # EOM(3)
 
 .ifdef ELF
         .section .debug_info,"", at progbits

diff  --git a/llvm/test/DebugInfo/X86/dwarfdump-rela-dwo.s b/llvm/test/DebugInfo/X86/dwarfdump-rela-dwo.s
index cff1331f491f0..d55f70f2c9488 100644
--- a/llvm/test/DebugInfo/X86/dwarfdump-rela-dwo.s
+++ b/llvm/test/DebugInfo/X86/dwarfdump-rela-dwo.s
@@ -31,6 +31,7 @@
         .byte 0x25  # DW_FORM_strx1
         .byte 0x00  # EOM(1)
         .byte 0x00  # EOM(2)
+        .byte 0x00  # EOM(3)
 
         .section .debug_info.dwo,"e", at progbits
 # CHECK-LABEL: .debug_info.dwo

diff  --git a/llvm/test/tools/dsymutil/Inputs/empty-CU.o b/llvm/test/tools/dsymutil/Inputs/empty-CU.o
deleted file mode 100644
index 11c5905bc12ae..0000000000000
Binary files a/llvm/test/tools/dsymutil/Inputs/empty-CU.o and /dev/null 
diff er

diff  --git a/llvm/test/tools/dsymutil/Inputs/empty-CU.s b/llvm/test/tools/dsymutil/Inputs/empty-CU.s
index c539588da1796..d5ba26c02f862 100644
--- a/llvm/test/tools/dsymutil/Inputs/empty-CU.s
+++ b/llvm/test/tools/dsymutil/Inputs/empty-CU.s
@@ -10,7 +10,8 @@
 .byte 4
         .section        __DWARF,__debug_abbrev,regular,debug
 .byte 1    # Abbrev code
-.byte 0x11 # TAG_compile_unit
-.byte 0    # no children
-.byte 0    # no attributes
-.byte 0
+.byte 0x11 # DW_TAG_compile_unit
+.byte 0    # DW_CHILDREN_no
+.byte 0    # Terminating attribute
+.byte 0    # Terminating form
+.byte 0    # Terminating abbrev code

diff  --git a/llvm/test/tools/dsymutil/Inputs/swift-interface.s b/llvm/test/tools/dsymutil/Inputs/swift-interface.s
index f08ab9aaf601f..a69f008a6cf3e 100644
--- a/llvm/test/tools/dsymutil/Inputs/swift-interface.s
+++ b/llvm/test/tools/dsymutil/Inputs/swift-interface.s
@@ -2,16 +2,16 @@
 ##;
 ##; target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
 ##; target triple = "x86_64-apple-macosx10.9.0"
-##;  
+##;
 ##; @__swift_reflection_version = linkonce_odr hidden constant i16 3
 ##; @llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata", align 8
-##;  
+##;
 ##; define i32 @main(i32, i8**) !dbg !29 {
 ##; entry:
 ##;   %2 = bitcast i8** %1 to i8*
 ##;   ret i32 0, !dbg !35
 ##; }
-##;  
+##;
 ##; !llvm.dbg.cu = !{!0}
 ##; !swift.module.flags = !{!14}
 ##; !llvm.module.flags = !{!20, !21, !24}
@@ -23,9 +23,9 @@
 ##; !4 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !5, file: !1)
 ##; !5 = !DIModule(scope: null, name: "Foo", includePath: "/Foo/x86_64.swiftinterface")
 ##; !6 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !7, file: !1)
-##; !7 = !DIModule(scope: null, name: "Swift", includePath: "/SDK/Swift.swiftmodule/x86_64.swiftinterface", sysroot: "/SDK")
+##; !7 = !DIModule(scope: null, name: "Swift", includePath: "/SDK/Swift.swiftmodule/x86_64.swiftinterface")
 ##; !8 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !7, file: !1)
-##; !9 = !DIModule(scope: null, name: "Foundation", includePath: "/SDK/Foundation.swiftmodu
+##; !9 = !DIModule(scope: null, name: "Foundation", includePath: "/SDK/Foundation.swiftmodule")
 ##; !14 = !{!"standard-library", i1 false}
 ##; !20 = !{i32 2, !"Dwarf Version", i32 4}
 ##; !21 = !{i32 2, !"Debug Info Version", i32 3}
@@ -36,14 +36,14 @@
 ##; !35 = !DILocation(line: 0, scope: !36)
 ##; !36 = !DILexicalBlockFile(scope: !29, file: !37, discriminator: 0)
 ##; !37 = !DIFile(filename: "<compiler-generated>", directory: "")
-        .section	__TEXT,__text,regular,pure_instructions
+	.section	__TEXT,__text,regular,pure_instructions
 	.macosx_version_min 10, 9
-	.globl	_main                   ## -- Begin function main
+	.globl	_main                           ## -- Begin function main
 	.p2align	4, 0x90
 _main:                                  ## @main
 Lfunc_begin0:
-	.file	1 "/ParseableInterfaceImports.swift"
-	.loc	1 0 0                   ## ParseableInterfaceImports.swift:0:0
+	.file	1 "/" "ParseableInterfaceImports.swift"
+	.loc	1 0 0                           ## ParseableInterfaceImports.swift:0:0
 	.cfi_startproc
 ## %bb.0:                               ## %entry
 	xorl	%eax, %eax
@@ -56,160 +56,209 @@ Lfunc_end0:
 	.section	__TEXT,__const
 	.globl	___swift_reflection_version
 	.weak_definition	___swift_reflection_version
-	.p2align	1
+	.p2align	1, 0x0
 ___swift_reflection_version:
-	.short	3                       ## 0x3
+	.short	3                               ## 0x3
 
 	.no_dead_strip	___swift_reflection_version
-	.section	__DWARF,__debug_str,regular,debug
-Linfo_string:
-	.byte	0                       ## string offset=0
-	.asciz	"ParseableInterfaceImports.swift" ## string offset=1
-	.asciz	"/"                     ## string offset=33
-	.asciz	"Foo"                   ## string offset=35
-	.asciz	"/Foo/x86_64.swiftinterface" ## string offset=39
-	.asciz	"Swift"                 ## string offset=66
-	.asciz	"/SDK/Swift.swiftmodule/x86_64.swiftinterface" ## string offset=72
-	.asciz	"/SDK"                  ## string offset=117
-	.asciz	"main"                  ## string offset=122
-	.asciz	"Foundation"            ## string offset=127
-        .asciz	"/SDK/Foundation.swiftmodule/x86_64.swiftinterface" ## string offset=138
 	.section	__DWARF,__debug_abbrev,regular,debug
 Lsection_abbrev:
-	.byte	1                       ## Abbreviation Code
-	.byte	17                      ## DW_TAG_compile_unit
-	.byte	1                       ## DW_CHILDREN_yes
-	.byte	37                      ## DW_AT_producer
-	.byte	14                      ## DW_FORM_strp
-	.byte	19                      ## DW_AT_language
-	.byte	5                       ## DW_FORM_data2
-	.byte	3                       ## DW_AT_name
-	.byte	14                      ## DW_FORM_strp
-	.ascii	"\202|"                 ## DW_AT_LLVM_sysroot
-	.byte	14                      ## DW_FORM_strp
-	.byte	16                      ## DW_AT_stmt_list
-	.byte	23                      ## DW_FORM_sec_offset
-	.byte	27                      ## DW_AT_comp_dir
-	.byte	14                      ## DW_FORM_strp
-	.ascii	"\345\177"              ## DW_AT_APPLE_major_runtime_vers
-	.byte	11                      ## DW_FORM_data1
-	.byte	17                      ## DW_AT_low_pc
-	.byte	1                       ## DW_FORM_addr
-	.byte	18                      ## DW_AT_high_pc
-	.byte	6                       ## DW_FORM_data4
-	.byte	0                       ## EOM(1)
-	.byte	0                       ## EOM(2)
-	.byte	2                       ## Abbreviation Code
-	.byte	30                      ## DW_TAG_module
-	.byte	1                       ## DW_CHILDREN_yes
-	.byte	3                       ## DW_AT_name
-	.byte	14                      ## DW_FORM_strp
-	.ascii	"\200|"                 ## DW_AT_LLVM_include_path
-	.byte	14                      ## DW_FORM_strp
-	.byte	0                       ## EOM(1)
-	.byte	0                       ## EOM(2)
-	.byte	3                       ## Abbreviation Code
-	.byte	46                      ## DW_TAG_subprogram
-	.byte	0                       ## DW_CHILDREN_no
-	.byte	17                      ## DW_AT_low_pc
-	.byte	1                       ## DW_FORM_addr
-	.byte	18                      ## DW_AT_high_pc
-	.byte	6                       ## DW_FORM_data4
-	.ascii	"\347\177"              ## DW_AT_APPLE_omit_frame_ptr
-	.byte	25                      ## DW_FORM_flag_present
-	.byte	64                      ## DW_AT_frame_base
-	.byte	24                      ## DW_FORM_exprloc
-	.byte	110                     ## DW_AT_linkage_name
-	.byte	14                      ## DW_FORM_strp
-	.byte	3                       ## DW_AT_name
-	.byte	14                      ## DW_FORM_strp
-	.byte	58                      ## DW_AT_decl_file
-	.byte	11                      ## DW_FORM_data1
-	.byte	59                      ## DW_AT_decl_line
-	.byte	11                      ## DW_FORM_data1
-	.byte	63                      ## DW_AT_external
-	.byte	25                      ## DW_FORM_flag_present
-	.byte	0                       ## EOM(1)
-	.byte	0                       ## EOM(2)
-	.byte	4                       ## Abbreviation Code
-	.byte	58                      ## DW_TAG_imported_module
-	.byte	0                       ## DW_CHILDREN_no
-	.byte	24                      ## DW_AT_import
-	.byte	19                      ## DW_FORM_ref4
-	.byte	0                       ## EOM(1)
-	.byte	0                       ## EOM(2)
-	.byte	5                       ## Abbreviation Code
-	.byte	30                      ## DW_TAG_module
-	.byte	0                       ## DW_CHILDREN_no
-	.byte	3                       ## DW_AT_name
-	.byte	14                      ## DW_FORM_strp
-	.ascii	"\200|"                 ## DW_AT_LLVM_include_path
-	.byte	14                      ## DW_FORM_strp
-	.ascii	"\202|"                 ## DW_AT_LLVM_sysroot
-	.byte	14                      ## DW_FORM_strp
-	.byte	0                       ## EOM(1)
-	.byte	0                       ## EOM(2)
- 	.byte	30                      ## DW_TAG_module
-	.byte	1                       ## DW_CHILDREN_no
-	.byte	3                       ## DW_AT_name
-	.byte	14                      ## DW_FORM_strp
-	.ascii	"\200|"                 ## DW_AT_LLVM_include_path
-	.byte	14                      ## DW_FORM_strp
-	.byte	0                       ## EOM(1)
-	.byte	0                       ## EOM(2)
-	.byte	0                       ## EOM(3)
+	.byte	1                               ## Abbreviation Code
+	.byte	17                              ## DW_TAG_compile_unit
+	.byte	1                               ## DW_CHILDREN_yes
+	.byte	37                              ## DW_AT_producer
+	.byte	14                              ## DW_FORM_strp
+	.byte	19                              ## DW_AT_language
+	.byte	5                               ## DW_FORM_data2
+	.byte	3                               ## DW_AT_name
+	.byte	14                              ## DW_FORM_strp
+	.ascii	"\202|"                         ## DW_AT_LLVM_sysroot
+	.byte	14                              ## DW_FORM_strp
+	.byte	16                              ## DW_AT_stmt_list
+	.byte	23                              ## DW_FORM_sec_offset
+	.byte	27                              ## DW_AT_comp_dir
+	.byte	14                              ## DW_FORM_strp
+	.ascii	"\345\177"                      ## DW_AT_APPLE_major_runtime_vers
+	.byte	11                              ## DW_FORM_data1
+	.byte	17                              ## DW_AT_low_pc
+	.byte	1                               ## DW_FORM_addr
+	.byte	18                              ## DW_AT_high_pc
+	.byte	6                               ## DW_FORM_data4
+	.byte	0                               ## EOM(1)
+	.byte	0                               ## EOM(2)
+	.byte	2                               ## Abbreviation Code
+	.byte	30                              ## DW_TAG_module
+	.byte	1                               ## DW_CHILDREN_yes
+	.byte	3                               ## DW_AT_name
+	.byte	14                              ## DW_FORM_strp
+	.ascii	"\200|"                         ## DW_AT_LLVM_include_path
+	.byte	14                              ## DW_FORM_strp
+	.byte	0                               ## EOM(1)
+	.byte	0                               ## EOM(2)
+	.byte	3                               ## Abbreviation Code
+	.byte	46                              ## DW_TAG_subprogram
+	.byte	0                               ## DW_CHILDREN_no
+	.byte	17                              ## DW_AT_low_pc
+	.byte	1                               ## DW_FORM_addr
+	.byte	18                              ## DW_AT_high_pc
+	.byte	6                               ## DW_FORM_data4
+	.ascii	"\347\177"                      ## DW_AT_APPLE_omit_frame_ptr
+	.byte	25                              ## DW_FORM_flag_present
+	.byte	64                              ## DW_AT_frame_base
+	.byte	24                              ## DW_FORM_exprloc
+	.byte	110                             ## DW_AT_linkage_name
+	.byte	14                              ## DW_FORM_strp
+	.byte	3                               ## DW_AT_name
+	.byte	14                              ## DW_FORM_strp
+	.byte	58                              ## DW_AT_decl_file
+	.byte	11                              ## DW_FORM_data1
+	.byte	59                              ## DW_AT_decl_line
+	.byte	11                              ## DW_FORM_data1
+	.byte	63                              ## DW_AT_external
+	.byte	25                              ## DW_FORM_flag_present
+	.byte	0                               ## EOM(1)
+	.byte	0                               ## EOM(2)
+	.byte	4                               ## Abbreviation Code
+	.byte	58                              ## DW_TAG_imported_module
+	.byte	0                               ## DW_CHILDREN_no
+	.byte	24                              ## DW_AT_import
+	.byte	19                              ## DW_FORM_ref4
+	.byte	0                               ## EOM(1)
+	.byte	0                               ## EOM(2)
+	.byte	5                               ## Abbreviation Code
+	.byte	30                              ## DW_TAG_module
+	.byte	0                               ## DW_CHILDREN_no
+	.byte	3                               ## DW_AT_name
+	.byte	14                              ## DW_FORM_strp
+	.ascii	"\200|"                         ## DW_AT_LLVM_include_path
+	.byte	14                              ## DW_FORM_strp
+	.byte	0                               ## EOM(1)
+	.byte	0                               ## EOM(2)
+	.byte	0                               ## EOM(3)
 	.section	__DWARF,__debug_info,regular,debug
 Lsection_info:
 Lcu_begin0:
 .set Lset0, Ldebug_info_end0-Ldebug_info_start0 ## Length of Unit
 	.long	Lset0
 Ldebug_info_start0:
-	.short	4                       ## DWARF version number
+	.short	4                               ## DWARF version number
 .set Lset1, Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section
 	.long	Lset1
-	.byte	8                       ## Address Size (in bytes)
-	.byte	1                       ## Abbrev [1] 0xb:0x5b DW_TAG_compile_unit
-	.long	0                       ## DW_AT_producer
-	.short	30                      ## DW_AT_language
-	.long	1                       ## DW_AT_name
-        .long	117                     ## DW_AT_name
+	.byte	8                               ## Address Size (in bytes)
+	.byte	1                               ## Abbrev [1] 0xb:0x60 DW_TAG_compile_unit
+	.long	0                               ## DW_AT_producer
+	.short	30                              ## DW_AT_language
+	.long	1                               ## DW_AT_name
+	.long	33                              ## DW_AT_LLVM_sysroot
 .set Lset2, Lline_table_start0-Lsection_line ## DW_AT_stmt_list
 	.long	Lset2
-	.long	33                      ## DW_AT_comp_dir
-	.byte	5                       ## DW_AT_APPLE_major_runtime_vers
-	.quad	Lfunc_begin0            ## DW_AT_low_pc
+	.long	38                              ## DW_AT_comp_dir
+	.byte	5                               ## DW_AT_APPLE_major_runtime_vers
+	.quad	Lfunc_begin0                    ## DW_AT_low_pc
 .set Lset3, Lfunc_end0-Lfunc_begin0     ## DW_AT_high_pc
 	.long	Lset3
-	.byte	2                       ## Abbrev [2] 0x2b:0x23 DW_TAG_module
-	.long	35                      ## DW_AT_name
-	.long	39                      ## DW_AT_LLVM_include_path
-	.byte	3                       ## Abbrev [3] 0x34:0x19 DW_TAG_subprogram
-	.quad	Lfunc_begin0            ## DW_AT_low_pc
+	.byte	2                               ## Abbrev [2] 0x2f:0x23 DW_TAG_module
+	.long	40                              ## DW_AT_name
+	.long	44                              ## DW_AT_LLVM_include_path
+	.byte	3                               ## Abbrev [3] 0x38:0x19 DW_TAG_subprogram
+	.quad	Lfunc_begin0                    ## DW_AT_low_pc
 .set Lset4, Lfunc_end0-Lfunc_begin0     ## DW_AT_high_pc
 	.long	Lset4
                                         ## DW_AT_APPLE_omit_frame_ptr
-	.byte	1                       ## DW_AT_frame_base
+	.byte	1                               ## DW_AT_frame_base
 	.byte	87
-	.long	122                     ## DW_AT_linkage_name
-	.long	122                     ## DW_AT_name
-	.byte	1                       ## DW_AT_decl_file
-	.byte	1                       ## DW_AT_decl_line
+	.long	122                             ## DW_AT_linkage_name
+	.long	122                             ## DW_AT_name
+	.byte	1                               ## DW_AT_decl_file
+	.byte	1                               ## DW_AT_decl_line
                                         ## DW_AT_external
-	.byte	0                       ## End Of Children Mark
-	.byte	4                       ## Abbrev [4] 0x4e:0x5 DW_TAG_imported_module
-	.long	47                      ## DW_AT_import
-	.byte	5                       ## Abbrev [5] 0x53:0xd DW_TAG_module
-	.long	66                      ## DW_AT_name
-	.long	72                      ## DW_AT_LLVM_include_path
-	.long	117                     ## DW_AT_LLVM_sysroot
-	.byte	4                       ## Abbrev [4] 0x60:0x5 DW_TAG_imported_module
-	.long	105                      ## DW_AT_import
-	.byte	2                       ## Abbrev [2] 0x2b:0x23 DW_TAG_module
-	.long	127                     ## DW_AT_name
-	.long	138                     ## DW_AT_LLVM_include_path
-	.byte	0                       ## End Of Children Mark
-	.byte	0                       ## End Of Children Mark
+	.byte	0                               ## End Of Children Mark
+	.byte	4                               ## Abbrev [4] 0x52:0x5 DW_TAG_imported_module
+	.long	47                              ## DW_AT_import
+	.byte	5                               ## Abbrev [5] 0x57:0x9 DW_TAG_module
+	.long	71                              ## DW_AT_name
+	.long	77                              ## DW_AT_LLVM_include_path
+	.byte	4                               ## Abbrev [4] 0x60:0x5 DW_TAG_imported_module
+	.long	87                              ## DW_AT_import
+	.byte	4                               ## Abbrev [4] 0x65:0x5 DW_TAG_imported_module
+	.long	87                              ## DW_AT_import
+	.byte	0                               ## End Of Children Mark
 Ldebug_info_end0:
+	.section	__DWARF,__debug_str,regular,debug
+Linfo_string:
+	.byte	0                               ## string offset=0
+	.asciz	"ParseableInterfaceImports.swift" ## string offset=1
+	.asciz	"/SDK"                          ## string offset=33
+	.asciz	"/"                             ## string offset=38
+	.asciz	"Foo"                           ## string offset=40
+	.asciz	"/Foo/x86_64.swiftinterface"    ## string offset=44
+	.asciz	"Swift"                         ## string offset=71
+	.asciz	"/SDK/Swift.swiftmodule/x86_64.swiftinterface" ## string offset=77
+	.asciz	"main"                          ## string offset=122
+	.section	__DWARF,__apple_names,regular,debug
+Lnames_begin:
+	.long	1212240712                      ## Header Magic
+	.short	1                               ## Header Version
+	.short	0                               ## Header Hash Function
+	.long	1                               ## Header Bucket Count
+	.long	1                               ## Header Hash Count
+	.long	12                              ## Header Data Length
+	.long	0                               ## HeaderData Die Offset Base
+	.long	1                               ## HeaderData Atom Count
+	.short	1                               ## DW_ATOM_die_offset
+	.short	6                               ## DW_FORM_data4
+	.long	0                               ## Bucket 0
+	.long	2090499946                      ## Hash in Bucket 0
+.set Lset5, LNames0-Lnames_begin        ## Offset in Bucket 0
+	.long	Lset5
+LNames0:
+	.long	122                             ## main
+	.long	1                               ## Num DIEs
+	.long	56
+	.long	0
+	.section	__DWARF,__apple_objc,regular,debug
+Lobjc_begin:
+	.long	1212240712                      ## Header Magic
+	.short	1                               ## Header Version
+	.short	0                               ## Header Hash Function
+	.long	1                               ## Header Bucket Count
+	.long	0                               ## Header Hash Count
+	.long	12                              ## Header Data Length
+	.long	0                               ## HeaderData Die Offset Base
+	.long	1                               ## HeaderData Atom Count
+	.short	1                               ## DW_ATOM_die_offset
+	.short	6                               ## DW_FORM_data4
+	.long	-1                              ## Bucket 0
+	.section	__DWARF,__apple_namespac,regular,debug
+Lnamespac_begin:
+	.long	1212240712                      ## Header Magic
+	.short	1                               ## Header Version
+	.short	0                               ## Header Hash Function
+	.long	1                               ## Header Bucket Count
+	.long	0                               ## Header Hash Count
+	.long	12                              ## Header Data Length
+	.long	0                               ## HeaderData Die Offset Base
+	.long	1                               ## HeaderData Atom Count
+	.short	1                               ## DW_ATOM_die_offset
+	.short	6                               ## DW_FORM_data4
+	.long	-1                              ## Bucket 0
+	.section	__DWARF,__apple_types,regular,debug
+Ltypes_begin:
+	.long	1212240712                      ## Header Magic
+	.short	1                               ## Header Version
+	.short	0                               ## Header Hash Function
+	.long	1                               ## Header Bucket Count
+	.long	0                               ## Header Hash Count
+	.long	20                              ## Header Data Length
+	.long	0                               ## HeaderData Die Offset Base
+	.long	3                               ## HeaderData Atom Count
+	.short	1                               ## DW_ATOM_die_offset
+	.short	6                               ## DW_FORM_data4
+	.short	3                               ## DW_ATOM_die_tag
+	.short	5                               ## DW_FORM_data2
+	.short	4                               ## DW_ATOM_type_flags
+	.short	11                              ## DW_FORM_data1
+	.long	-1                              ## Bucket 0
 .subsections_via_symbols
 	.section	__DWARF,__debug_line,regular,debug
 Lsection_line:

diff  --git a/llvm/test/tools/dsymutil/X86/empty-CU.test b/llvm/test/tools/dsymutil/X86/empty-CU.test
index bd3a54491ae6a..7b06607a74cbc 100644
--- a/llvm/test/tools/dsymutil/X86/empty-CU.test
+++ b/llvm/test/tools/dsymutil/X86/empty-CU.test
@@ -1,4 +1,5 @@
-RUN: dsymutil --update -f %p/../Inputs/empty-CU.o -o - | llvm-dwarfdump -v - -debug-info | FileCheck %s
+RUN: llvm-mc %p/../Inputs/empty-CU.s -filetype obj -triple x86_64-apple-darwin -o %t.o
+RUN: dsymutil --update -f %t.o -o - | llvm-dwarfdump -v - -debug-info | FileCheck %s
 
 CHECK: .debug_info contents:
 CHECK: 0x00000000: Compile Unit: length = 0x00000008, format = DWARF32, version = 0x0003, abbr_offset = 0x0000, addr_size = 0x04 (next unit at 0x0000000c)

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/debug-abbrev.s b/llvm/test/tools/llvm-dwarfdump/X86/debug-abbrev.s
index 04e0845d9300a..f9fccc9fee8bd 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/debug-abbrev.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug-abbrev.s
@@ -79,7 +79,7 @@
     .byte 0x02 ## Invalid children encoding (interpreted as DW_CHILDREN_no).
         .byte 0, 0         ## End of attributes.
 
-    .byte 0 ## End of abbrevs.
+    .byte 0 ## End of first abbreviation set.
 
     ## Second .debug_abbrev set.
     .byte 0x42 ## Abbreviation Code (duplicate in 
diff erent unit)
@@ -88,3 +88,5 @@
         .byte 0x66 ## DW_AT_elemental
         .byte 0x19 ## DW_FORM_flag_present
         .byte 0, 0 ## End of attributes.
+
+    .byte 0 # End of second abbreviation set.

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/no_debug_addr.s b/llvm/test/tools/llvm-dwarfdump/X86/no_debug_addr.s
index bf660679837be..288589129bdb5 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/no_debug_addr.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/no_debug_addr.s
@@ -28,6 +28,7 @@
   .byte 35                       # DW_FORM_rnglistx
   .byte 0                        # EOM(1)
   .byte 0                        # EOM(2)
+  .byte 0                        # EOM(3)
 
 .section .debug_rnglists.dwo,"e", at progbits
   .long  .Ldebug_rnglist_table_end1-.Ldebug_rnglist_table_start1 # Length

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_strings.s b/llvm/test/tools/llvm-dwarfdump/X86/verify_strings.s
index 9beb7a1873ed6..b8666f963a3ce 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/verify_strings.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_strings.s
@@ -35,6 +35,7 @@ str_producer:
         .byte 0x17  # DW_FORM_sec_offset
         .byte 0x00  # EOM(1)
         .byte 0x00  # EOM(2)
+        .byte 0x00  # EOM(3)
 
         .section .debug_info,"", at progbits
 

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s b/llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s
index baee5d86a24ed..5921f75643273 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s
@@ -28,6 +28,7 @@ Linfo_string:
 Lsection_abbrev:
 	.byte	1                       ## Abbreviation Code
 	.byte	17                      ## DW_TAG_compile_unit
+        .byte   0                       ## DW_CHILDREN_no
 	.byte	0                       ## EOM(1)
 	.byte	0                       ## EOM(2)
 	.byte	0                       ## EOM(3)

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp
index 62627ae6956ff..7ba22d2eefff7 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp
@@ -20,8 +20,8 @@ using namespace dwarf;
 
 enum OrderKind : bool { InOrder, OutOfOrder };
 
-void writeAbbreviationDeclarations(raw_ostream &OS, uint32_t FirstCode,
-                                   OrderKind Order) {
+void writeValidAbbreviationDeclarations(raw_ostream &OS, uint32_t FirstCode,
+                                        OrderKind Order) {
   encodeULEB128(FirstCode, OS);
   encodeULEB128(DW_TAG_compile_unit, OS);
   OS << static_cast<uint8_t>(DW_CHILDREN_yes);
@@ -57,14 +57,13 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetExtractSuccess) {
   raw_svector_ostream OS(RawData);
   uint32_t FirstCode = 5;
 
-  writeAbbreviationDeclarations(OS, FirstCode, InOrder);
+  writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);
   encodeULEB128(0, OS);
 
   uint64_t Offset = 0;
   DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
   DWARFAbbreviationDeclarationSet AbbrevSet;
-  const bool DataWasExtracted = AbbrevSet.extract(Data, &Offset);
-  EXPECT_TRUE(DataWasExtracted);
+  ASSERT_THAT_ERROR(AbbrevSet.extract(Data, &Offset), Succeeded());
   // The Abbreviation Declarations are in order and contiguous, so we want to
   // make sure that FirstAbbrCode was correctly set.
   EXPECT_EQ(AbbrevSet.getFirstAbbrCode(), FirstCode);
@@ -89,14 +88,13 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetExtractSuccessOutOfOrder) {
   raw_svector_ostream OS(RawData);
   uint32_t FirstCode = 2;
 
-  writeAbbreviationDeclarations(OS, FirstCode, OutOfOrder);
+  writeValidAbbreviationDeclarations(OS, FirstCode, OutOfOrder);
   encodeULEB128(0, OS);
 
   uint64_t Offset = 0;
   DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
   DWARFAbbreviationDeclarationSet AbbrevSet;
-  const bool DataWasExtracted = AbbrevSet.extract(Data, &Offset);
-  EXPECT_TRUE(DataWasExtracted);
+  ASSERT_THAT_ERROR(AbbrevSet.extract(Data, &Offset), Succeeded());
   // The declarations are out of order, ensure that FirstAbbrCode is UINT32_MAX.
   EXPECT_EQ(AbbrevSet.getFirstAbbrCode(), UINT32_MAX);
 
@@ -126,7 +124,10 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetCodeExtractionError) {
     uint64_t Offset = 0;
     DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
     DWARFAbbreviationDeclarationSet AbbrevSet;
-    EXPECT_FALSE(AbbrevSet.extract(Data, &Offset));
+    ASSERT_THAT_ERROR(
+        AbbrevSet.extract(Data, &Offset),
+        FailedWithMessage("unable to decode LEB128 at offset 0x00000000: "
+                          "malformed uleb128, extends past end"));
     EXPECT_EQ(Offset, 0u);
   }
 
@@ -139,7 +140,10 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetCodeExtractionError) {
     uint64_t Offset = 0;
     DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
     DWARFAbbreviationDeclarationSet AbbrevSet;
-    EXPECT_FALSE(AbbrevSet.extract(Data, &Offset));
+    ASSERT_THAT_ERROR(
+        AbbrevSet.extract(Data, &Offset),
+        FailedWithMessage("unable to decode LEB128 at offset 0x00000000: "
+                          "uleb128 too big for uint64"));
     EXPECT_EQ(Offset, 0u);
   }
 }
@@ -157,7 +161,10 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetTagExtractionError) {
     uint64_t Offset = 0;
     DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
     DWARFAbbreviationDeclarationSet AbbrevSet;
-    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    ASSERT_THAT_ERROR(
+        AbbrevSet.extract(Data, &Offset),
+        FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
+                          "malformed uleb128, extends past end"));
     // Only the code was extracted correctly.
     EXPECT_EQ(Offset, 1u);
   }
@@ -172,13 +179,16 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetTagExtractionError) {
     uint64_t Offset = 0;
     DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
     DWARFAbbreviationDeclarationSet AbbrevSet;
-    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    ASSERT_THAT_ERROR(
+        AbbrevSet.extract(Data, &Offset),
+        FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
+                          "uleb128 too big for uint64"));
     // Only the code was extracted correctly.
     EXPECT_EQ(Offset, 1u);
   }
 }
 
-TEST(DWARFDebugAbbrevTest, DWARFAbbreviatioDeclSetChildExtractionError) {
+TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetChildExtractionError) {
   SmallString<64> RawData;
   const uint32_t Code = 1;
   const dwarf::Tag Tag = DW_TAG_compile_unit;
@@ -188,11 +198,13 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviatioDeclSetChildExtractionError) {
   raw_svector_ostream OS(RawData);
   encodeULEB128(Code, OS);
   encodeULEB128(Tag, OS);
-
   uint64_t Offset = 0;
   DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
   DWARFAbbreviationDeclarationSet AbbrevSet;
-  EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+  ASSERT_THAT_ERROR(
+      AbbrevSet.extract(Data, &Offset),
+      FailedWithMessage(
+          "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));
   // The code and the tag were extracted correctly.
   EXPECT_EQ(Offset, 2u);
 }
@@ -214,7 +226,10 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetAttributeExtractionError) {
     uint64_t Offset = 0;
     DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
     DWARFAbbreviationDeclarationSet AbbrevSet;
-    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    ASSERT_THAT_ERROR(
+        AbbrevSet.extract(Data, &Offset),
+        FailedWithMessage("unable to decode LEB128 at offset 0x00000003: "
+                          "malformed uleb128, extends past end"));
     // The code, tag, and child byte were extracted correctly.
     EXPECT_EQ(Offset, 3u);
   }
@@ -231,7 +246,10 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetAttributeExtractionError) {
     uint64_t Offset = 0;
     DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
     DWARFAbbreviationDeclarationSet AbbrevSet;
-    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    ASSERT_THAT_ERROR(
+        AbbrevSet.extract(Data, &Offset),
+        FailedWithMessage("unable to decode LEB128 at offset 0x00000003: "
+                          "uleb128 too big for uint64"));
     // The code, tag, and child byte were extracted correctly.
     EXPECT_EQ(Offset, 3u);
   }
@@ -256,7 +274,10 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetFormExtractionError) {
     uint64_t Offset = 0;
     DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
     DWARFAbbreviationDeclarationSet AbbrevSet;
-    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    ASSERT_THAT_ERROR(
+        AbbrevSet.extract(Data, &Offset),
+        FailedWithMessage("unable to decode LEB128 at offset 0x00000004: "
+                          "malformed uleb128, extends past end"));
     // The code, tag, child byte, and first attribute were extracted correctly.
     EXPECT_EQ(Offset, 4u);
   }
@@ -274,8 +295,120 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetFormExtractionError) {
     uint64_t Offset = 0;
     DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
     DWARFAbbreviationDeclarationSet AbbrevSet;
-    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    ASSERT_THAT_ERROR(
+        AbbrevSet.extract(Data, &Offset),
+        FailedWithMessage("unable to decode LEB128 at offset 0x00000004: "
+                          "uleb128 too big for uint64"));
     // The code, tag, child byte, and first attribute were extracted correctly.
     EXPECT_EQ(Offset, 4u);
   }
 }
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetInvalidTag) {
+  SmallString<64> RawData;
+  raw_svector_ostream OS(RawData);
+  uint32_t FirstCode = 1;
+  // First, we're going to manually add good data.
+  writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);
+
+  // Afterwards, we're going to write an Abbreviation Decl manually with an
+  // invalid tag.
+  encodeULEB128(FirstCode + 2, OS);
+  encodeULEB128(0, OS); // Invalid Tag
+  OS << static_cast<uint8_t>(DW_CHILDREN_no);
+  encodeULEB128(DW_AT_name, OS);
+  encodeULEB128(DW_FORM_strp, OS);
+  encodeULEB128(0, OS);
+  encodeULEB128(0, OS);
+
+  encodeULEB128(0, OS);
+  uint64_t Offset = 0;
+  DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+  DWARFAbbreviationDeclarationSet AbbrevSet;
+  EXPECT_THAT_ERROR(
+      AbbrevSet.extract(Data, &Offset),
+      FailedWithMessage("abbreviation declaration requires a non-null tag"));
+}
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetInvalidAttrValidForm) {
+  SmallString<64> RawData;
+  raw_svector_ostream OS(RawData);
+  uint32_t FirstCode = 120;
+  // First, we're going to manually add good data.
+  writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);
+
+  // Afterwards, we're going to write an Abbreviation Decl manually with an
+  // invalid attribute but valid form.
+  encodeULEB128(FirstCode - 5, OS);
+  encodeULEB128(DW_TAG_compile_unit, OS);
+  OS << static_cast<uint8_t>(DW_CHILDREN_no);
+  encodeULEB128(0, OS); // Invalid attribute followed by an invalid form.
+  encodeULEB128(DW_FORM_strp, OS);
+  encodeULEB128(0, OS);
+  encodeULEB128(0, OS);
+
+  encodeULEB128(0, OS);
+
+  uint64_t Offset = 0;
+  DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+  DWARFAbbreviationDeclarationSet AbbrevSet;
+  EXPECT_THAT_ERROR(
+      AbbrevSet.extract(Data, &Offset),
+      FailedWithMessage(
+          "malformed abbreviation declaration attribute. Either the "
+          "attribute or the form is zero while the other is not"));
+}
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetValidAttrInvalidForm) {
+  SmallString<64> RawData;
+  raw_svector_ostream OS(RawData);
+  uint32_t FirstCode = 120;
+  // First, we're going to manually add good data.
+  writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);
+
+  // Afterwards, we're going to write an Abbreviation Decl manually with a
+  // valid attribute but invalid form.
+  encodeULEB128(FirstCode - 5, OS);
+  encodeULEB128(DW_TAG_compile_unit, OS);
+  OS << static_cast<uint8_t>(DW_CHILDREN_no);
+  encodeULEB128(DW_AT_name, OS);
+  encodeULEB128(0, OS); // Invalid form after a valid attribute.
+  encodeULEB128(0, OS);
+  encodeULEB128(0, OS);
+
+  encodeULEB128(0, OS);
+
+  uint64_t Offset = 0;
+  DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+  DWARFAbbreviationDeclarationSet AbbrevSet;
+  EXPECT_THAT_ERROR(
+      AbbrevSet.extract(Data, &Offset),
+      FailedWithMessage(
+          "malformed abbreviation declaration attribute. Either the "
+          "attribute or the form is zero while the other is not"));
+}
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetMissingTerminator) {
+  SmallString<64> RawData;
+  raw_svector_ostream OS(RawData);
+  uint32_t FirstCode = 120;
+  // First, we're going to manually add good data.
+  writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);
+
+  // Afterwards, we're going to write an Abbreviation Decl manually without a
+  // termintating sequence.
+  encodeULEB128(FirstCode + 7, OS);
+  encodeULEB128(DW_TAG_compile_unit, OS);
+  OS << static_cast<uint8_t>(DW_CHILDREN_no);
+  encodeULEB128(DW_AT_name, OS);
+  encodeULEB128(DW_FORM_strp, OS);
+
+  uint64_t Offset = 0;
+  DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+  DWARFAbbreviationDeclarationSet AbbrevSet;
+  EXPECT_THAT_ERROR(
+      AbbrevSet.extract(Data, &Offset),
+      FailedWithMessage(
+          "abbreviation declaration attribute list was not terminated with a "
+          "null entry"));
+}


        


More information about the llvm-commits mailing list