facebookarchive / BOLT

Binary Optimization and Layout Tool - A linux command-line utility used for optimizing performance of binaries
2.51k stars 176 forks source link

[bug]Dwarf Error: Cannot handle DW_FORM_indirect in updating debug_abbrev #236

Closed HShan886 closed 2 years ago

HShan886 commented 2 years ago

Hi,

when using --update-debug-sections options, llvm-bolt prints a lot of BOLT-ERROR/BOLT-WARNING, such as: BOLT-WARNING: empty location list detected at 0xf595166 for DIE at 0x18e9511e in CU at 0x18e849dc BOLT-ERROR: cannot update ranges for DIE at offset 0x18e96584

BOLT-WARNING:

.debug_info contents:
0x18e950fa:   DW_TAG_subprogram
                DW_AT_abstract_origin   (0x18e950e0 "_ZNSt3tr116_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_destroyEv")
                DW_AT_linkage_name      ("_ZNSt3tr116_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_destroyEv")
                DW_AT_low_pc    (0x0000000000000000)
                DW_AT_high_pc   (0x0000000000000012)
                DW_AT_frame_base        (DW_OP_call_frame_cfa)
                DW_AT_object_pointer    (0x18e9511e)
                DW_AT_GNU_all_call_sites        (true)
                DW_AT_sibling   (0x18e9513c)
0x18e9511e:     DW_TAG_formal_parameter
                  DW_AT_abstract_origin (0x18e950ef "this")
                  DW_AT_location        (0x0f595156: )

BOLT-ERROR due to dwarf information 0x18e96584: DW_TAG_lexical_block without DW_AT_low_pc and DW_AT_high_pc.

My binary is compiled with Gcc-4.9.2 and '-g' compile option.

Finally, when I debug the new binary with gdb-7.6, This new binary loses line information and function information, even global variable information. I am a newbie about dwarf. More help would be appreciated.

HShan886 commented 2 years ago

Using the following command $llvm-dwarfdump -a newbinary.bolt Getting a warning, like warning: DWARF unit at offset 0x017608f3 contains invalid FORM_* 0x16 at offset 0x0176090a

Comppare origin .debug_abbrev with bolt of my binary, the addr/data8 is converted into indirect/sec_offset, for example Origin DW_AT_low_pc DW_FORM_addr DW_AT_high_pc DW_FORM_data8

Updated DW_AT_low_pc DW_FORM_indirect DW_AT_ranges DW_FORM_sec_offset Moreover, gdb report an error about DW_FROM_indirect. Dwarf Error: Cannot handle DW_FORM_<unknown: 1049776> in DWARF reader Then, gdb will consider new-binary without debug symbol.

Is there a occupied memory bug in updated debug abbrev stage (DWARFRewriter::convertToRanges) ?

maksfb commented 2 years ago

Thanks for reporting the problem.

BOLT-WARNING: empty location list detected at ...

These warnings are innocuous and could be safely ignored.

BOLT-ERROR: cannot update ranges for DIE at offset...

In this case the input did not contain address information. It can be ignored as well.

The error messages from gdb and llvm-dwarfdump look serious. The .debug_abbrev conversion is expected, but the new format should be compatible with all tooling. Do you use the latest version of BOLT and llvm-dwarfdump?

HShan886 commented 2 years ago

The error messages from gdb and llvm-dwarfdump look serious. The .debug_abbrev conversion is expected, but the new format should be compatible with all tooling. Do you use the latest version of BOLT and llvm-dwarfdump?

Yes, I use latest version. And when I comment conversion code, gdb will read symbols correctly, but debug information is wrong.

maksfb commented 2 years ago

Are you using split DWARF for the binary? Can you repro using a smaller binary that you can share?

HShan886 commented 2 years ago

@maksfb my binary is compiled without -gsplit-dwarf, and I doesn't strip the binary. I try to reduce my binary size for verify dwarf recently, If success, I will share it.

Moreover, when use llvm-objdump -S binary.bolt, I get a core, this due to getCU function which return null.

warning: DWARF unit at offset 0x017608f3 contains invalid FORM_* 0x16 at offset 0x0176090a
llvm-objdump: /tmp/BOLT/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h:60: const llvm::DWARFAbbreviationDeclaration* llvm::DWARFDie::getAbbreviationDeclarationPtr() const: Assertion `isValid() && "must check validity prior to calling"' failed.

 #9 0x000000000046ba8f llvm::DWARFDie::getAbbreviationDeclarationPtr() const /tmp/BOLT/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h:60:5
#10 0x000000000046baba llvm::DWARFDie::getTag() const /tmpBOLT/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h:73:52
#11 0x000000000063e0c6 llvm::DWARFDie::isSubroutineDIE() const /tmp/BOLT/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp:815:20
#12 0x000000000065c776 llvm::DWARFUnit::updateAddressDieMap(llvm::DWARFDie) /tmp/BOLT/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp:695:3
#13 0x000000000065caba llvm::DWARFUnit::getSubroutineForAddress(unsigned long) /tmp/BOLT/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp:729:42
#14 0x000000000065cc22 llvm::DWARFUnit::getInlinedChainForAddress(unsigned long, llvm::SmallVectorImpl<llvm::DWARFDie>&) /tmp/BOLT/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp:748:59
#15 0x00000000005cf32d getFunctionNameAndStartLineForAddress(llvm::DWARFCompileUnit*, unsigned long, llvm::DINameKind, llvm::DILineInfoSpecifier::FileLineInfoKind, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, unsigned int&, llvm::Optional<unsigned long>&) /tmp/BOLT/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp:1048:25
#16 0x00000000005d04e1 llvm::DWARFContext::getLineInfoForAddress(llvm::object::SectionedAddress, llvm::DILineInfoSpecifier) /tmp/BOLT/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp:1235:40
HShan886 commented 2 years ago

Are you using split DWARF for the binary? Can you repro using a smaller binary that you can share?

This binary is compiled by gcc-4.9.2 and link a libtcmalloc.a which was compiled by gcc-4.1.2. So I guess dwarf2 generated by gcc-4.1.2 is not incompatible with bolt.

maksfb commented 2 years ago

Did you get a warning: BOLT-WARNING: high_pc expected immediately after low_pc. ?

HShan886 commented 2 years ago

Did you get a warning: BOLT-WARNING: high_pc expected immediately after low_pc. ?

Yes, I get a "BOLT-WARNING: high_pc expected immediately after low_pc. Cannot update DIE at offset 0x4f5" original dwarf information:

0x000004f5: DW_TAG_compile_unit
              DW_AT_stmt_list   (0x0000017f)
              DW_AT_high_pc     (0x000000000040e75a)
              DW_AT_low_pc      (0x000000000040e620)
              DW_AT_producer    ("GNU C 4.1.2")
              DW_AT_language    (DW_LANG_C89)
              DW_AT_name        ("src/base/dynamic_annotations.c")
              DW_AT_comp_dir    ("/tmp/gperftools-gperftools-2.0")
ayermolo commented 2 years ago

@Haishan312 can you try with latest from llvm upstream?

HShan886 commented 2 years ago

Latest code works ok

ayermolo commented 2 years ago

ok, closing