使用 dbx 调试程序

此部分包含有关如何使用 dbx 调试程序的信息。

启动 dbx 调试程序

可使用各种标记启动 dbx 程序。 使用 dbx 程序启动调试会话的最为常见的 3 种方法是:

  • 对指定的对象文件运行 dbx 命令
  • 使用 -r 标志在异常结束的程序上运行 dbx 命令
  • 使用 -a 标志在已在进行中的进程上运行 dbx 命令

启动 dbx 命令时,它检查用户当前目录和用户 $HOME 目录中的 .dbxinit 文件。 如果 .dbxinit 文件存在,那么其子命令在调试会话开始时运行。 如果主目录和当前目录中都有 .dbxinit 文件,那么都以该顺序加以读取。 由于当前目录 .dbxinit 文件是最后读取的,其子命令可取代主目录中的那些文件。

如果未指定对象文件,那么 dbx 程序请求将要检查的对象文件的名称。 缺省值为 a.out。 如果 core 文件存在于当前目录中或 CoreFile 参数已指定,那么 dbx 程序报告该程序发生故障的位置。 可能对核心映像中驻留的变量、寄存器和内存进行检查,直至开始执行对象文件。 那时 dbx 调试程序提示输入命令。

调试缺少从属模块的核心映像

AIX 5.3 开始,即使一个或多个从属模块无法访问,"dbx程序也能检查核心映像。 在初始化期间,为每个缺失从属模块显示通知消息。

在正常操作中, dbx 程序依赖于从属模块的符号表和文本部分中包含的信息。 由于缺少某些信息,因此缺少从属模块的 dbx 会话具有以下限制:
  • 用户尝试读取内存(驻留在缺失从属模块的文本部分中)的内容将导致错误消息。 该错误消息类似于由于数据未驻留在核心文件中因而无法对其进行访问时出现的错误。
  • 用户无法获取涉及本应从缺失从属模块的符号表读取的任何符号的信息。 dbx 程序的行为类似于除去从属模块的符号表的情况。
  • 与缺失从属模块内的例程对应的堆栈帧显示为:
    .()
    此外,还将显示未知例程中的指令地址以及对应缺失从属模块的名称。

用户始终可以选择使用 -p 标志将 dbx 程序定向到可访问的从属模块。

调试从属模块不匹配的核心映像

AIX 5.3开始, dbx 程序会检测核心文件中引用的任何从属模块是否与核心文件创建时的从属模块不同。 在初始化期间,为每个不匹配的从属模块显示通知消息。

用户应该知道, dbx 程序根据不匹配的从属模块的内容显示的任何信息都可能不可靠。 为了提醒用户不应该信任的信息,只要显示有问题的信息, dbx 程序就会发送通知消息。

要禁用此功能并强制 dbx 程序将不匹配的从属模块视为缺失的从属模块,用户可以导出值为 DISCARD 的 DBX_MISMATCH_MODULE 环境变量。 导出此变量后, dbx 程序仍会通知用户不匹配,但继续操作,就像不匹配的从属模块不可访问一样。

用户始终可以选择使用 -p 标志将 dbx 程序定向到匹配的从属模块。

从 dbx 运行 shell 命令

可以使用 sh 子命令在不退出调试程序的情况下运行 shell 命令。

如果未指定任何命令便输入了 sh,那么输入 shell 以供使用直至退出它,此时时间控制权返回到 dbx 程序。

在 dbx 中进行命令行编辑

dbx 命令提供了命令行编辑功能,这些功能与 Korn Shell 程序提供的功能相似。 vi 方式提供类似于 vi 的编辑功能,而 emacs 方式赋予您类似于 emacs 的控制权。

您可以使用dbx子命令 set-oset edit 打开这些功能。 因此,要开启 vi样式的命令行编辑,请输入子命令set edit viset -o vi.

您也可以使用 EDITOR 环境变量来设置编辑方式。

dbx 命令将输入的命令保存到历史记录文件 .dbxhistory 中。 如果没有设置 DBXHISTFILE 环境变量,那么使用的历史记录文件就是 $HOME/.dbxhistory

在缺省情况下,dbx 命令保存最后输入的 128 个命令的文本。 DBXHISTSIZE 环境变量可以从来增加该限制。

使用程序控制

dbx 调试程序允许在程序中设置断点(停止位置)。 输入 dbx 程序后,可指定那些行或地址将设为断点,然后运行想要使用 dbx 程序调试的程序。 当程序到达断点时将停止并报告。 然后,可以使用 dbx 命令检查程序的状态。

设置断点的另一种方法就是一次运行程序的一行或一个指令,此过程称为单步执行。

