调试信息存储在 Framework 中的什么位置?

Where Debug info stored in Framework?

如标题所述,我对 .Framework 文件中存储调试信息的位置感到困惑。

我用谷歌搜索了几天,得到的是:

Framework binary compiled by debug mode will include a debug info segment, to indicate the symbol location. Release mode compiling will move it to a dSYM file.

但是,让我感到困惑的是,我用 ninja 构建了一个框架,它不会生成 dSYM 文件。同时我无法通过 dwarfdump 命令或 MachOView 应用程序找到符号位置。作为问候 strings 命令可以获得一些相对文件路径结果,如 ../../flutter/fml/memory/task_runner_checker.cc.

这里 dwarfdump 打印:

Flutter.framework/Flutter:      file format Mach-O arm64

.debug_info contents:

这是我的问题:

  1. 当我在框架的某处触发断点时,源代码仍然显示。为什么?

  2. 当我运行 lldb 命令时,它显示:

(lldb) image lookup -a $pc --verbose
      Address: Flutter[0x0000000001964f18] (Flutter.__TEXT.__text + 26604184)
      Summary: Flutter`dart::BootstrapNatives::DN_LoadLibraryFromTypedData(dart::Thread*, dart::Zone*, dart::NativeArguments*) + 44 [inlined] dart::NativeArguments::NativeArgAt(int) const at object.cc:537
               Flutter`dart::BootstrapNatives::DN_LoadLibraryFromTypedData(dart::Thread*, dart::Zone*, dart::NativeArguments*) + 44 [inlined] dart::DN_HelperLoadLibraryFromTypedData(dart::Isolate*, dart::Thread*, dart::Zone*, dart::NativeArguments*) at object.cc:534
               Flutter`dart::BootstrapNatives::DN_LoadLibraryFromTypedData(dart::Thread*, dart::Zone*, dart::NativeArguments*) + 44 at object.cc:534
       Module: file = "/Users/xx/Library/Developer/Xcode/DerivedData/XXX-ddigzjlnuypwnydlawevfrkmdsov/Build/Products/Debug-iphoneos/XXX.app/Frameworks/Flutter.framework/Flutter", arch = "arm64"
  CompileUnit: id = {0x00000000}, file = "/Users/xx/Documents/workspace/aion/flutter_engine/src/third_party/dart/runtime/lib/object.cc", language = "c++14"
     Function: id = {0x7d40006244d}, name = "dart::BootstrapNatives::DN_LoadLibraryFromTypedData(dart::Thread*, dart::Zone*, dart::NativeArguments*)", mangled = "_ZN4dart16BootstrapNatives27DN_LoadLibraryFromTypedDataEPNS_6ThreadEPNS_4ZoneEPNS_15NativeArgumentsE", range = [0x0000000117310eec-0x0000000117311490)
     FuncType: id = {0x7d40006244d}, byte-size = 0, decl = bootstrap_natives.h:507, compiler_type = "class dart::ObjectPtr (class dart::Thread *, class dart::Zone *, class dart::NativeArguments *)"
       Blocks: id = {0x7d40006244d}, range = [0x117310eec-0x117311490)
               id = {0x7d40006249b}, ranges = [0x117310f18-0x1173113e0)[0x117311404-0x117311490), name = "DN_HelperLoadLibraryFromTypedData", decl = object.cc:534, mangled = _ZN4dartL33DN_HelperLoadLibraryFromTypedDataEPNS_7IsolateEPNS_6ThreadEPNS_4ZoneEPNS_15NativeArgumentsE, demangled = dart::DN_HelperLoadLibraryFromTypedData(dart::Isolate*, dart::Thread*, dart::Zone*, dart::NativeArguments*)
               id = {0x7d40006253a}, range = [0x117310f18-0x117310f24), name = "NativeArgAt", decl = native_arguments.h:129, mangled = _ZNK4dart15NativeArguments11NativeArgAtEi, demangled = dart::NativeArguments::NativeArgAt(int) const
    LineEntry: [0x0000000117310f18-0x0000000117310f24): /Users/xx/Documents/workspace/xxx/flutter_engine/src/third_party/dart/runtime/vm/native_arguments.h:132:14
       Symbol: id = {0x0013fd0f}, range = [0x0000000117310eec-0x0000000117311490), name="dart::BootstrapNatives::DN_LoadLibraryFromTypedData(dart::Thread*, dart::Zone*, dart::NativeArguments*)", mangled="_ZN4dart16BootstrapNatives27DN_LoadLibraryFromTypedDataEPNS_6ThreadEPNS_4ZoneEPNS_15NativeArgumentsE"
     Variable: id = {0x7d400062553}, name = "this", type = "const dart::NativeArguments *", location = DW_OP_reg20 W20, decl = 
     Variable: id = {0x7d40006255c}, name = "index", type = "int", location = <decoding error> 00 00 00, decl = native_arguments.h:129
     Variable: id = {0x7d4000624a8}, name = "isolate", type = "dart::Isolate *", location = , decl = object.cc:534
     Variable: id = {0x7d4000624ad}, name = "thread", type = "dart::Thread *", location = , decl = object.cc:534
     Variable: id = {0x7d4000624b2}, name = "zone", type = "dart::Zone *", location = DW_OP_reg19 W19, decl = object.cc:534
     Variable: id = {0x7d4000624bb}, name = "arguments", type = "dart::NativeArguments *", location = DW_OP_reg20 W20, decl = object.cc:534
     Variable: id = {0x7d4000624c4}, name = "program", type = "unique_ptr<dart::xx_kernel::Program, std::__1::default_delete<dart::xx_kernel::Program> >", location = DW_OP_breg31 WSP+64, decl = object.cc:556
     Variable: id = {0x7d400062468}, name = "thread", type = "dart::Thread *", location = DW_OP_reg24 W24, decl = object.cc:534
     Variable: id = {0x7d400062479}, name = "zone", type = "dart::Zone *", location = DW_OP_reg19 W19, decl = object.cc:534
     Variable: id = {0x7d40006248a}, name = "arguments", type = "dart::NativeArguments *", location = DW_OP_reg20 W20, decl = object.cc:534

那么,lldb 在哪里获得 Compile UnitLineEntry 输出?

Darwin 系统的调试信息存在于两个地方之一:在 .o 文件中,然后在 dsymutil 之后 运行 创建一个 .dSYM,它存在在 .dSYM 包中,全部收集在一起,重新定位到实际二进制文件的地址。

这是构建-link-调试性能增强。链接所有调试信息——更新所有符号地址,将其复制到周围——非常慢,因此将调试信息留在 .o 文件中以用于此常见的迭代开发周期,并让调试器找到.o 文件并在内部更新函数的地址,允许快速开发。

将所有调试信息留在 .o 文件中当然需要它们全部存在!并在相同的文件路径。因此,当您需要在计算机之间移动二进制文件或将其保存以供以后调试时,这并不好。对于这些情况,您 link 使用 dsymutil 调试信息并获得 .dSYM 包。