【问题标题】:How to use debug libraries on ubuntu如何在 ubuntu 上使用调试库
【发布时间】:2013-01-15 18:43:45
【问题描述】:

我目前的问题是 libwebkitgtk-3.0-0,但我想这个问题足够通用。

我的应用程序在 webkit 代码中的某处崩溃。我的假设是我们正在做一些愚蠢的事情,并想知道是什么。最简单的方法是设置断点或使用库的调试版本。

  1. 如何获得构建库的确切源代码?我在转储核心后得到堆栈跟踪,但行号 gdb 说与我在代码中看到的不匹配。换句话说,如果我安装 libwebkitgtk-3.0-0,我想获得它的确切源代码。

  2. 我已经安装了调试版的 webkit 库。这些调试版本是否具有与使用 --enable-debug 标志编译 webkit 相同的功能?调试版本的 webkit 启用基于 WEBKIT_DEBUG 环境变量的日志记录,但即使使用调试版本的库,我也无法获得相同的日志记录。

  3. 如何使用我设法编译的调试版本?我设法在我的机器上编译 webkit 并尝试摆弄加载路径等。无论我做什么,我的应用程序都不会获取新的共享库 - 我可以根据用户代理签名来判断。有一次,我设法拿起图书馆,但随后 SSL 停止工作。 GtkLauncher 确实会发生同样的 SSL 问题。所以我在某个地方犯了错误。

感谢指点。