设置和删除断点

使用 stop 子命令在 dbx 程序中设置断点。 当满足特定条件时,stop 子命令将停止应用程序:

  • 指定 Variable 参数将更改 Variable
  • 当使用 if Condition 标志时, Condition 为 true。
  • 当使用 程序 标志时,将调用 程序
  • 当使用 at SourceLine 标志时,将达到 SourceLine 行号。

    注意:可将 SourceLine 变量指定为整数或后跟一个 :(冒号)和一个整数的文件名字符串。

执行完这些命令,dbx 程序以报告与断点以及命令解释相关联的事件标识的消息来进行响应。 可以使用 addcmd 子命令将 dbx 子命令与指定的事件标识相关联。 在运行到与该事件对应的断点、跟踪点或观察点时,将发出这些关联的 dbx 子命令。 使用 delcmd 子命令从指定的事件标识中删除关联的 dbx 子命令。

运行程序

run 子命令启动程序。 它告诉 dbx 程序开始运行对象文件、读取任何参数,就好像它们被输入到 shell 命令行上。 rerun 子命令的格式与 run相同; 不同的是,如果未传递任何自变量,那么将使用先前执行中的自变量列表。 程序开始后,它一直继续运行,直至发生以下事件之一:

  • 程序到达断点。
  • 没有被忽略的信号出现,比如 INTERRUPTQUIT
  • 启用多进程调试时,出现多进程事件。
  • 程序执行 load卸载, 或 loadbind 子例程。

    注意:如果设置了 $ignoreload 变量,那么 dbx 程序忽略此情况。 这是缺省情况。 有关更多信息,请参阅 set 子命令。

  • 程序完成。

在每种情况下,dbx 调试程序接收控制权并显示说明程序停止原因的消息。

一旦程序停止,有一些方法能够使其继续:

命令 描述
连接 从程序停止处继续该程序。
拆离 从程序停止处继续该程序,退出调试程序。 对该程序打了补丁后如果想不使用调试程序继续该程序,这种方法很有用。
返回 继续执行直至返回 Procedure,或直至当前过程返回(如果未指定 Procedure)。
跳过 继续执行直至程序结尾或 Number + 1 断点执行。
步骤 运行一行源行或指定 Number 行源行。
下一个 运行至下一源行,或运行指定 Number 行源行。

调试的常见方法就是一次执行程序的一行。 stepnext 子命令就是为了这一目而服务的。 仅当将要运行的下一源行涉及到调用子程序时,这两个命令之间的区别才比较明显。 在这种情况下,step 子命令在子程序中停止;next 子命令在调用后运行直至该子程序完成,然后停止在下一个指令处。

$stepignore 调试变量可用来修改 step 子命令的行为。

没有任何事件号与这些停止相关,因为没有任何永久事件与停止程序相关。

如果程序具有多个线程,那么它们在 contnextnextistep 子命令的执行期间都将正常运行。 这些命令在运行的线程(运行到断点就停止执行的线程)上执行,所以即使另一线程运行正在执行中的代码, contnextnextistep 操作也会继续,直到正在运行的线程也已执行该代码。

如果想让这些子命令仅执行正在运行的线程,可设置 dbx 调试程序变量 $hold_next;这将导致 dbx 调试程序在执行 contnextnextistep 子命令期间保留所有其他用户线程。

注意:如果使用此功能,请记住已被保留的线程将无法释放它所需的任何锁定,需要这些锁定之一的另一线程将死锁住程序。

使 dbx 输出与程序输出分离

screen 子命令用于面向屏幕的调试程序,比如文本编辑器或图形程序。 此子命令为 dbx 命令交互作用打开了 Xwindow。 程序继续在它发生的窗口中运作。 如果未使用 屏幕 ,那么 dbx 程序输出将与面向屏幕的程序输出混合。

跟踪执行

trace 子命令告诉 dbx 程序打印有关该程序运行时正在调试的程序的状态的信息。 trace 子命令能够根据 dbx 程序需要处理的工作量大幅度地减慢程序。 程序跟踪有 5 种形式:

  • 可单步执行程序,显示出执行的每个源行。 $stepignore 调试变量可用于修改 trace 子命令的行为。 请参阅 set 子命令以获取更多信息。
  • 可将源行的显示限制为指定过程活动时。 还可指定可选条件以控制跟踪信息的产生时间。
  • 可在每次调用或返回过程时都显示一条消息。
  • 可在程序到达该行时显示指定源行。
  • 可在程序到达指定源行时显示表达式的值。

删除跟踪事件等同于删除停止事件。 执行 trace 子命令时,相关事件标识将同事件的内部表示一起显示。