<div dir="ltr">This included some unused variables :)<div><br></div><div>I've gone ahead and removed them in r307987</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Jul 13, 2017 at 4:25 PM Spyridoula Gravani via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: sgravani<br>
Date: Thu Jul 13 16:25:24 2017<br>
New Revision: 307975<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=307975&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=307975&view=rev</a><br>
Log:<br>
[DWARF] Introduce verification for the unit header chain in .debug_info section to llvm-dwarfdump.<br>
<br>
This patch adds verification checks for the unit header chain in the .debug_info section.<br>
Specifically, for each unit in the .debug_info section, the verifier checks that:<br>
<br>
The unit length is valid (i.e. the unit can actually fit in the .debug_info section)<br>
The dwarf version of the unit is valid<br>
The address size is valid (4 or 8)<br>
The unit type (if the unit is in dwarf5) is valid<br>
The debug_abbrev_offset is valid<br>
<br>
Added:<br>
llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s<br>
Modified:<br>
llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h<br>
llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h<br>
llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp<br>
llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h?rev=307975&r1=307974&r2=307975&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h?rev=307975&r1=307974&r2=307975&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h Thu Jul 13 16:25:24 2017<br>
@@ -238,6 +238,34 @@ public:<br>
<br>
uint8_t getUnitType() const { return UnitType; }<br>
<br>
+ static bool isValidUnitType(uint8_t UnitType) {<br>
+ return UnitType == dwarf::DW_UT_compile || UnitType == dwarf::DW_UT_type ||<br>
+ UnitType == dwarf::DW_UT_partial ||<br>
+ UnitType == dwarf::DW_UT_skeleton ||<br>
+ UnitType == dwarf::DW_UT_split_compile ||<br>
+ UnitType == dwarf::DW_UT_split_type;<br>
+ }<br>
+<br>
+ /// \brief Return the number of bytes for the header of a unit of<br>
+ /// UnitType type.<br>
+ ///<br>
+ /// This function must be called with a valid unit type which in<br>
+ /// DWARF5 is defined as one of the following six types.<br>
+ static uint32_t getDWARF5HeaderSize(uint8_t UnitType) {<br>
+ switch (UnitType) {<br>
+ case dwarf::DW_UT_compile:<br>
+ case dwarf::DW_UT_partial:<br>
+ return 12;<br>
+ case dwarf::DW_UT_skeleton:<br>
+ case dwarf::DW_UT_split_compile:<br>
+ return 20;<br>
+ case dwarf::DW_UT_type:<br>
+ case dwarf::DW_UT_split_type:<br>
+ return 24;<br>
+ }<br>
+ llvm_unreachable("Invalid UnitType.");<br>
+ }<br>
+<br>
uint64_t getBaseAddress() const { return BaseAddr; }<br>
<br>
void setBaseAddress(uint64_t base_addr) {<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h?rev=307975&r1=307974&r2=307975&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h?rev=307975&r1=307974&r2=307975&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h Thu Jul 13 16:25:24 2017<br>
@@ -21,6 +21,7 @@ class DWARFContext;<br>
class DWARFDie;<br>
class DWARFUnit;<br>
class DWARFAcceleratorTable;<br>
+class DWARFDataExtractor;<br>
<br>
/// A class that verifies DWARF debug information given a DWARF Context.<br>
class DWARFVerifier {<br>
@@ -34,6 +35,29 @@ class DWARFVerifier {<br>
uint32_t NumDebugLineErrors = 0;<br>
uint32_t NumAppleNamesErrors = 0;<br>
<br>
+ /// Verifies the header of a unit in the .debug_info section.<br>
+ ///<br>
+ /// This function currently checks for:<br>
+ /// - Unit is in 32-bit DWARF format. The function can be modified to<br>
+ /// support 64-bit format.<br>
+ /// - The DWARF version is valid<br>
+ /// - The unit type is valid (if unit is in version >=5)<br>
+ /// - The unit doesn't extend beyond .debug_info section<br>
+ /// - The address size is valid<br>
+ /// - The offset in the .debug_abbrev section is valid<br>
+ ///<br>
+ /// \param DebugInfoData The .debug_info section data<br>
+ /// \param Offset A reference to the offset start of the unit. The offset will<br>
+ /// be updated to point to the next unit in .debug_info<br>
+ /// \param UnitIndex The index of the unit to be verified<br>
+ /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is<br>
+ /// in 64-bit format.<br>
+ ///<br>
+ /// \returns true if the header is verified successfully, false otherwise.<br>
+ bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,<br>
+ uint32_t *Offset, unsigned UnitIndex,<br>
+ bool &isUnitDWARF64);<br>
+<br>
/// Verifies the attribute's DWARF attribute and its value.<br>
///<br>
/// This function currently checks for:<br>
@@ -78,6 +102,14 @@ class DWARFVerifier {<br>
public:<br>
DWARFVerifier(raw_ostream &S, DWARFContext &D)<br>
: OS(S), DCtx(D) {}<br>
+ /// Verify the unit header chain in the .debug_info section.<br>
+ ///<br>
+ /// Any errors are reported to the stream that this object was<br>
+ /// constructed with.<br>
+ ///<br>
+ /// \returns true if the unit header chain verifies successfully, false<br>
+ /// otherwise.<br>
+ bool handleDebugInfoUnitHeaderChain();<br>
/// Verify the information in the .debug_info section.<br>
///<br>
/// Any errors are reported to the stream that was this object was<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=307975&r1=307974&r2=307975&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=307975&r1=307974&r2=307975&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Thu Jul 13 16:25:24 2017<br>
@@ -414,6 +414,8 @@ DWARFDie DWARFContext::getDIEForOffset(u<br>
bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {<br>
bool Success = true;<br>
DWARFVerifier verifier(OS, *this);<br>
+ if (!verifier.handleDebugInfoUnitHeaderChain())<br>
+ Success = false;<br>
if (DumpType == DIDT_All || DumpType == DIDT_Info) {<br>
if (!verifier.handleDebugInfo())<br>
Success = false;<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp?rev=307975&r1=307974&r2=307975&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp?rev=307975&r1=307974&r2=307975&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp Thu Jul 13 16:25:24 2017<br>
@@ -24,6 +24,98 @@ using namespace llvm;<br>
using namespace dwarf;<br>
using namespace object;<br>
<br>
+bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,<br>
+ uint32_t *Offset, unsigned UnitIndex,<br>
+ bool &isUnitDWARF64) {<br>
+ uint32_t AbbrOffset, Length;<br>
+ uint8_t AddrSize = 0, UnitType = 0;<br>
+ uint16_t Version;<br>
+ bool Success = true;<br>
+ uint32_t HeaderSize =<br>
+ 11; // means that we have only compile units in .debug_info<br>
+<br>
+ bool ValidLength = false;<br>
+ bool ValidVersion = false;<br>
+ bool ValidAddrSize = false;<br>
+ bool ValidType = true;<br>
+ bool ValidAbbrevOffset = true;<br>
+<br>
+ uint32_t OffsetStart = *Offset;<br>
+ Length = DebugInfoData.getU32(Offset);<br>
+ if (Length == UINT32_MAX) {<br>
+ isUnitDWARF64 = true;<br>
+ OS << format(<br>
+ "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",<br>
+ UnitIndex);<br>
+ return false;<br>
+ }<br>
+ Version = DebugInfoData.getU16(Offset);<br>
+<br>
+ if (Version >= 5) {<br>
+ UnitType = DebugInfoData.getU8(Offset);<br>
+ AddrSize = DebugInfoData.getU8(Offset);<br>
+ AbbrOffset = DebugInfoData.getU32(Offset);<br>
+ ValidType = DWARFUnit::isValidUnitType(UnitType);<br>
+ if (ValidType)<br>
+ HeaderSize = DWARFUnit::getDWARF5HeaderSize(UnitType);<br>
+ } else {<br>
+ AbbrOffset = DebugInfoData.getU32(Offset);<br>
+ AddrSize = DebugInfoData.getU8(Offset);<br>
+ }<br>
+<br>
+ if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))<br>
+ ValidAbbrevOffset = false;<br>
+<br>
+ ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);<br>
+ ValidVersion = DWARFContext::isSupportedVersion(Version);<br>
+ ValidAddrSize = AddrSize == 4 || AddrSize == 8;<br>
+ if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||<br>
+ !ValidType) {<br>
+ Success = false;<br>
+ OS << format("Units[%d] - start offset: 0x%08x \n", UnitIndex, OffsetStart);<br>
+ if (!ValidLength)<br>
+ OS << "\tError: The length for this unit is too "<br>
+ "large for the .debug_info provided.\n";<br>
+ if (!ValidVersion)<br>
+ OS << "\tError: The 16 bit unit header version is not valid.\n";<br>
+ if (!ValidType)<br>
+ OS << "\tError: The unit type encoding is not valid.\n";<br>
+ if (!ValidAbbrevOffset)<br>
+ OS << "\tError: The offset into the .debug_abbrev section is "<br>
+ "not valid.\n";<br>
+ if (!ValidAddrSize)<br>
+ OS << "\tError: The address size is unsupported.\n";<br>
+ }<br>
+ *Offset = OffsetStart + Length + 4;<br>
+ return Success;<br>
+}<br>
+<br>
+bool DWARFVerifier::handleDebugInfoUnitHeaderChain() {<br>
+ OS << "Verifying .debug_info Unit Header Chain...\n";<br>
+<br>
+ DWARFDataExtractor DebugInfoData(DCtx.getInfoSection(), DCtx.isLittleEndian(),<br>
+ 0);<br>
+ uint32_t OffsetStart, Offset = 0, UnitIdx = 0;<br>
+ bool isUnitDWARF64 = false;<br>
+ bool Success = true;<br>
+ bool hasDIE = DebugInfoData.isValidOffset(Offset);<br>
+ while (hasDIE) {<br>
+ OffsetStart = Offset;<br>
+ if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, isUnitDWARF64)) {<br>
+ Success = false;<br>
+ if (isUnitDWARF64)<br>
+ break;<br>
+ }<br>
+ hasDIE = DebugInfoData.isValidOffset(Offset);<br>
+ ++UnitIdx;<br>
+ }<br>
+ if (UnitIdx == 0 && !hasDIE) {<br>
+ OS << "Warning: .debug_info is empty.\n";<br>
+ Success = true;<br>
+ }<br>
+ return Success;<br>
+}<br>
+<br>
void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,<br>
DWARFAttribute &AttrValue) {<br>
const auto Attr = AttrValue.Attr;<br>
<br>
Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s?rev=307975&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s?rev=307975&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s (added)<br>
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s Thu Jul 13 16:25:24 2017<br>
@@ -0,0 +1,81 @@<br>
+# RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \<br>
+# RUN: | not llvm-dwarfdump -verify - \<br>
+# RUN: | FileCheck %s<br>
+<br>
+# CHECK: Verifying .debug_info Unit Header Chain...<br>
+# CHECK-NEXT: Units[1] - start offset: 0x0000000d<br>
+# CHECK-NEXT: Error: The unit type encoding is not valid.<br>
+# CHECK-NEXT: Error: The address size is unsupported.<br>
+# CHECK-NEXT: Units[2] - start offset: 0x00000026<br>
+# CHECK-NEXT: Error: The 16 bit unit header version is not valid.<br>
+# CHECK-NEXT: Error: The offset into the .debug_abbrev section is not valid.<br>
+# CHECK-NEXT: Units[4] - start offset: 0x00000041<br>
+# CHECK-NEXT: Error: The length for this unit is too large for the .debug_info provided.<br>
+<br>
+ .section __TEXT,__text,regular,pure_instructions<br>
+ .file 1 "basic.c"<br>
+ .comm _i,4,2 ## @i<br>
+ .comm _j,4,2 ## @j<br>
+ .section __DWARF,__debug_str,regular,debug<br>
+Linfo_string:<br>
+ .asciz "clang version 5.0.0 (trunk 307232) (llvm/trunk 307042)" ## string offset=0<br>
+ .asciz "basic.c" ## string offset=55<br>
+ .asciz "/Users/sgravani/Development/tests" ## string offset=63<br>
+ .asciz "i" ## string offset=97<br>
+ .asciz "int" ## string offset=99<br>
+ .asciz "j" ## string offset=103<br>
+ .section __DWARF,__debug_abbrev,regular,debug<br>
+Lsection_abbrev:<br>
+ .byte 1 ## Abbreviation Code<br>
+ .byte 17 ## DW_TAG_compile_unit<br>
+ .byte 0 ## EOM(1)<br>
+ .byte 0 ## EOM(2)<br>
+ .byte 0 ## EOM(3)<br>
+ .section __DWARF,__debug_info,regular,debug<br>
+Lsection_info:<br>
+Lcu_begin0:<br>
+ .long 9 ## Length of Unit<br>
+ .short 4 ## DWARF version number<br>
+Lset0 = Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section<br>
+ .long Lset0<br>
+ .byte 4 ## Address Size (in bytes)<br>
+ .byte 1 ## Abbrev [1] 0xc:0x45 DW_TAG_compile_unit<br>
+ .byte 0 ## End Of Children Mark<br>
+Ltu_begin0:<br>
+ .long 21 ## Length of Unit<br>
+ .short 5 ## DWARF version number<br>
+ .byte 0 ## DWARF Unit Type -- Error: The unit type encoding is not valid.<br>
+ .byte 3 ## Address Size (in bytes) -- Error: The address size is unsupported.<br>
+ .long 0<br>
+ .quad 0<br>
+ .long 0<br>
+ .byte 0<br>
+Lcu_begin1:<br>
+ .long 10 ## Length of Unit<br>
+ .short 6 ## DWARF version number -- Error: The 16 bit unit header version is not valid.<br>
+ .byte 1 ## DWARF Unit Type<br>
+ .byte 4 ## Address Size (in bytes) -- The offset into the .debug_abbrev section is not valid.<br>
+ .long Lline_table_start0<br>
+ .byte 1 ## Abbrev [1] 0xc:0x45 DW_TAG_compile_unit<br>
+ .byte 0 ## End Of Children Mark<br>
+Lcu_begin2:<br>
+ .long 9 ## Length of Unit<br>
+ .short 5 ## DWARF version number<br>
+ .byte 1 ## DWARF Unit Type<br>
+ .byte 4 ## Address Size (in bytes)<br>
+ .long 0 ## Abbrev offset<br>
+ .byte 0<br>
+Ltu_begin1:<br>
+ .long 26 ## Length of Unit -- Error: The length for this unit is too large for the .debug_info provided.<br>
+ .short 5 ## DWARF version number<br>
+ .byte 2 ## DWARF Unit Type<br>
+ .byte 4 ## Address Size (in bytes)<br>
+ .long 0<br>
+ .quad 0<br>
+ .long 0<br>
+ .byte 0<br>
+<br>
+.subsections_via_symbols<br>
+ .section __DWARF,__debug_line,regular,debug<br>
+Lsection_line:<br>
+Lline_table_start0:<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>