labath created this revision. labath added reviewers: clayborg, jankratochvil, JDevlieghere.
While parsing a childless compile unit DIE we could crash if the DIE was followed by any extra data (such as a superfluous end-of-children marker). This happened because the break-on-depth=0 check was performed only when parsing the null DIE, which was not correct because with a childless root DIE, we could reach the end of the unit without ever encountering the null DIE. If the compile unit contribution ended directly after the CU DIE, everything would be fine as we would terminate parsing due to reaching EOF. However, if the contribution contained extra data (perhaps a superfluous end-of-children marker), we would crash because we would treat that data as the begging of another compile unit. This fixes the crash by moving the depth=0 check to a more generic place, and also adds a regression test. https://reviews.llvm.org/D54417 Files: lit/SymbolFile/DWARF/childless-compile-unit.s source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -244,9 +244,6 @@ if (depth > 0) --depth; - if (depth == 0) - break; // We are done with this compile unit! - prev_die_had_children = false; } else { die_index_stack.back() = m_die_array.size() - 1; @@ -258,6 +255,9 @@ } prev_die_had_children = die_has_children; } + + if (depth == 0) + break; // We are done with this compile unit! } if (!m_die_array.empty()) { Index: lit/SymbolFile/DWARF/childless-compile-unit.s =================================================================== --- /dev/null +++ lit/SymbolFile/DWARF/childless-compile-unit.s @@ -0,0 +1,45 @@ +# Test that we don't crash when parsing slightly invalid DWARF. The compile +# unit in this file sets DW_CHILDREN_no, but it still includes an +# end-of-children marker in its contribution. + +# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o +# RUN: lldb-test symbols %t.o + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "Hand-written DWARF" +.Linfo_string1: + .asciz "-" +.Linfo_string2: + .asciz "/tmp" + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .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 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Lcu_length_end-.Lcu_length_start # Length of Unit +.Lcu_length_start: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x30 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 12 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Linfo_string2 # DW_AT_comp_dir + .byte 0 # Bogus End Of Children Mark +.Lcu_length_end:
Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -244,9 +244,6 @@ if (depth > 0) --depth; - if (depth == 0) - break; // We are done with this compile unit! - prev_die_had_children = false; } else { die_index_stack.back() = m_die_array.size() - 1; @@ -258,6 +255,9 @@ } prev_die_had_children = die_has_children; } + + if (depth == 0) + break; // We are done with this compile unit! } if (!m_die_array.empty()) { Index: lit/SymbolFile/DWARF/childless-compile-unit.s =================================================================== --- /dev/null +++ lit/SymbolFile/DWARF/childless-compile-unit.s @@ -0,0 +1,45 @@ +# Test that we don't crash when parsing slightly invalid DWARF. The compile +# unit in this file sets DW_CHILDREN_no, but it still includes an +# end-of-children marker in its contribution. + +# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o +# RUN: lldb-test symbols %t.o + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "Hand-written DWARF" +.Linfo_string1: + .asciz "-" +.Linfo_string2: + .asciz "/tmp" + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .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 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Lcu_length_end-.Lcu_length_start # Length of Unit +.Lcu_length_start: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x30 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 12 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Linfo_string2 # DW_AT_comp_dir + .byte 0 # Bogus End Of Children Mark +.Lcu_length_end:
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits