diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" @@ -30,8 +31,14 @@ uint64_t UEndOffset, uint32_t D) { Offset = *OffsetPtr; Depth = D; - if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) + if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) { + U.getContext().getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF compile unit extends beyond its " + "bounds cu 0x%8.8" PRIx64 " at 0x%8.8" PRIx64, + U.getOffset(), Offset)); return false; + } uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); if (0 == AbbrCode) { // NULL debug tag entry. @@ -41,6 +48,11 @@ if (const auto *AbbrevSet = U.getAbbreviations()) AbbrevDecl = AbbrevSet->getAbbreviationDeclaration(AbbrCode); if (nullptr == AbbrevDecl) { + U.getContext().getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF abbreviation 0x%" PRIx64 " is not valid " + "in cu 0x%8.8" PRIx64 " at 0x%8.8" PRIx64, + AbbrCode, U.getOffset(), Offset)); // Restore the original offset. *OffsetPtr = Offset; return false; @@ -62,6 +74,11 @@ OffsetPtr, U.getFormParams())) { // We failed to skip this attribute's value, restore the original offset // and return the failure status. + U.getContext().getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF FORM_* 0x%x is not valid " + "in cu 0x%8.8" PRIx64 " at 0x%8.8" PRIx64, + AttrSpec.Form, U.getOffset(), *OffsetPtr)); *OffsetPtr = Offset; return false; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -385,6 +385,8 @@ // Normal DIE if (AbbrDecl->hasChildren()) ++Depth; + else if (Depth == 0) + break; // This unit has a single DIE with no children. } else { // NULL DIE. if (Depth > 0) @@ -393,17 +395,6 @@ break; // We are done with this compile unit! } } - - // Give a little bit of info if we encounter corrupt DWARF (our offset - // should always terminate at or before the start of the next compilation - // unit header). - if (DIEOffset > NextCUOffset) - Context.getWarningHandler()( - createStringError(errc::invalid_argument, - "DWARF compile unit extends beyond its " - "bounds cu 0x%8.8" PRIx64 " " - "at 0x%8.8" PRIx64 "\n", - getOffset(), DIEOffset)); } void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { diff --git a/llvm/test/tools/llvm-dwarfdump/X86/format-warnings.s b/llvm/test/tools/llvm-dwarfdump/X86/format-warnings.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/format-warnings.s @@ -0,0 +1,43 @@ +# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj --defsym=CUEND=1 \ +# RUN: | llvm-dwarfdump - 2>&1 | FileCheck --check-prefix=CHECK-CUEND %s +# CHECK-CUEND: warning: DWARF compile unit extends beyond its bounds cu 0x00000000 at 0x0000001f + +# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj --defsym=ABBREVNO=2 \ +# RUN: | llvm-dwarfdump - 2>&1 | FileCheck --check-prefix=CHECK-ABBREVNO %s +# CHECK-ABBREVNO: warning: DWARF abbreviation 0x2 is not valid in cu 0x00000000 at 0x0000000b + +# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj --defsym=FORMNO=0xdead \ +# RUN: | llvm-dwarfdump - 2>&1 | FileCheck --check-prefix=CHECK-FORMNO %s +# CHECK-FORMNO: warning: DWARF FORM_* 0xdead is not valid in cu 0x00000000 at 0x0000000c + + .section .debug_abbrev,"",@progbits + .uleb128 1 # Abbreviation Code + .uleb128 17 # DW_TAG_compile_unit + .uleb128 1 # DW_CHILDREN_yes + .uleb128 37 # DW_AT_producer +.ifndef FORMNO + .uleb128 8 # DW_FORM_string +.else + .uleb128 FORMNO +.endif + .uleb128 0 # end DW_AT_* + .uleb128 0 # end DW_FORM_* + .uleb128 0 # end abbreviation code + + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Lcu_end0-.Lcu_start0 # Length of Unit +.Lcu_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) +.ifndef ABBREVNO + .uleb128 1 # Abbrev [1] DW_TAG_compile_unit +.else + .uleb128 ABBREVNO +.endif + .asciz "hand-written DWARF" # DW_AT_producer +.ifndef CUEND + .uleb128 0 # End Of Children Mark +.endif +.Lcu_end0: