<div dir="ltr">Hey - could we revisit the review for this (I've followed up there too) - I feel like the crux of my concerns was never really resolved? <br><br>(if I recall correctly, the original version of this code was non-recursive (& only walked a fixed set of levels (one abstract, one specification)) - I'm not sure how/why it became recursive & would like to revisit/reexamine that decision before we add more complexity to handle that route)</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Apr 30, 2018 at 10:06 AM Jonas Devlieghere 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: jdevlieghere<br>
Date: Mon Apr 30 10:02:41 2018<br>
New Revision: 331200<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=331200&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=331200&view=rev</a><br>
Log:<br>
[DebugInfo] Prevent infinite recursion for malformed DWARF<br>
<br>
This prevents infinite recursion in DWARFDie::findRecursively for<br>
malformed DWARF where a DIE references itself.<br>
<br>
This fixes PR36257.<br>
<br>
Differential revision: <a href="https://reviews.llvm.org/D43092" rel="noreferrer" target="_blank">https://reviews.llvm.org/D43092</a><br>
<br>
Added:<br>
    llvm/trunk/test/tools/llvm-dwarfdump/X86/invalid_abstract_origin.s<br>
Modified:<br>
    llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp?rev=331200&r1=331199&r2=331200&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp?rev=331200&r1=331199&r2=331200&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp Mon Apr 30 10:02:41 2018<br>
@@ -10,6 +10,7 @@<br>
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"<br>
 #include "llvm/ADT/None.h"<br>
 #include "llvm/ADT/Optional.h"<br>
+#include "llvm/ADT/SmallSet.h"<br>
 #include "llvm/ADT/StringRef.h"<br>
 #include "llvm/BinaryFormat/Dwarf.h"<br>
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"<br>
@@ -295,18 +296,37 @@ DWARFDie::find(ArrayRef<dwarf::Attribute<br>
<br>
 Optional<DWARFFormValue><br>
 DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {<br>
-  if (!isValid())<br>
-    return None;<br>
-  if (auto Value = find(Attrs))<br>
-    return Value;<br>
-  if (auto Die = getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) {<br>
-    if (auto Value = Die.findRecursively(Attrs))<br>
-      return Value;<br>
-  }<br>
-  if (auto Die = getAttributeValueAsReferencedDie(DW_AT_specification)) {<br>
-    if (auto Value = Die.findRecursively(Attrs))<br>
+  std::vector<DWARFDie> Worklist;<br>
+  Worklist.push_back(*this);<br>
+<br>
+  // Keep track if DIEs already seen to prevent infinite recursion.<br>
+  // Empirically we rarely see a depth of more than 3 when dealing with valid<br>
+  // DWARF. This corresponds to following the DW_AT_abstract_origin and<br>
+  // DW_AT_specification just once.<br>
+  SmallSet<DWARFDie, 3> Seen;<br>
+<br>
+  while (!Worklist.empty()) {<br>
+    DWARFDie Die = Worklist.back();<br>
+    Worklist.pop_back();<br>
+<br>
+    if (!Die.isValid())<br>
+      continue;<br>
+<br>
+    if (Seen.count(Die))<br>
+      continue;<br>
+<br>
+    Seen.insert(Die);<br>
+<br>
+    if (auto Value = Die.find(Attrs))<br>
       return Value;<br>
+<br>
+    if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))<br>
+      Worklist.push_back(D);<br>
+<br>
+    if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification))<br>
+      Worklist.push_back(D);<br>
   }<br>
+<br>
   return None;<br>
 }<br>
