我有一个已部署到客户站点的C应用程序.它是在HP-UX上编译和运行的.用户已报告崩溃,我们已获得核心转储.到目前为止,我一直无法在内部复制崩溃.
正如您所怀疑的那样,核心文件/部署的可执行文件完全没有任何符号.当我在gdb中加载并执行bt时,我得到的最好的是:
(gdb) bt
#0 0xc0199470 in ?? ()
Run Code Online (Sandbox Code Playgroud)
我可以在文件上做一个'字符串核心',但我的理解是,所有我到达那里的是可执行文件中的所有字符串,所以在那里找到任何东西似乎是不可能的.
我确实有一个可执行文件的调试版本(用-g编译),不幸的是比发布版本新几个月.如果我尝试使用该集线器启动gdb,我会看到:
warning: exec file is newer than core file.
Core was generated by `program_name'.
Program terminated with signal 11, Segmentation fault.
__dld_list is not valid according to __dld_flags.
#0 0xc0199470 in ?? ()
(gdb) bt
#0 0xc0199470 in ?? ()
Run Code Online (Sandbox Code Playgroud)
虽然编译调试版本并将其部署在客户的站点然后等待另一次崩溃是可行的,但由于多种原因,这将是相对困难和不可取的.
我对代码非常熟悉,并且根据客户的错误报告,对代码崩溃的位置有了更好的了解.
有什么方法可以从这个核心转储中收集更多信息吗?通过字符串或其他调试器或任何东西?谢谢.
这种来自gdb的响应:
(gdb) bt
#0 0xc0199470 in ?? ()
Run Code Online (Sandbox Code Playgroud)
也可能发生在堆栈被缓冲区溢出破坏的情况下,其中返回地址被覆盖在内存中,因此程序计数器被设置为看似随机的区域.
这是即使使用相应的符号数据库构建也可能导致符号查找错误(或奇怪的回溯)的方法之一.如果您在获得符号表后仍然可以获得此信息,那么您的问题很可能是客户的数据导致代码出现问题.
为未来:
对于这种情况:
你知道一般区域,所以要看你是否正确,转到堆栈跟踪并找到汇编代码 - 看看它并看看你认为它是否与你的源匹配(如果你知道什么源生成这个,这会更容易部件).如果它看起来正确,那么您对您的假设进行了一些验证.您可以通过查看堆栈来找出局部变量的值(因为您知道传入并声明了什么).
在 gdb 下,“信息寄存器”应该为您提供崩溃时足够的执行状态,以便与可执行文件和相关共享库的反汇编一起使用。我通常使用 objdump 进行反汇编,将输出重定向到文件,然后在我最喜欢的编辑器中打开该文件 - 这对于在弄清楚事情时进行记录很有用。gdb 的“info target”和“info sharedlib”对于确定共享库的加载位置也很有用。
有了寄存器状态、堆栈内容和反汇编,再加上一点运气,重建调用堆栈应该很简单(如果很乏味的话)(当然,除非堆栈因缓冲区溢出或类似的灾难而被破坏......在这种情况下可能需要显灵板或水晶球。)
您还可以将使用 -g 构建的新版本的反汇编与剥离版本的反汇编相关联。