llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.12k stars 12.01k forks source link

llvm-symbolizer does not handle .gnu_debugaltlink on s390x #46881

Open llvmbot opened 4 years ago

llvmbot commented 4 years ago
Bugzilla Link 47537
Version trunk
OS Linux
Reporter LLVM Bugzilla Contributor
CC @dwblaikie,@JDevlieghere,@walkerkd,@pogo59

Extended Description

I noticed that llvm-symbolizer fails to fully symbolize python3-related backtraces on s390x Fedora 31. I tracked this down to lack of .gnu_debugaltlink support, so I'm fairly confident the problem occurs on other architectures as well.

For example:

$ llvm-project/build/bin/llvm-symbolizer -e /usr/lib64/libpython3.7m.so.1.0 0x3fffcf998c3 --adjust-vma 0x3fffcf00000 ?? /usr/src/debug/python3-3.7.4-5.fc31.s390x/Objects/obmalloc.c:1585:11 ?? /usr/src/debug/python3-3.7.4-5.fc31.s390x/Objects/obmalloc.c:1577:1

Surprisingly, llvm-symbolizer shows the correct source code lines, but no function names.

If we extract relevant DIE offsets with the debugger and dig into libpython3 debuginfo, we'll see:

<1><25eac>: Abbrev Number: 40 (DW_TAG_subprogram) <25ead> DW_AT_abstract_origin: <25eb1> DW_AT_low_pc : 0x99850 <25eb9> DW_AT_high_pc : 148 <25ebb> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <25ebd> DW_AT_GNU_all_call_sites: 1 <25ebd> DW_AT_sibling : <0x25f58> DW_AT_abstract_origin points to , so the target DIE is in a file pointed to by .gnu_debugaltlink. As far as I understand, dwz produces these when deduplicating debuginfo. And indeed: Contents of section .gnu_debugaltlink: 0000 2e2e2f2e 2e2f2e64 777a2f70 7974686f ../../.dwz/pytho 0010 6e332d33 2e372e34 2d352e66 6333312e n3-3.7.4-5.fc31. 0020 73333930 7800467e 07ea9a25 a5feb0ca s390x.F~...%.... 0030 82f3ed5f 3ebb73aa 698e ..._>.s.i. If we look into /usr/lib/debug/usr/lib64/libpython3.7m.so.1.0-3.7.4-5.fc31.s390x.debug, we'll find: <1><10f7a>: Abbrev Number: 26 (DW_TAG_subprogram) <10f7b> DW_AT_name : (indirect string, offset: 0x19edc): _PyObject_Malloc <10f7f> DW_AT_decl_file : 200 <10f80> DW_AT_decl_line : 1577 <10f82> DW_AT_decl_column : 1 <10f83> DW_AT_prototyped : 1 <10f83> DW_AT_type : <0x52df7> <10f87> DW_AT_sibling : <0x10fb1> _PyObject_Malloc is exactly the missing function name. It would be great if .gnu_debugaltlink support could be added to llvm-symbolizer. I see that lldb already has it.
llvmbot commented 4 years ago

I've taken a quick look at the code, and it looks as if here:

Optional DWARFFormValue::getAsRelativeReference() const { if (!isFormClass(FC_Reference)) return None; switch (Form) { case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: if (!U) return None; return UnitOffset{const_cast<DWARFUnit*>(U), Value.uval}; case DW_FORM_ref_addr: case DW_FORM_ref_sig8: case DW_FORM_GNU_ref_alt: return UnitOffset{nullptr, Value.uval}; default: return None; } }

the DW_FORM_GNU_ref_alt case should return DWARFUnit, which refers to (a portion of) a file referenced by .gnu_debugaltlink, but instead it returns just nullptr.

llvmbot commented 4 years ago

I just checked, and the problem also exists on x86_64 F31:

$ readelf --debug-dump=info /usr/lib/debug/lib64/libpython3.7m.so.1.0-3.7.9-1.fc31.x86_64.debug

<1><9a93>: Abbrev Number: 45 (DW_TAG_subprogram) <9a94> DW_AT_abstract_origin: <9a98> DW_AT_low_pc : 0x68460 <9aa0> DW_AT_high_pc : 273 <9aa2> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <9aa4> DW_AT_GNU_all_call_sites: 1 <9aa4> DW_AT_sibling : <0x9c73> $ llvm-symbolizer --obj=/usr/lib64/libpython3.7m.so 0x68460 ?? /usr/src/debug/python3-3.7.9-1.fc31.x86_64/Parser/listnode.c:31:8 28 static void 29 list1node(FILE *fp, node *n) 30 { 31 if (n == NULL) 32 return; $ objdump -s -j .gnu_debugaltlink /usr/lib/debug/lib64/libpython3.7m.so.1.0-3.7.9-1.fc31.x86_64.debug /usr/lib/debug/lib64/libpython3.7m.so.1.0-3.7.9-1.fc31.x86_64.debug: file format elf64-x86-64 Contents of section .gnu_debugaltlink: 0000 2e2e2f2e 2e2f2e64 777a2f70 7974686f ../../.dwz/pytho 0010 6e332d33 2e372e39 2d312e66 6333312e n3-3.7.9-1.fc31. 0020 7838365f 36340061 f7f8f6df 7ab0d718 x86_64.a....z... 0030 8d1f74dd 437a4754 e0d84b ..t.CzGT..K $ readelf --debug-dump=info /usr/lib/debug/.dwz/python3-3.7.9-1.fc31.x86_64 <1>: Abbrev Number: 88 (DW_TAG_subprogram) DW_AT_name : (indirect string, offset: 0x23226): list1node DW_AT_decl_file : 154 DW_AT_decl_line : 29 DW_AT_decl_column : 1 DW_AT_prototyped : 1 DW_AT_sibling : <0xd4ba>
llvmbot commented 4 years ago

Hmm, actually the support is there since r237721. But it seems to be broken at least on s390x. I'll change the bug title to reflect this.