<br>
<br>
Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/invalid_abstract_origin.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/invalid_abstract_origin.s?rev=331200&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/invalid_abstract_origin.s?rev=331200&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/invalid_abstract_origin.s (added)<br>
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/invalid_abstract_origin.s Mon Apr 30 10:02:41 2018<br>
@@ -0,0 +1,296 @@<br>
+# This test ensures that dwarfdump doesn't crash for malformed DWARF where a<br>
+# DIE references itself.<br>
+#<br>
+# Source:<br>
+#   void f();<br>
+#   __attribute__((always_inline)) void g() {<br>
+#     f();<br>
+#   }<br>
+#   void h() {<br>
+#     g();<br>
+#   };<br>
+#<br>
+# Compile with:<br>
+#   clang inlined.c -S -g -o inlined.s<br>
+#<br>
+# RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \<br>
+# RUN:   | llvm-dwarfdump -debug-info - \<br>
+# RUN:   | FileCheck %s<br>
+<br>
+# CHECK: 0x0000005a:     DW_TAG_inlined_subroutine<br>
+# CHECK-NEXT: DW_AT_abstract_origin (0x0000005a)<br>
+<br>
+       .section        __TEXT,__text,regular,pure_instructions<br>
+       .macosx_version_min 10, 13<br>
+       .globl  _g                      ## -- Begin function g<br>
+       .p2align        4, 0x90<br>
+_g:                                     ## @g<br>
+Lfunc_begin0:<br>
+       .file   1 "inlined.c"<br>
+       .loc    1 2 0                   ## inlined.c:2:0<br>
+       .cfi_startproc<br>
+## %bb.0:                               ## %entry<br>
+       pushq   %rbp<br>
+       .cfi_def_cfa_offset 16<br>
+       .cfi_offset %rbp, -16<br>
+       movq    %rsp, %rbp<br>
+       .cfi_def_cfa_register %rbp<br>
+Ltmp0:<br>
+       .loc    1 3 3 prologue_end      ## inlined.c:3:3<br>
+       movb    $0, %al<br>
+       callq   _f<br>
+       .loc    1 4 1                   ## inlined.c:4:1<br>
+       popq    %rbp<br>
+       retq<br>
+Ltmp1:<br>
+Lfunc_end0:<br>
+       .cfi_endproc<br>
+                                        ## -- End function<br>
+       .globl  _h                      ## -- Begin function h<br>
+       .p2align        4, 0x90<br>
+_h:                                     ## @h<br>
+Lfunc_begin1:<br>
+       .loc    1 5 0                   ## inlined.c:5:0<br>
+       .cfi_startproc<br>
+## %bb.0:                               ## %entry<br>
+       pushq   %rbp<br>
+       .cfi_def_cfa_offset 16<br>
+       .cfi_offset %rbp, -16<br>
+       movq    %rsp, %rbp<br>
+       .cfi_def_cfa_register %rbp<br>
+Ltmp2:<br>
+       .loc    1 3 3 prologue_end      ## inlined.c:3:3<br>
+       movb    $0, %al<br>
+       callq   _f<br>
+Ltmp3:<br>
+       .loc    1 7 1                   ## inlined.c:7:1<br>
+       popq    %rbp<br>
+       retq<br>
+Ltmp4:<br>
+Lfunc_end1:<br>
+       .cfi_endproc<br>
+                                        ## -- End function<br>
+       .section        __DWARF,__debug_str,regular,debug<br>
+Linfo_string:<br>
+       .asciz  "clang version 7.0.0 "  ## string offset=0<br>
+       .asciz  "inlined.c"             ## string offset=21<br>
+       .asciz  "/private/tmp"          ## string offset=31<br>
+       .asciz  "g"                     ## string offset=44<br>
+       .asciz  "h"                     ## string offset=46<br>
+       .section        __DWARF,__debug_abbrev,regular,debug<br>
+Lsection_abbrev:<br>
+       .byte   1                       ## Abbreviation Code<br>
+       .byte   17                      ## DW_TAG_compile_unit<br>
+       .byte   1                       ## DW_CHILDREN_yes<br>
+       .byte   37                      ## DW_AT_producer<br>
+       .byte   14                      ## DW_FORM_strp<br>
+       .byte   19                      ## DW_AT_language<br>
+       .byte   5                       ## DW_FORM_data2<br>
+       .byte   3                       ## DW_AT_name<br>
+       .byte   14                      ## DW_FORM_strp<br>
+       .byte   16                      ## DW_AT_stmt_list<br>
+       .byte   23                      ## DW_FORM_sec_offset<br>
+       .byte   27                      ## DW_AT_comp_dir<br>
+       .byte   14                      ## DW_FORM_strp<br>
+       .byte   17                      ## DW_AT_low_pc<br>
+       .byte   1                       ## DW_FORM_addr<br>
+       .byte   18                      ## DW_AT_high_pc<br>
+       .byte   6                       ## DW_FORM_data4<br>
+       .byte   0                       ## EOM(1)<br>
+       .byte   0                       ## EOM(2)<br>
+       .byte   2                       ## Abbreviation Code<br>
+       .byte   46                      ## DW_TAG_subprogram<br>
+       .byte   0                       ## DW_CHILDREN_no<br>
+       .byte   17                      ## DW_AT_low_pc<br>
+       .byte   1                       ## DW_FORM_addr<br>
+       .byte   18                      ## DW_AT_high_pc<br>
+       .byte   6                       ## DW_FORM_data4<br>
+       .byte   64                      ## DW_AT_frame_base<br>
+       .byte   24                      ## DW_FORM_exprloc<br>
+       .byte   49                      ## DW_AT_abstract_origin<br>
+       .byte   19                      ## DW_FORM_ref4<br>
+       .byte   0                       ## EOM(1)<br>
+       .byte   0                       ## EOM(2)<br>
+       .byte   3                       ## Abbreviation Code<br>
+       .byte   46                      ## DW_TAG_subprogram<br>
+       .byte   0                       ## DW_CHILDREN_no<br>
+       .byte   3                       ## DW_AT_name<br>
+       .byte   14                      ## DW_FORM_strp<br>
+       .byte   58                      ## DW_AT_decl_file<br>
+       .byte   11                      ## DW_FORM_data1<br>
+       .byte   59                      ## DW_AT_decl_line<br>
+       .byte   11                      ## DW_FORM_data1<br>
+       .byte   63                      ## DW_AT_external<br>
+       .byte   25                      ## DW_FORM_flag_present<br>
+       .byte   32                      ## DW_AT_inline<br>
+       .byte   11                      ## DW_FORM_data1<br>
+       .byte   0                       ## EOM(1)<br>
+       .byte   0                       ## EOM(2)<br>
+       .byte   4                       ## Abbreviation Code<br>
+       .byte   46                      ## DW_TAG_subprogram<br>
+       .byte   1                       ## DW_CHILDREN_yes<br>
+       .byte   17                      ## DW_AT_low_pc<br>
+       .byte   1                       ## DW_FORM_addr<br>
+       .byte   18                      ## DW_AT_high_pc<br>
+       .byte   6                       ## DW_FORM_data4<br>
+       .byte   64                      ## DW_AT_frame_base<br>
+       .byte   24                      ## DW_FORM_exprloc<br>
+       .byte   3                       ## DW_AT_name<br>
+       .byte   14                      ## DW_FORM_strp<br>
+       .byte   58                      ## DW_AT_decl_file<br>
+       .byte   11                      ## DW_FORM_data1<br>
+       .byte   59                      ## DW_AT_decl_line<br>
+       .byte   11                      ## DW_FORM_data1<br>
+       .byte   63                      ## DW_AT_external<br>
+       .byte   25                      ## DW_FORM_flag_present<br>
+       .byte   0                       ## EOM(1)<br>
+       .byte   0                       ## EOM(2)<br>
+       .byte   5                       ## Abbreviation Code<br>
+       .byte   29                      ## DW_TAG_inlined_subroutine<br>
+       .byte   0                       ## DW_CHILDREN_no<br>
+       .byte   49                      ## DW_AT_abstract_origin<br>
+       .byte   19                      ## DW_FORM_ref4<br>
+       .byte   17                      ## DW_AT_low_pc<br>
+       .byte   1                       ## DW_FORM_addr<br>
+       .byte   18                      ## DW_AT_high_pc<br>
+       .byte   6                       ## DW_FORM_data4<br>
+       .byte   88                      ## DW_AT_call_file<br>
+       .byte   11                      ## DW_FORM_data1<br>
+       .byte   89                      ## DW_AT_call_line<br>
+       .byte   11                      ## DW_FORM_data1<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   107                     ## Length of Unit<br>
+       .short  4                       ## DWARF version number<br>
+Lset0 = Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section<br>
+       .long   Lset0<br>
+       .byte   8                       ## Address Size (in bytes)<br>
+       .byte   1                       ## Abbrev [1] 0xb:0x64 DW_TAG_compile_unit<br>
+       .long   0                       ## DW_AT_producer<br>
+       .short  12                      ## DW_AT_language<br>
+       .long   21                      ## DW_AT_name<br>
+Lset1 = Lline_table_start0-Lsection_line ## DW_AT_stmt_list<br>
+       .long   Lset1<br>
+       .long   31                      ## DW_AT_comp_dir<br>
+       .quad   Lfunc_begin0            ## DW_AT_low_pc<br>
+Lset2 = Lfunc_end1-Lfunc_begin0         ## DW_AT_high_pc<br>
+       .long   Lset2<br>
+       .byte   2                       ## Abbrev [2] 0x2a:0x13 DW_TAG_subprogram<br>
+       .quad   Lfunc_begin0            ## DW_AT_low_pc<br>
+Lset3 = Lfunc_end0-Lfunc_begin0         ## DW_AT_high_pc<br>
+       .long   Lset3<br>
+       .byte   1                       ## DW_AT_frame_base<br>
+       .byte   86<br>
+       .long   61                      ## DW_AT_abstract_origin<br>
+       .byte   3                       ## Abbrev [3] 0x3d:0x8 DW_TAG_subprogram<br>
+       .long   44                      ## DW_AT_name<br>
+       .byte   1                       ## DW_AT_decl_file<br>
+       .byte   2                       ## DW_AT_decl_line<br>
+                                        ## DW_AT_external<br>
+       .byte   1                       ## DW_AT_inline<br>
+       .byte   4                       ## Abbrev [4] 0x45:0x29 DW_TAG_subprogram<br>
+       .quad   Lfunc_begin1            ## DW_AT_low_pc<br>
+Lset4 = Lfunc_end1-Lfunc_begin1         ## DW_AT_high_pc<br>
+       .long   Lset4<br>
+       .byte   1                       ## DW_AT_frame_base<br>
+       .byte   86<br>
+       .long   46                      ## DW_AT_name<br>
+       .byte   1                       ## DW_AT_decl_file<br>
+       .byte   5                       ## DW_AT_decl_line<br>
+                                        ## DW_AT_external<br>
+       .byte   5                       ## Abbrev [5] 0x5a:0x13 DW_TAG_inlined_subroutine<br>
+       .long   90                      ## DW_AT_abstract_origin <- We modified the value so the DIE references itself.<br>
+       .quad   Ltmp2                   ## DW_AT_low_pc<br>
+Lset5 = Ltmp3-Ltmp2                     ## DW_AT_high_pc<br>
+       .long   Lset5<br>
+       .byte   1                       ## DW_AT_call_file<br>
+       .byte   6                       ## DW_AT_call_line<br>
+       .byte   0                       ## End Of Children Mark<br>
+       .byte   0                       ## End Of Children Mark<br>
+       .section        __DWARF,__debug_ranges,regular,debug<br>
+Ldebug_range:<br>
+       .section        __DWARF,__debug_macinfo,regular,debug<br>
+Ldebug_macinfo:<br>
+Lcu_macro_begin0:<br>
+       .byte   0                       ## End Of Macro List Mark<br>
+       .section        __DWARF,__apple_names,regular,debug<br>
+Lnames_begin:<br>
+       .long   1212240712              ## Header Magic<br>
+       .short  1                       ## Header Version<br>
+       .short  0                       ## Header Hash Function<br>
+       .long   2                       ## Header Bucket Count<br>
+       .long   2                       ## Header Hash Count<br>
+       .long   12                      ## Header Data Length<br>
+       .long   0                       ## HeaderData Die Offset Base<br>
+       .long   1                       ## HeaderData Atom Count<br>
+       .short  1                       ## DW_ATOM_die_offset<br>
+       .short  6                       ## DW_FORM_data4<br>
+       .long   0                       ## Bucket 0<br>
+       .long   1                       ## Bucket 1<br>
+       .long   177676                  ## Hash in Bucket 0<br>
+       .long   177677                  ## Hash in Bucket 1<br>
+       .long   LNames0-Lnames_begin    ## Offset in Bucket 0<br>
+       .long   LNames1-Lnames_begin    ## Offset in Bucket 1<br>
+LNames0:<br>
+       .long   44                      ## g<br>
+       .long   2                       ## Num DIEs<br>
+       .long   42<br>
+       .long   90<br>
+       .long   0<br>
+LNames1:<br>
+       .long   46                      ## h<br>
+       .long   1                       ## Num DIEs<br>
+       .long   69<br>
+       .long   0<br>
+       .section        __DWARF,__apple_objc,regular,debug<br>
+Lobjc_begin:<br>
+       .long   1212240712              ## Header Magic<br>
+       .short  1                       ## Header Version<br>
+       .short  0                       ## Header Hash Function<br>
+       .long   1                       ## Header Bucket Count<br>
+       .long   0                       ## Header Hash Count<br>
+       .long   12                      ## Header Data Length<br>
+       .long   0                       ## HeaderData Die Offset Base<br>
+       .long   1                       ## HeaderData Atom Count<br>
+       .short  1                       ## DW_ATOM_die_offset<br>
+       .short  6                       ## DW_FORM_data4<br>
+       .long   -1                      ## Bucket 0<br>
+       .section        __DWARF,__apple_namespac,regular,debug<br>
+Lnamespac_begin:<br>
+       .long   1212240712              ## Header Magic<br>
+       .short  1                       ## Header Version<br>
+       .short  0                       ## Header Hash Function<br>
+       .long   1                       ## Header Bucket Count<br>
+       .long   0                       ## Header Hash Count<br>
+       .long   12                      ## Header Data Length<br>
+       .long   0                       ## HeaderData Die Offset Base<br>
+       .long   1                       ## HeaderData Atom Count<br>
+       .short  1                       ## DW_ATOM_die_offset<br>
+       .short  6                       ## DW_FORM_data4<br>
+       .long   -1                      ## Bucket 0<br>
+       .section        __DWARF,__apple_types,regular,debug<br>
+Ltypes_begin:<br>
+       .long   1212240712              ## Header Magic<br>
+       .short  1                       ## Header Version<br>
+       .short  0                       ## Header Hash Function<br>
+       .long   1                       ## Header Bucket Count<br>
+       .long   0                       ## Header Hash Count<br>
+       .long   20                      ## Header Data Length<br>
+       .long   0                       ## HeaderData Die Offset Base<br>
+       .long   3                       ## HeaderData Atom Count<br>
+       .short  1                       ## DW_ATOM_die_offset<br>
+       .short  6                       ## DW_FORM_data4<br>
+       .short  3                       ## DW_ATOM_die_tag<br>
+       .short  5                       ## DW_FORM_data2<br>
+       .short  4                       ## DW_ATOM_type_flags<br>
+       .short  11                      ## DW_FORM_data1<br>
+       .long   -1                      ## Bucket 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>