summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h10
-rw-r--r--llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h3
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp11
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp19
-rw-r--r--llvm/test/tools/llvm-dwarfdump/X86/apple_types_verify_tag.s128
5 files changed, 158 insertions, 13 deletions
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index eb6d0f541c1..5c304340c13 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -61,11 +61,11 @@ public:
/// performing a lookup by name.
///
/// \param HashDataOffset an offset into the hash data table
- /// \returns DIEOffset the offset into the .debug_info section for the DIE
- /// related to the input hash data offset. Currently this function returns
- /// only the DIEOffset but it can be modified to return more data regarding
- /// the DIE
- uint32_t readAtoms(uint32_t &HashDataOffset);
+ /// \returns <DieOffset, DieTag>
+ /// DieOffset is the offset into the .debug_info section for the DIE
+ /// related to the input hash data offset.
+ /// DieTag is the tag of the DIE
+ std::pair<uint32_t, dwarf::Tag> readAtoms(uint32_t &HashDataOffset);
void dump(raw_ostream &OS) const;
};
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
index 3fe182155e3..70fdaa22cf2 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -141,10 +141,11 @@ class DWARFVerifier {
/// - The size of the section is as large as what the header describes
/// - There is at least one atom
/// - The form for each atom is valid
+ /// - The tag for each DIE in the table is valid
/// - The buckets have a valid index, or they are empty
/// - Each hashdata offset is valid
/// - Each DIE is valid
- ///
+ ///
/// \param AccelSection pointer to the section containing the acceleration table
/// \param StrData pointer to the string section
/// \param SectionName the name of the table we're verifying
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 9ae7c9a07f7..f17b00e5605 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -73,6 +73,8 @@ bool DWARFAcceleratorTable::validateForms() {
DWARFFormValue FormValue(Atom.second);
switch (Atom.first) {
case dwarf::DW_ATOM_die_offset:
+ case dwarf::DW_ATOM_die_tag:
+ case dwarf::DW_ATOM_type_flags:
if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) &&
!FormValue.isFormClass(DWARFFormValue::FC_Flag)) ||
FormValue.getForm() == dwarf::DW_FORM_sdata)
@@ -84,8 +86,10 @@ bool DWARFAcceleratorTable::validateForms() {
return true;
}
-uint32_t DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
+std::pair<uint32_t, dwarf::Tag>
+DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
uint32_t DieOffset = dwarf::DW_INVALID_OFFSET;
+ dwarf::Tag DieTag = dwarf::DW_TAG_null;
for (auto Atom : getAtomsDesc()) {
DWARFFormValue FormValue(Atom.second);
@@ -94,11 +98,14 @@ uint32_t DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
case dwarf::DW_ATOM_die_offset:
DieOffset = *FormValue.getAsUnsignedConstant();
break;
+ case dwarf::DW_ATOM_die_tag:
+ DieTag = (dwarf::Tag)*FormValue.getAsUnsignedConstant();
+ break;
default:
break;
}
}
- return DieOffset;
+ return {DieOffset, DieTag};
}
LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index c5dc723d829..577fce93d3c 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -525,15 +525,16 @@ unsigned DWARFVerifier::verifyAccelTable(const DWARFSection *AccelSection,
uint32_t StrpOffset;
uint32_t StringOffset;
uint32_t StringCount = 0;
- uint32_t DieOffset = dwarf::DW_INVALID_OFFSET;
-
+ unsigned Offset;
+ unsigned Tag;
while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
const uint32_t NumHashDataObjects =
AccelSectionData.getU32(&HashDataOffset);
for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
++HashDataIdx) {
- DieOffset = AccelTable.readAtoms(HashDataOffset);
- if (!DCtx.getDIEForOffset(DieOffset)) {
+ std::tie(Offset, Tag) = AccelTable.readAtoms(HashDataOffset);
+ auto Die = DCtx.getDIEForOffset(Offset);
+ if (!Die) {
const uint32_t BucketIdx =
NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
StringOffset = StrpOffset;
@@ -546,9 +547,17 @@ unsigned DWARFVerifier::verifyAccelTable(const DWARFSection *AccelSection,
"Str[%u] = 0x%08x "
"DIE[%d] = 0x%08x is not a valid DIE offset for \"%s\".\n",
SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
- HashDataIdx, DieOffset, Name);
+ HashDataIdx, Offset, Name);
++NumErrors;
+ continue;
+ }
+ if ((Tag != dwarf::DW_TAG_null) && (Die.getTag() != Tag)) {
+ OS << "\terror: Tag " << dwarf::TagString(Tag)
+ << " in accelerator table does not match Tag "
+ << dwarf::TagString(Die.getTag()) << " of DIE[" << HashDataIdx
+ << "].\n";
+ ++NumErrors;
}
}
++StringCount;
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/apple_types_verify_tag.s b/llvm/test/tools/llvm-dwarfdump/X86/apple_types_verify_tag.s
new file mode 100644
index 00000000000..c2955a62f2b
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/apple_types_verify_tag.s
@@ -0,0 +1,128 @@
+# RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \
+# RUN: | not llvm-dwarfdump -verify - \
+# RUN: | FileCheck %s
+
+# CHECK: Verifying .apple_types...
+# CHECK-NEXT: error: Tag DW_TAG_ptr_to_member_type in accelerator table does not match Tag DW_TAG_base_type of DIE[0].
+
+# This test is meant to verify that the -verify option
+# in llvm-dwarfdump, correctly identifies an invalid DIE tag in .apple_types.
+
+ .section __TEXT,__text,regular,pure_instructions
+ .macosx_version_min 10, 12
+ .file 1 "basic.c"
+ .comm _i,4,2 ## @i
+ .section __DWARF,__debug_str,regular,debug
+Linfo_string:
+ .asciz "clang version 6.0.0 (trunk 309427) (llvm/trunk 309432)" ## string offset=0
+ .asciz "basic.c" ## string offset=55
+ .asciz "/Users/sgravani/Development/tests" ## string offset=63
+ .asciz "i" ## string offset=97
+ .asciz "int" ## string offset=99
+ .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
+ .byte 16 ## DW_AT_stmt_list
+ .byte 23 ## DW_FORM_sec_offset
+ .byte 27 ## DW_AT_comp_dir
+ .byte 14 ## DW_FORM_strp
+ .byte 0 ## EOM(1)
+ .byte 0 ## EOM(2)
+ .byte 2 ## Abbreviation Code
+ .byte 52 ## DW_TAG_variable
+ .byte 0 ## DW_CHILDREN_no
+ .byte 3 ## DW_AT_name
+ .byte 14 ## DW_FORM_strp
+ .byte 73 ## DW_AT_type
+ .byte 19 ## DW_FORM_ref4
+ .byte 63 ## DW_AT_external
+ .byte 25 ## DW_FORM_flag_present
+ .byte 58 ## DW_AT_decl_file
+ .byte 11 ## DW_FORM_data1
+ .byte 59 ## DW_AT_decl_line
+ .byte 11 ## DW_FORM_data1
+ .byte 2 ## DW_AT_location
+ .byte 24 ## DW_FORM_exprloc
+ .byte 0 ## EOM(1)
+ .byte 0 ## EOM(2)
+ .byte 3 ## Abbreviation Code
+ .byte 36 ## DW_TAG_base_type
+ .byte 0 ## DW_CHILDREN_no
+ .byte 3 ## DW_AT_name
+ .byte 14 ## DW_FORM_strp
+ .byte 62 ## DW_AT_encoding
+ .byte 11 ## DW_FORM_data1
+ .byte 11 ## DW_AT_byte_size
+ .byte 11 ## DW_FORM_data1
+ .byte 0 ## EOM(1)
+ .byte 0 ## EOM(2)
+ .byte 0 ## EOM(3)
+ .section __DWARF,__debug_info,regular,debug
+Lsection_info:
+Lcu_begin0:
+ .long 56 ## Length of Unit
+ .short 5 ## DWARF version number
+ .byte 1 ## DWARF Unit Type
+ .byte 8 ## Address Size (in bytes)
+Lset0 = Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section
+ .long Lset0
+ .byte 1 ## Abbrev [1] 0xc:0x30 DW_TAG_compile_unit
+ .long 0 ## DW_AT_producer
+ .short 12 ## DW_AT_language
+ .long 55 ## DW_AT_name
+Lset1 = Lline_table_start0-Lsection_line ## DW_AT_stmt_list
+ .long Lset1
+ .long 63 ## DW_AT_comp_dir
+ .byte 2 ## Abbrev [2] 0x1f:0x15 DW_TAG_variable
+ .long 97 ## DW_AT_name
+ .long 52 ## DW_AT_type
+ ## DW_AT_external
+ .byte 1 ## DW_AT_decl_file
+ .byte 1 ## DW_AT_decl_line
+ .byte 9 ## DW_AT_location
+ .byte 3
+ .quad _i
+ .byte 3 ## Abbrev [3] 0x34:0x7 DW_TAG_base_type
+ .long 99 ## DW_AT_name
+ .byte 5 ## DW_AT_encoding
+ .byte 4 ## DW_AT_byte_size
+ .byte 0 ## End Of Children Mark
+ .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 1 ## 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 0 ## Bucket 0
+ .long 193495088 ## Hash in Bucket 0
+ .long Ltypes0-Ltypes_begin ## Offset in Bucket 0
+Ltypes0:
+ .long 99 ## int
+ .long 1 ## Num DIEs
+ .long 52
+ .short 31 ## error: Tag DW_TAG_ptr_to_member_type in accelerator table does not match Tag DW_TAG_base_type of DIE[0].
+ .byte 0
+ .long 0
+
+.subsections_via_symbols
+ .section __DWARF,__debug_line,regular,debug
+Lsection_line:
+Lline_table_start0:
OpenPOWER on IntegriCloud