如果转储核心的程序与所有共享库动态链接,最好在创建核心转储文件的相同操作环境中调试核心转储文件。dbx 对调试“不匹配的”核心转储文件(例如,运行其他版本或修补程序级别的 Solaris 操作系统的系统上生成的核心转储文件)具有有限的支持。
注 - dbx 无法像对待本机代码那样通过核心转储文件来指明 Java 应用程序的状态。
要调试核心转储文件,键入:
$ dbx program_name core
或
$ dbxtool program_name core
如果键入以下命令,dbx 会通过核心转储文件确定 program_name。
$ dbx - core
或
$ dbxtool - core
如果 dbx 已在运行,也可以使用 debug 命令调试核心转储文件。
(dbx) debug -c core program_name
可以用 - 替换程序名,dbx 将尝试从核心转储文件中提取程序名。如果在核心转储文件中未提供可执行文件的全路径名,则 dbx 可能找不到可执行文件。如果 dbx 找不到可执行文件,请在指示 dbx 装入核心转储文件时指定二进制文件的完整路径名。
如果核心转储文件不在当前目录下,可指定它的路径名(例如,/tmp/core)。
使用 where 命令(请参见where 命令)确定程序在进行核心转储时的执行位置。
调试核心转储文件时,也可以求变量和表达式的值来查看程序崩溃时的值,但不能求调用函数的表达式的值。无法单步执行。可以设置断点,然后重新运行程序。
如果装入核心存储文件时存在问题,请检查是否有被截断的核心转储文件。如果在创建核心转储文件时将其最大允许大小设得太低,那么 dbx 将无法读取最终被截断的核心转储文件。在 C shell 中,可使用 limit 命令来设置允许的最大核心转储文件大小(请参见 limit(1) 手册页)。在 Bourne shell 和 Korn shell 中,应使用 ulimit 命令(请参见 limit(1) 手册页)。可以在 shell 启动文件中更改核心转储文件大小的限制,重新寻找启动文件,然后重新运行生成该核心转储文件的程序,以生成完整的核心转储文件。
如果核心转储文件不完整并且缺少栈段,则栈跟踪信息不可用。如果缺少运行时链接程序信息,则装入对象列表不可用。在这种情况下,您会收到 librtld_db.so 未初始化的错误消息。如果缺少 LWP 列表,则线程信息、lwp 信息或栈跟踪信息不可用。如果运行 where 命令,将看到一条错误消息,指出程序未处于“活动状态”。
有时核心转储文件在一个系统(核心主机)上创建,而您想在另一台机器(dbx 主机)上装入该核心转储文件。但这样做可能会引起两个与库有关的问题:
核心主机上的程序所使用的共享库与 dbx 主机上的共享库可能不相同。要获取该库相关的正确栈跟踪,需要在 dbx 主机上提供这些原始库。
dbx 使用 /usr/lib 中的系统库来帮助了解系统内有关运行时链接程序和线程库实现的详细信息。可能还需要通过核心主机提供这些系统库,以便 dbx 能够了解运行时链接程序数据结构和线程数据结构。
用户库和系统库可随着修补程序以及主要的 Solaris 操作环境升级而改变,因此如果在收集核心转储文件之后但在核心转储文件上运行 dbx 之前安装修补程序,此问题仍会出现在同一台主机上。
当装入“不匹配”的核心转储文件时,dbx 可能会显示以下一条或多条错误消息:
dbx: core file read error: address 0xff3dd1bc not available dbx: warning: could not initialize librtld_db.so.1 -- trying libDP_rtld_db.so dbx: cannot get thread info for 1 -- generic libthread_db.so error dbx: attempt to fetch registers failed - stack corrupted dbx: read of registers from (0xff363430) failed -- debugger service failed
例如,假定核心主机的根分区已通过 NFS 导出,并且可以通过 dbx 主机上的 /net/core-host/ 访问,应使用以下命令装入 prog 程序和 prog.core 核心转储文件来进行调试:
(dbx) dbxenv core_lo_pathmap on (dbx) pathmap /usr /net/core-host/usr (dbx) pathmap /appstuff /net/core-host/appstuff (dbx) debug prog prog.core
如果没有导出核心主机的根分区,则必须手动复制这些库。不需要重新创建符号链接。(例如,您不必建立从 libc.so 到 libc.so.1 的链接,只需确保 libc.so.1 可用即可)。
调试不匹配的核心转储文件时应注意:
pathmap 命令不能识别 "/" 路径映射,因此不能使用以下命令:
pathmap / /net/core-host
pathmap 命令的单参数模式不能与装入对象路径名同时使用,因此请使用双参数(来源路径和目标路径)模式。
如果 dbx 主机使用的 Solaris 操作环境版本与核心主机相同或比它更新,那么调试核心转储文件时效果可能会更好,虽然这并不总是必要。
可能需要的系统库是:
对于运行时链接程序:
/usr/lib/ld.so.1
/usr/lib/librtld_db.so.1
/usr/lib/64/ld.so.1
/usr/lib/64/librtld_db.so.1
对于线程库,取决于您所使用的 libthread 执行:
/usr/lib/libthread_db.so.1
/usr/lib/64/libthread_db.so.1
如果 dbx 在支持 64 位的 Solaris OS 版本上运行,您将需要 64 位版本的 xxx_db.so 库,因为这些系统库是作为 dbx 的一部分(而不是目标程序的一部分)装入和使用的。
与 libc.so 或任何其他库一样,ld.so.1 库是核心转储文件映像的一部分,因此需要与创建核心转储文件的程序相匹配的 32 位 ld.so.1 库或 64 位 ld.so.1 库。
如果正在查看来自某个线程程序的核心转储文件,并且 where 命令未显示栈,请尝试使用 lwp 命令。例如:
(dbx) where current thread: t@0 [1] 0x0(), at 0xffffffff (dbx) lwps o>l@1 signal SIGSEGV in _sigfillset() (dbx) lwp l@1 (dbx) where =>[1] _sigfillset(), line 2 in "lo.c" [2] _liblwp_init(0xff36291c, 0xff2f9740, ... [3] _init(0x0, 0xff3e2658, 0x1, ... ...
如果 LWP 的帧指针 (fp) 被破坏,则 lwp 命令的 -setfp 和 -resetfp 选项会很有用。这些选项在调试核心转储文件时使用,此时 assign $fp=... 不可用。
缺少线程栈表明 thread_db.so.1 有问题,因此,您可能还需要尝试从核心主机中复制适当的 libthread_db.so.1 库。