分类

查看动态库的依赖关系树

2021-12-27 11:07 linux

今天调试一个内存泄露的问题, 表现是在 amd64 的机器上进程正常退出, 而 arm64 上会出现 指针错误.

$ ./lithium https://bing.com
[1223/105725.272479:INFO:command_line_ipc_client.cpp(58)] args item: ./lithium
[1223/105725.272716:INFO:command_line_ipc_client.cpp(58)] args item: --disable-gpu
[1223/105725.272742:INFO:command_line_ipc_client.cpp(58)] args item: --enable-print-preview
[1223/105725.272787:INFO:command_line_ipc_client.cpp(58)] args item: https://bing.com
[1223/105725.272809:INFO:command_line_ipc_client.cpp(58)] args item:
Found existing runtime, exit now!
*** Error in `./lithium': free(): invalid pointer: 0x00000000402c2f30 ***

这里, 先用 gdb 追踪了一下, 发现在 main() 函数退出后, 执行全局对象的 dtor() 时出了问题. 单步执行来追查, 发现是 protobuf 库在析构时挂了.

之后, 又使用 valgrind 来确认, 同样定位到了相同的问题点:

$ valgrind ./lithium https://bing.com
==2927== Memcheck, a memory error detector
==2927== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==2927== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==2927== Command: ./lithium https://bing.com
==2927== 
[1227/121246.927662:ERROR:shell.cpp(48)] --enable-print-preview switch is invalid
[1227/121247.102714:INFO:command_line_ipc_client.cpp(58)] args item: ./lithium
[1227/121247.106468:INFO:command_line_ipc_client.cpp(58)] args item: 
Found existing runtime, exit now!
==2927== Invalid read of size 4
==2927==    at 0x6A2928: void google::protobuf::internal::RepeatedPtrFieldBase::Destroy<google::protobuf::RepeatedPtrField<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::TypeHandler>() [clone .isra.78] (repeated_field.h:868)
==2927==    by 0x6A29BB: ~RepeatedPtrField (repeated_field.h:1090)
==2927==    by 0x6A29BB: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1650)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f7745c is 12 bytes inside a block of size 24 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2964: void google::protobuf::internal::RepeatedPtrFieldBase::Destroy<google::protobuf::RepeatedPtrField<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::TypeHandler>() [clone .isra.78] (repeated_field.h:871)
==2927==    by 0x6A29BB: ~RepeatedPtrField (repeated_field.h:1090)
==2927==    by 0x6A29BB: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1650)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f77450 is 0 bytes inside a block of size 24 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid free() / delete / delete[] / realloc()
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Address 0x12f77450 is 0 bytes inside a block of size 24 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 4
==2927==    at 0x6A29D0: Destroy<google::protobuf::RepeatedPtrField<google::protobuf::MessageLite*>::TypeHandler> (repeated_field.h:868)
==2927==    by 0x6A29D0: ~RepeatedPtrField (repeated_field.h:1090)
==2927==    by 0x6A29D0: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1651)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f774bc is 12 bytes inside a block of size 24 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2A04: Destroy<google::protobuf::RepeatedPtrField<google::protobuf::MessageLite*>::TypeHandler> (repeated_field.h:871)
==2927==    by 0x6A2A04: ~RepeatedPtrField (repeated_field.h:1090)
==2927==    by 0x6A2A04: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1651)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f774b0 is 0 bytes inside a block of size 24 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2A24: ~RepeatedField (repeated_field.h:614)
==2927==    by 0x6A2A24: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1652)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f77510 is 0 bytes inside a block of size 16 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2A44: ~RepeatedField (repeated_field.h:614)
==2927==    by 0x6A2A44: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1653)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f77560 is 0 bytes inside a block of size 16 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2A64: ~RepeatedField (repeated_field.h:614)
==2927==    by 0x6A2A64: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1654)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f775b0 is 0 bytes inside a block of size 16 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2A84: ~RepeatedField (repeated_field.h:614)
==2927==    by 0x6A2A84: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1655)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f77600 is 0 bytes inside a block of size 16 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2AA4: ~RepeatedField (repeated_field.h:614)
==2927==    by 0x6A2AA4: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1656)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f77650 is 0 bytes inside a block of size 16 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2AC4: ~RepeatedField (repeated_field.h:614)
==2927==    by 0x6A2AC4: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1657)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f776a0 is 0 bytes inside a block of size 16 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== Invalid read of size 8
==2927==    at 0x6A2AE4: ~RepeatedField (repeated_field.h:614)
==2927==    by 0x6A2AE4: google::protobuf::internal::DestroyDefaultRepeatedFields() (extension_set.cc:1658)
==2927==    by 0x635A63: google::protobuf::ShutdownProtobufLibrary() (common.cc:378)
==2927==    by 0x128E653B: ??? (in /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3)
==2927==    by 0x400E1AF: _dl_fini (dl-fini.c:235)
==2927==    by 0x11650F97: __run_exit_handlers (exit.c:82)
==2927==    by 0x11650FBF: exit (exit.c:104)
==2927==    by 0x480E3B: lnks::RunMain(int, char**) (shell.cpp:65)
==2927==    by 0x4A5ED7: main (lithium_frontend_linux.cpp:9)
==2927==  Address 0x12f776f0 is 0 bytes inside a block of size 16 free'd
==2927==    at 0x4846324: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927==  Block was alloc'd at
==2927==    at 0x4845108: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so)
==2927== 
==2927== 
==2927== HEAP SUMMARY:
==2927==     in use at exit: 116,478 bytes in 254 blocks
==2927==   total heap usage: 2,631 allocs, 2,386 frees, 306,596 bytes allocated
==2927== 
==2927== LEAK SUMMARY:
==2927==    definitely lost: 160 bytes in 9 blocks
==2927==    indirectly lost: 0 bytes in 0 blocks
==2927==      possibly lost: 1,888 bytes in 24 blocks
==2927==    still reachable: 114,430 bytes in 221 blocks
==2927==                       of which reachable via heuristic:
==2927==                         newarray           : 1,536 bytes in 16 blocks
==2927==                         multipleinheritance: 48 bytes in 1 blocks
==2927==         suppressed: 0 bytes in 0 blocks
==2927== Rerun with --leak-check=full to see details of leaked memory
==2927== 
==2927== For counts of detected and suppressed errors, rerun with: -v
==2927== ERROR SUMMARY: 20 errors from 12 contexts (suppressed: 0 from 0)

可是, 这里的一条报错记录很奇怪.

尽管项目中使用了 protobuf 库, 可是是静态链接上的, 并没有使用系统中的 protobuf. 使用 ldd 命令查看一下可执行文件, 发现它确实有动态链接到系统中的 protobuf.

为了排除问题, 给项目的 cmake 加一个目标, 用于显示项目依赖关系图:

add_custom_target(generate_deps
    COMMAND mkdir -pv ${CMAKE_BINARY_DIR}/deps
    COMMAND cmake --graphviz=deps/deps.dot ..
    COMMAND dot -Tsvg -o deps/deps.svg deps/deps.dot
    COMMAND setsid xdg-open deps/deps.svg
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
    )

最终输出的依赖关系图如下: deps.svg

可以看到, 项目本身并没有依赖系统的 protobuf 库, 但依赖了系统中的基础图形库. 那有可能就是间接依赖了.

接下来使用 lddtree 工具打印动态库的树形依赖关系:

lithium => ./lithium (interpreter => /lib/ld-linux-aarch64.so.1)
    libX11.so.6 => /usr/lib/aarch64-linux-gnu/libX11.so.6
        libxcb.so.1 => /usr/lib/aarch64-linux-gnu/libxcb.so.1
            libXau.so.6 => /usr/lib/aarch64-linux-gnu/libXau.so.6
            libXdmcp.so.6 => /usr/lib/aarch64-linux-gnu/libXdmcp.so.6
        libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2
    libcef.so => ./libcef.so
        libnss3.so => /usr/lib/aarch64-linux-gnu/libnss3.so
            libplc4.so => /usr/lib/aarch64-linux-gnu/libplc4.so
            libplds4.so => /usr/lib/aarch64-linux-gnu/libplds4.so
        libnssutil3.so => /usr/lib/aarch64-linux-gnu/libnssutil3.so
        libsmime3.so => /usr/lib/aarch64-linux-gnu/libsmime3.so
        libnspr4.so => /usr/lib/aarch64-linux-gnu/libnspr4.so
        libatk-1.0.so.0 => /usr/lib/aarch64-linux-gnu/libatk-1.0.so.0
        libatk-bridge-2.0.so.0 => /usr/lib/aarch64-linux-gnu/libatk-bridge-2.0.so.0
        libexpat.so.1 => /lib/aarch64-linux-gnu/libexpat.so.1
        libgio-2.0.so.0 => /usr/lib/aarch64-linux-gnu/libgio-2.0.so.0
            libgmodule-2.0.so.0 => /usr/lib/aarch64-linux-gnu/libgmodule-2.0.so.0
            libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1
            libselinux.so.1 => /lib/aarch64-linux-gnu/libselinux.so.1
                libpcre.so.3 => /lib/aarch64-linux-gnu/libpcre.so.3
                libsecurity.so.0 => /lib/aarch64-linux-gnu/libsecurity.so.0
            libresolv.so.2 => /lib/aarch64-linux-gnu/libresolv.so.2
        libxkbcommon.so.0 => /usr/lib/aarch64-linux-gnu/libxkbcommon.so.0
        libdbus-1.so.3 => /lib/aarch64-linux-gnu/libdbus-1.so.3
            libsystemd.so.0 => /lib/aarch64-linux-gnu/libsystemd.so.0
                librt.so.1 => /lib/aarch64-linux-gnu/librt.so.1
                liblzma.so.5 => /lib/aarch64-linux-gnu/liblzma.so.5
                libgcrypt.so.20 => /lib/aarch64-linux-gnu/libgcrypt.so.20
                    libgpg-error.so.0 => /lib/aarch64-linux-gnu/libgpg-error.so.0
        libXcomposite.so.1 => /usr/lib/aarch64-linux-gnu/libXcomposite.so.1
        libXdamage.so.1 => /usr/lib/aarch64-linux-gnu/libXdamage.so.1
        libXfixes.so.3 => /usr/lib/aarch64-linux-gnu/libXfixes.so.3
        libXrandr.so.2 => /usr/lib/aarch64-linux-gnu/libXrandr.so.2
            libXrender.so.1 => /usr/lib/aarch64-linux-gnu/libXrender.so.1
        libXtst.so.6 => /usr/lib/aarch64-linux-gnu/libXtst.so.6
        libgbm.so.1 => /usr/lib/aarch64-linux-gnu/libgbm.so.1
            libwayland-server.so.0 => /usr/lib/aarch64-linux-gnu/libwayland-server.so.0
                libffi.so.6 => /usr/lib/aarch64-linux-gnu/libffi.so.6
            libdrm.so.2 => /usr/lib/aarch64-linux-gnu/libdrm.so.2
        libpango-1.0.so.0 => /usr/lib/aarch64-linux-gnu/libpango-1.0.so.0
            libthai.so.0 => /usr/lib/aarch64-linux-gnu/libthai.so.0
                libdatrie.so.1 => /usr/lib/aarch64-linux-gnu/libdatrie.so.1
        libcairo.so.2 => /usr/lib/aarch64-linux-gnu/libcairo.so.2
            libpixman-1.so.0 => /usr/lib/aarch64-linux-gnu/libpixman-1.so.0
            libfontconfig.so.1 => /usr/lib/aarch64-linux-gnu/libfontconfig.so.1
            libfreetype.so.6 => /usr/lib/aarch64-linux-gnu/libfreetype.so.6
            libpng12.so.0 => /lib/aarch64-linux-gnu/libpng12.so.0
            libxcb-shm.so.0 => /usr/lib/aarch64-linux-gnu/libxcb-shm.so.0
            libxcb-render.so.0 => /usr/lib/aarch64-linux-gnu/libxcb-render.so.0
        libasound.so.2 => /usr/lib/aarch64-linux-gnu/libasound.so.2
        libcups.so.2 => /usr/lib/aarch64-linux-gnu/libcups.so.2
            libgssapi_krb5.so.2 => /usr/lib/aarch64-linux-gnu/libgssapi_krb5.so.2
                libkrb5.so.3 => /usr/lib/aarch64-linux-gnu/libkrb5.so.3
                    libkeyutils.so.1 => /lib/aarch64-linux-gnu/libkeyutils.so.1
                libk5crypto.so.3 => /usr/lib/aarch64-linux-gnu/libk5crypto.so.3
                libcom_err.so.2 => /lib/aarch64-linux-gnu/libcom_err.so.2
                libkrb5support.so.0 => /usr/lib/aarch64-linux-gnu/libkrb5support.so.0
            libgnutls.so.30 => /usr/lib/aarch64-linux-gnu/libgnutls.so.30
                libp11-kit.so.0 => /usr/lib/aarch64-linux-gnu/libp11-kit.so.0
                libidn.so.11 => /usr/lib/aarch64-linux-gnu/libidn.so.11
                libtasn1.so.6 => /usr/lib/aarch64-linux-gnu/libtasn1.so.6
                libnettle.so.6 => /usr/lib/aarch64-linux-gnu/libnettle.so.6
                libhogweed.so.4 => /usr/lib/aarch64-linux-gnu/libhogweed.so.4
                libgmp.so.10 => /usr/lib/aarch64-linux-gnu/libgmp.so.10
            libavahi-common.so.3 => /usr/lib/aarch64-linux-gnu/libavahi-common.so.3
            libavahi-client.so.3 => /usr/lib/aarch64-linux-gnu/libavahi-client.so.3
        libatspi.so.0 => /usr/lib/aarch64-linux-gnu/libatspi.so.0
        libxshmfence.so.1 => /usr/lib/aarch64-linux-gnu/libxshmfence.so.1
    libgtk-3.so.0 => /usr/lib/aarch64-linux-gnu/libgtk-3.so.0
        libpangocairo-1.0.so.0 => /usr/lib/aarch64-linux-gnu/libpangocairo-1.0.so.0
        libXi.so.6 => /usr/lib/aarch64-linux-gnu/libXi.so.6
        libcairo-gobject.so.2 => /usr/lib/aarch64-linux-gnu/libcairo-gobject.so.2
        libepoxy.so.0 => /usr/lib/aarch64-linux-gnu/libepoxy.so.0
        libpangoft2-1.0.so.0 => /usr/lib/aarch64-linux-gnu/libpangoft2-1.0.so.0
            libharfbuzz.so.0 => /usr/lib/aarch64-linux-gnu/libharfbuzz.so.0
                libgraphite2.so.3 => /usr/lib/aarch64-linux-gnu/libgraphite2.so.3
    libgdk-3.so.0 => /usr/lib/aarch64-linux-gnu/libgdk-3.so.0
        libXinerama.so.1 => /usr/lib/aarch64-linux-gnu/libXinerama.so.1
        libXcursor.so.1 => /usr/lib/aarch64-linux-gnu/libXcursor.so.1
        libwayland-cursor.so.0 => /usr/lib/aarch64-linux-gnu/libwayland-cursor.so.0
        libwayland-egl.so.1 => /usr/lib/aarch64-linux-gnu/libwayland-egl.so.1
        libwayland-client.so.0 => /usr/lib/aarch64-linux-gnu/libwayland-client.so.0
        libmirclient.so.9 => /usr/lib/aarch64-linux-gnu/libmirclient.so.9
            libmircommon.so.7 => /usr/lib/aarch64-linux-gnu/libmircommon.so.7
                libboost_filesystem.so.1.58.0 => /usr/lib/aarch64-linux-gnu/libboost_filesystem.so.1.58.0
            libmirprotobuf.so.3 => /usr/lib/aarch64-linux-gnu/libmirprotobuf.so.3
            libcapnp-0.5.3.so => /usr/lib/aarch64-linux-gnu/libcapnp-0.5.3.so
                libkj-0.5.3.so => /usr/lib/aarch64-linux-gnu/libkj-0.5.3.so
            libmircore.so.1 => /usr/lib/aarch64-linux-gnu/libmircore.so.1
            libboost_system.so.1.58.0 => /usr/lib/aarch64-linux-gnu/libboost_system.so.1.58.0
            libprotobuf-lite.so.9 => /usr/lib/aarch64-linux-gnu/libprotobuf-lite.so.9
    libgdk_pixbuf-2.0.so.0 => /usr/lib/aarch64-linux-gnu/libgdk_pixbuf-2.0.so.0
    libgobject-2.0.so.0 => /usr/lib/aarch64-linux-gnu/libgobject-2.0.so.0
    libglib-2.0.so.0 => /lib/aarch64-linux-gnu/libglib-2.0.so.0
    libXext.so.6 => /usr/lib/aarch64-linux-gnu/libXext.so.6
    libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6
    libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6
    libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1
    libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0
    libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6
    ld-linux-aarch64.so.1 => /lib/ld-linux-aarch64.so.1

lddtree 命令由 pax-utils 软件包提供, 可以在应用仓库中直接安装.

可以明显地看到, libgdk-3.so.0 会依赖 libmirclient.so.9, 后者又链接到了 protobuf.

之后会更新一下解决该系统库问题的方法.