【问题讨论】:

    标签: debugging ubuntu webkit gtk


    【解决方案1】:

    TL;DR:安装libwebkitgtk-3.0-0-dbg ,然后你就有必要的调试符号了。

    ##对于调试符号,您通常不必从源代码安装。

    如您所知,要为您自己构建的软件获取调试符号,您可以使用-g 运行 GCC。

    对于通过操作系统的包管理器(包括libwebkitgtk-3.0-0,这里)安装的软件,至少对于官方包,通常还有提供调试符号的包

    您实际上不需要对程序或库进行调试构建即可在gdb 中获取符号堆栈跟踪。 gdb 还支持在/usr/lib/debug 中提供“附加”调试符号的文件。

    根据您问题上的标签,您使用的是 Ubuntu。 在 Ubuntu 上,可以使用两种调试符号包:-dbg-dbgsym。位于/<strong><em>path</em></strong> 的程序或库在/usr/lib/debug/<strong><em>path</em></strong> 获取调试符号。

    ##-dbg

    这些包的命名通常与提供实际可执行文件或库文件的相应包不同。它们的名称通常类似于-dev 包(提供头文件)和-doc 包。 -dbg 包名称中的库版本编号有时比实际库包少,有时涵盖多个其他包中提供的二进制文件。

    例如libgtkmm-3.0-1对应的-dbg包为libgtkmm-3.0-dbg

    另一方面,有时-dbg 包的名称与其提供符号的包相同(-dbg 后缀除外)。例如,libwebkitgtk-3.0-0对应的-dbg包是libwebkitgtk-3.0-0-dbg 这就是你想要的。

    您可以在软件中心安装它或通过运行:

    sudo apt-get update && sudo apt-get install libwebkitgtk-3.0-0-dbg
    

    现在,当您调试链接到libwebkitgtk-3.0-0 提供的库的程序时,gdb 将自动从libwebkitgtk-3.0-0-dbg 提供的文件中加载符号。

    ##-dbgsym

    有时官方包提供的二进制可执行文件没有任何-dbg 包中提供的符号。发生这种情况时,通常可以安装-dbgsym 包。

    不同于-dbg 包,-dbgsym 包:

    • 几乎总是简单(并且可以预测)命名为<strong><em>X</em></strong>-dbgsym,其中X是提供程序或库本身的包。
    • 由特殊的软件源(存储库)提供,与提供相应程序/库包和-dbg 包的软件源不同。

    由于-dbgsym 软件包位于不同的存储库中,您必须启用这些存储库。他们的 DEB 线路是:

    deb http://ddebs.ubuntu.com YOUR_RELEASE main restricted universe multiverse
    deb http://ddebs.ubuntu.com YOUR_RELEASE-updates main restricted universe multiverse
    deb http://ddebs.ubuntu.com YOUR_RELEASE-security main restricted universe multiverse
    deb http://ddebs.ubuntu.com YOUR_RELEASE-proposed main restricted universe multiverse

    要启用它们,您可以运行以下命令(改编自 DebuggingProgramCrash "Contributors to the Ubuntu documentation wiki"section 2):

    echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse
    deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
    deb http://ddebs.ubuntu.com $(lsb_release -cs)-security main restricted universe multiverse
    deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse
    " | sudo tee -a /etc/apt/sources.list.d/ddebs.list
    sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 428D7C01
    sudo apt-get update

    如果您处于开发版本(alpha 或 beta),请省略 斜体 行。不过,如果您在稳定后继续使用该版本,请务必添加它们。

    这些命令做了三件事:

    1. 创建文件/etc/apt/sources.list.d/ddebs.list(其中包含 DEB 行)。
    2. 为这些存储库导入签名密钥。
    3. 更新系统信息,了解哪些软件包和版本可用于从何处安装。

    因此,如果您想使用-dbgsym 提供的符号而不是-dbg 提供的符号,则libwebkitgtk-3.0-0-dbgsym 包是(根据上面的简单命名约定)libwebkitgtk-3.0-0-dbgsym

    您可以将-dbg-dbgsym 软件包安装在同一系统上,但如果它们为任何相同文件提供符号,则不能。所以libwebkitgtk-3.0-0-dbglibwebkitgtk-3.0-0-dbgsym相互冲突;它们不能同时安装。

    ##使用符号

    在大多数类 Unix 操作系统上,调试器会自动查找已安装的符号。 Ubuntu 也不例外——在 Ubuntu 中,gdb 会自动在 /usr/lib/debug 中查找它们。所以你不需要做任何特别的事情。

    但是,如果您确实需要告诉 gdb 加载特定的调试符号文件,则可以使用 -s <em>file</em> 标志。详情请参阅the GNU manualgdb(1)

    【讨论】:

    • 这很有趣,但它有什么帮助呢?如果您还没有安装源代码,您仍然无法确切地看到导致问题的原因 - 除非您可以仅从调用堆栈中的函数名称推测它。
    • 不幸的是,这并不总是有效的。例如,libarchive13 既没有 -dbg 也没有 -dbgsym ....
    • 我认为尝试一段时间后这是不可能的,ubuntu 也不在乎。如果我们希望源代码单步进入 webkit 或 gtk 等 3rd 方库,我们是否都必须安装 gentoo 进行开发?
    • 我的脚本替换了一个断开的链接,但我不确定这个包现在在哪里。请考虑改进修复,或将其回滚:)
    【解决方案2】:

    1) 当我需要深入了解通过包安装的库时,我要做的第一件事就是从源代码安装它。我的意思是配置/制作/制作安装。我通常将源代码放在 /usr/local/src 中并将其安装在 /usr/local 中。在我看来,这是运行您拥有源代码的确切代码的最可靠方法。

    3)

    如何使用我设法编译的调试版本?

    这听起来像你做了我上面描述的事情。您需要做的是确保您的软件正在使用包含和链接目录,这些目录托管您的已编译、启用调试的库。这意味着确保设置了 -I/usr/local/include 和 -L /usr/local/lib 标志,并且它们位于 /usr/include 和 /usr/lib 之前。

    您可以通过从 ubuntu 安装中删除库的二进制版本来更加确定,确保您构建和安装的版本是硬盘上唯一存在的版本。通过这种方式,您将确定您能够配置您的应用程序以使用该库。否则它只会失败,而不是你一直想知道它是使用新库还是旧库。

    2) 通常是的。但这取决于库是如何编写的,以及 ubuntu 打包器决定做什么。

    使用本地构建的库编译程序后,请先查看是否遇到相同的错误。如果不是,那么这也是一个数据点。自从上次 ubuntu 打包库以来,问题可能已经解决了。也许库没有正确打包,这就是问题所在。你甚至可能会得到新的错误,因为 ubuntu 打包程序以某种方式配置了库,以便它可以工作,而你没有做同样的事情。无论如何,你都会得到有趣的线索。

    祝你好运

    【讨论】:

      【解决方案3】:

      @Eliah 的回答告诉我们如何以一种方便的方式获取符号。

      问题仍然存在,“我如何获得确切的源代码?”

      我通常会使用apt-get source &lt;pkgname&gt;,这很好,但我必须手动告诉 gdb dir &lt;path-to-wherever-I-put-the-source&gt;,如果它是像 eglibc 这样的包,必须弄清楚路径引用来自nss 子目录,而不是根目录。

      在 RHEL 上,一个简单的操作,例如yum install --enable-repo rhel-debuginfo libX11-debuginfo(在 CentOS 7 上只是 yum install libX11-debuginfo),您可以立即在 gdb 中获得完整的符号和源代码,而无需额外的混乱。我仍在寻找 Ubuntu 上的便利性。

      【讨论】:

      • 这里是kdbg中的操作方法:设置->此程序->调试器:gdb --fullname --nx --directory (relative_path_to_library_source) -- 见here
      【解决方案4】:

      为了针对动态库进行调试,您可以按照建议添加带有符号和源发行包的 dgb 齿轮。 然后需要检查调试符号表的编译目录是否与安装源的路径匹配,如果不是,则应在gdb中映射路径。按照命令启用 glibc 的调试

      $ objdump -g /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.27.so | sed -n '/<.*>\s\+DW_AT_comp_dir/ {s/\s\+<.*>\s\+//; p;}' | sort | uniq
      DW_AT_comp_dir : (indirect string, offset: 0x1127a): /build/glibc-OTsEL5/glibc-2.27/malloc
      ...
      DW_AT_comp_dir : (indirect string, offset: 0xd139): /build/glibc-OTsEL5/glibc-2.27/stdio-common
      DW_AT_comp_dir : (indirect string, offset: 0xef40): /build/glibc-OTsEL5/glibc-2.27/libio
      $ ls -ld glibc-2.27/{stdio-common,libio}
      drwxrwxr-x 3 fusillator fusillator 12288 feb 1 2018 glibc-2.27/libio
      drwxrwxr-x 3 fusillator fusillator 4096 feb 1 2018 glibc-2.27/stdio-common
      $ gdb ./hello
      Reading symbols from ./hello...done.
      (gdb) set substitute-path /build/glibc-OTsEL5/glibc-2.27 glibc-2.27
      (gdb) b main
      Breakpoint 1 at 0x63e: file hello.c, line 10.
      (gdb) run
      Starting program: hello
      Breakpoint 1, main () at hello.c:10
      10 printf("hello world\n");
      (gdb) s
      _IO_puts (str=0x5555555546e4 "hello world") at ioputs.c:33
      33 {
      (gdb) backtrace
      #0 _IO_puts (str=0x5555555546e4 "hello world") at ioputs.c:33
      #1 0x000055555555464a in main () at hello.c:10
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-12
        • 2012-09-23
        • 1970-01-01
        • 1970-01-01
        • 2018-03-18
        • 2010-12-09
        • 1970-01-01
        • 2022-11-24
        相关资源
        最近更新 更多