Index: lib/DebugInfo/DWARFDebugInfoEntry.cpp =================================================================== --- lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -20,6 +20,17 @@ using namespace dwarf; typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; +// Small helper to extract a DIE pointed by a reference +// attribute. It looks up the Unit containing the DIE and calls +// DIE.extractFast with the right unit. Returns new unit on success, +// nullptr otherwise. +static const DWARFUnit *findUnitAndExtractFast(DWARFDebugInfoEntryMinimal &DIE, + const DWARFUnit *Unit, + uint32_t *Offset) { + Unit = Unit->getUnitSection().getUnitForOffset(*Offset); + return Unit && DIE.extractFast(Unit, Offset) ? Unit : nullptr; +} + void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth, unsigned indent) const { @@ -315,8 +326,8 @@ getAttributeValueAsReference(U, DW_AT_specification, -1U); if (spec_ref != -1U) { DWARFDebugInfoEntryMinimal spec_die; - if (spec_die.extractFast(U, &spec_ref)) { - if (const char *name = spec_die.getSubroutineName(U, Kind)) + if (const DWARFUnit *RefU = findUnitAndExtractFast(spec_die, U, &spec_ref)) { + if (const char *name = spec_die.getSubroutineName(RefU, Kind)) return name; } } @@ -325,8 +336,9 @@ getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U); if (abs_origin_ref != -1U) { DWARFDebugInfoEntryMinimal abs_origin_die; - if (abs_origin_die.extractFast(U, &abs_origin_ref)) { - if (const char *name = abs_origin_die.getSubroutineName(U, Kind)) + if (const DWARFUnit *RefU = findUnitAndExtractFast(abs_origin_die, U, + &abs_origin_ref)) { + if (const char *name = abs_origin_die.getSubroutineName(RefU, Kind)) return name; } } Index: test/DebugInfo/Inputs/cross-cu-inlining.c =================================================================== --- /dev/null +++ test/DebugInfo/Inputs/cross-cu-inlining.c @@ -0,0 +1,18 @@ +// To generate the test file: +// clang cross-cu-inlining.c -DA_C -g -emit-llvm -S -o a.ll +// clang cross-cu-inlining.c -DB_C -g -emit-llvm -S -o b.ll +// llvm-link a.ll b.ll -o ab.bc +// opt -inline ab.bc -o cross-cu-inlining.bc +// clang -c cross-cu-inlining.bc -o cross-cu-inlining.o +#ifdef A_C +int i; +int func(int); +int main() { + return func(i); +} +#endif +#ifdef B_C +int __attribute__((always_inline)) func(int x) { + return x * 2; +} +#endif Index: test/DebugInfo/llvm-symbolizer.test =================================================================== --- test/DebugInfo/llvm-symbolizer.test +++ test/DebugInfo/llvm-symbolizer.test @@ -22,6 +22,7 @@ RUN: cp %p/Inputs/split-dwarf-test.dwo %T RUN: echo "%p/Inputs/split-dwarf-test 0x4004d0" >> %t.input RUN: echo "%p/Inputs/split-dwarf-test 0x4004c0" >> %t.input +RUN: echo "%p/Inputs/cross-cu-inlining.x86_64-macho.o 0x17" >> %t.input RUN: llvm-symbolizer --functions=linkage --inlining --demangle=false \ RUN: --default-arch=i386 < %t.input | FileCheck %s @@ -111,6 +112,13 @@ CHECK: _Z3fooi CHECK-NEXT: {{.*}}split-dwarf-test.cc +; func has been inlined into main by LTO. Check that the symbolizer is able +; to resolve the cross-cu reference and retrieve func's name +CHECK: func +CHECK-NEXT: /tmp{{[/\\]}}cross-cu-inlining.c:16:3 +CHECK-NEXT: main +CHECK-NEXT: /tmp{{[/\\]}}cross-cu-inlining.c:11:0 + RUN: echo "unexisting-file 0x1234" > %t.input2 RUN: llvm-symbolizer < %t.input2