Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 调试没有符号的核心文件_C_Gdb_Hp Ux - Fatal编程技术网

C 调试没有符号的核心文件

C 调试没有符号的核心文件,c,gdb,hp-ux,C,Gdb,Hp Ux,我有一个C应用程序,我们已经部署到客户站点。它是在HP-UX上编译和运行的。用户报告了一个崩溃,我们获得了一个内核转储。到目前为止,我还无法在房子里复制这次撞车事件 正如您所怀疑的,核心文件/部署的可执行文件完全没有任何类型的符号。当我在gdb中加载它并执行bt时,我得到的最好结果是: (gdb) bt #0 0xc0199470 in ?? () 我可以在文件上做一个“字符串核心”,但我的理解是,我得到的只是可执行文件中的所有字符串,因此似乎不可能在那里找到任何东西 我确实有一个调试版本(

我有一个C应用程序,我们已经部署到客户站点。它是在HP-UX上编译和运行的。用户报告了一个崩溃,我们获得了一个内核转储。到目前为止,我还无法在房子里复制这次撞车事件

正如您所怀疑的,核心文件/部署的可执行文件完全没有任何类型的符号。当我在gdb中加载它并执行bt时,我得到的最好结果是:

(gdb) bt
#0  0xc0199470 in ?? ()
我可以在文件上做一个“字符串核心”,但我的理解是,我得到的只是可执行文件中的所有字符串,因此似乎不可能在那里找到任何东西

我确实有一个调试版本(用-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 ?? ()
虽然编译调试版本并将其部署到客户站点,然后等待另一次崩溃是可行的,但由于许多原因,这将是相对困难和不可取的

我对代码非常熟悉,根据客户的bug报告,我对代码中的崩溃位置有一个比较好的了解


我有没有办法从这个核心转储中收集更多的信息?通过字符串或其他调试器或其他方式?谢谢。

您是否有编译旧版本的确切源代码(例如,通过源代码树中的标记或类似的方式)?也许您可以使用它进行重建,并可能了解崩溃发生的位置?

这里没有太多信息。二进制文件被剥离了。但是看看分段错误……你应该寻找有可能覆盖内存的地方

这只是一个建议。可能会有很多问题

顺便说一句,如果您无法在本地计算机上复制,那么客户计算机上的数据量可能是一个问题

未来:

  • 确保始终使用外部符号数据库进行构建(这不是调试构建——这是发布构建,但单独存储符号表)
  • 为您部署的版本保留它
  • 对于这种情况:


    您知道一般情况,因此要想知道您是否正确,请转到堆栈跟踪并找到汇编代码——仔细观察它,看看它是否与源代码匹配(如果您知道是什么源代码生成了这个程序集,这会更容易)。如果它看起来是正确的,那么你对你的假设有一些验证。您可以通过查看堆栈来计算局部变量的值(因为您知道传入和声明的内容)。

    这种类型的gdb响应:

    (gdb) bt
    #0  0xc0199470 in ?? ()
    
    在堆栈被缓冲区溢出破坏的情况下也会发生这种情况,返回地址在内存中被覆盖,因此程序计数器被设置为一个看似随机的区域

    这是一种方式,即使是具有相应符号数据库的构建也会导致符号查找错误(或奇怪的回溯)。如果在创建符号表后仍会出现这种情况,则问题可能是客户的数据导致代码出现了一些问题

  • 始终使用源代码管理(CVS/GIT/Subversion/etc),即使是测试版本也是如此
  • 标记所有发布
  • 考虑(将来)使用调试(-g)进行构建,并在发布之前剥离可执行文件。注意:不要使用和不使用-g进行两次构建;它们很可能不匹配,因为-g有时会导致在相同的优化级别生成不同的代码。在超性能关键代码中,对于关键文件,您可以放弃使用-g,但大多数情况下,它不会对您造成影响
  • 如果你真的被卡住了,转储堆栈,并将堆的相关部分转储到hex,然后手动查看;可能是获取一个插入指令的副本,并在生成的代码和堆栈中寻找类似的“签名”。这是真实的“老派”调试…:-) 在gdb下,“信息寄存器”应该为您提供足够的崩溃时的执行状态,以用于可执行文件和相关共享库的反汇编。我通常使用objdump进行反汇编,将输出重定向到一个文件,然后在我最喜欢的编辑器中调出该文件-这对于在解决问题时记录笔记非常有用。此外,gdb的“info目标”和“info sharedlib”对于确定共享库的加载位置也很有用

    有了寄存器状态、堆栈内容和反汇编,再加上一点运气,重建调用堆栈应该很简单(如果繁琐的话)(当然,除非堆栈被缓冲区溢出或类似灾难破坏了……在这种情况下,可能需要一块占卜板或水晶球)

    您还可以将使用-g构建的较新版本的反汇编与剥离版本的反汇编关联起来。

    尝试对核心文件运行“pmap”(如果hp/ux有此工具)。这应该报告核心文件中所有模块的起始地址。有了这些信息,您应该能够获取故障位置的地址,并找出哪个库崩溃了。进一步比较崩溃地址和库中已知函数的地址(“nm”与库中的“nm”应该得到该地址),可以帮助您确定哪个函数崩溃


    即使您设法在堆栈顶部识别函数,也不太可能该函数是问题的根源。。。希望它实际上已经在您的代码中崩溃了,而不是标准的C字符串库。在这一点上,重建堆栈跟踪是次好的选择。

    我认为核心文件不应该包含符号。您需要能够构建一个与交付给客户的程序完全相同的程序版本,但使用-g。如果剥离调试可执行文件,它应该与附带的版本相同。