LLDB 是如何找到内联函数的?

How does LLDB find inlined functions?

通过指定符号名称设置断点时,lldb 不仅会解析该符号,还会找到内联使用该函数的位置。这怎么可能?

1: name = 'my_func', locations = 4, resolved = 1, hit count = 1
  1.1: where = kernel.development`my_func + 6 at task.c:17, address = 0xxxx, resolved, hit count = 0 
  1.2: where = kernel.development`func_foo + 119 [inlined] my_func at task.c:22, address = 0xxxx, unresolved, hit count = 0  Options: disabled 
  1.3: where = kernel.development`func_bar + 95 [inlined] my_func at task.c:65, address = 0xxxx, unresolved, hit count = 1  Options: disabled 

查看 LLDB 的源代码,我只能找到它检查某个块是否内联的位置://source/API/SBBlock.cpp

bool SBBlock::IsInlined() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, IsInlined);

  if (m_opaque_ptr)
    return m_opaque_ptr->GetInlinedFunctionInfo() != nullptr;
  return false;
}

split-dwarf-inlining.cpp confirms that DWARF 调试信息中的 LLDB 测试用例用于查找内联函数。

// RUN: %clangxx -target x86_64-pc-linux -gsplit-dwarf -fsplit-dwarf-inlining \
// RUN:   -c %s -o %t
// RUN: %lldb %t -o "breakpoint set -n foo" -b | FileCheck %s

// CHECK: Breakpoint 1: 2 locations

__attribute__((always_inline)) int foo(int x) { return x; }
int bar(int x) { return foo(x); }

如果您 运行 dwarfinfo 在可执行文件上它会显示“嵌套”内联方法,这就是它找到它的方式。

它实际找到它的地方:

获取区块: 获取包含框架 PC 的最深块。

https://github.com/llvm-mirror/lldb/blob/d01083a850f577b85501a0902b52fd0930de72c7/include/lldb/API/SBFrame.h#L60

我认为最深的块指的是“嵌套”的内联方法。

然后它可以在该“最低块”上调用 getInlinedParent 或 getParent 以生成输出。诸如此类...