检测二进制文件
通过检测目标二进制文件,会在关键位置添加代码,以便 discover 可以在二进制文件运行时跟踪内存操作。
注 -
对于 SPARC V8 体系结构上的 32 位二进制文件,discover 会在检测时插入 V8plus 代码。因此,无论二进制文件输入如何,输出二进制文件始终为 v8plus。
可使用 discover 命令检测二进制文件。例如,以下命令将检测二进制文件 a.out,并使用检测过的 a.out 来覆盖输入 a.out:
discover a.out
当运行检测过的二进制文件时,discover 会监视程序对内存的使用。在运行过程中,discover 会将详细说明任何内存访问错误的报告写入一个 HTML 文件,您可以在 Web 浏览器中查看该文件。缺省文件名为 a.out.html。要请求将报告写入 ASCII 文件或 stderr,请在检测二进制文件时使用 –w 选项。
当 discover 检测二进制文件时,如果发现任何由于未注释而导致其无法检测的代码,将显示与以下内容类似的警告:
discover: (warning): a.out: 80% of code instrumented (16 out of 20 functions)
无注释代码可能来自链接到二进制文件中的汇编语言代码,或者来自使用早于支持的二进制文件中所列版本的编译器或操作系统编译的模块。
高速缓存共享库
当 discover 检测二进制文件时,会向与运行时链接程序一起工作的二进制文件中添加代码,以便在运行时装入相关的共享库时对其进行检测。检测过的库存储在高速缓存中;如果原始库自上次检测以来未发生更改,可以重新使用这些库。缺省情况下,高速缓存目录为 $HOME/SUNW_Bit_Cache。可以使用 –D 选项更改该目录。
检测共享库
如果检测整个程序(包括所有共享库),discover 实用程序会生成最准确的结果。 缺省情况下,discover 仅检查并报告可执行文件中的内存错误。要指定您希望 discover 跳过对可执行文件中错误的检查,请使用 –n 选项。
可以使用 –c 选项指定希望 discover 检查相关共享库和通过 dlopen() 动态打开的库中的错误。还可以使用 –c 选项避免检查特定的库中的错误。 尽管 discover 不报告该库中的任何错误,但由于其需要跟踪整个地址空间的内存状态以正确检测内存错误,因此会记录整个程序(包括共享库)中的分配和内存初始化。
discover 实用程序运行时使用链接程序审计接口(也称为 rtld-audit 或 LD_AUDIT)从 discover 的高速缓存目录自动装入检测过的共享库。在 Oracle Solaris 上,缺省情况下使用审计接口。在 Linux 上,当运行检测过的二进制文件时,需要在命令行上设置 LD_AUDIT。
对于 Oracle Linux 上的 32 位应用程序:
% LD_AUDIT=install-dir/lib/compilers/bitdl.so a.out
对于 Oracle Linux 上的 64 位应用程序:
% LD_AUDIT=install-dir/lib/compilers/amd64/bitdl.so a.out
该机制可能不会在所有运行 Oracle Enterprise Linux 5.x 的环境中起作用。如果不需要库检测并且未设置 LD_AUDIT,则 discover 在 Oracle Enterprise Linux 5.x 上没有问题。
应根据检测二进制文件中的说明检测程序使用的所有共享库。缺省情况下,如果运行时链接程序遇到一个未检测的库,会发生致命错误。不过,您可以指示 discover 忽略一个或多个库。
忽略库
您可能无法检测某些库 。您可以使用 –T 或 –N 选项(请参见检测选项)或者 bit.rc 文件中的规范(请参见bit.rc 初始化文件)指示 discover 忽略这些库。可能会损失一些准确性。
缺省情况下,discover 使用 bit.rc 系统文件中的规范将系统和编译器提供的某些库设置为忽略,因为它们可能未添加注释。由于 discover 了解最常用库的内存特征,因此,对准确性的影响微乎其微。
检查库或可执行文件的部分
可以使用 –c 选项指定某个可执行文件或库。可以通过将内存访问检查限定至某些目标文件来进一步限定目标可执行文件或目标库。
例如,如果目标库为 libx.so 并且目标可执行文件为 a.out,则可使用以下命令:
$ discover -c libx.so -o a.out.disc a.out
还可以通过添加冒号分隔的文件或目录来限制对任何目标的检查。文件可以是 ELF 文件或目录。如果指定 ELF 文件,则会检查文件中定义的所有函数。如果指定目录,则会递归使用目录中的所有文件。
$ discover -o a.out.disc a.out:t1.0:dir
$ discover -c libx.so:l1.o:12.o -o a.out.disc a.out
命令行选项
您可以将以下选项与 discover 命令结合使用来检测二进制文件。
输出选项
–a
将错误数据写入 binary-name.analyze/dynamic 目录以供代码分析器使用。
–b browser
运行检测过的程序时会自动启动 Web 浏览器 browser(缺省情况下为 off)。
–e n
仅在报告中显示 n 个内存错误(缺省情况下显示所有错误)。
–E n
仅在报告中显示 n 个内存泄漏(缺省情况下显示 100 个)。
–f
在报告中显示偏移(缺省情况下隐藏偏移)。
–H html-file
将 discover 有关二进制文件的报告以 HTML 格式写入 html-file。此文件是在您运行检测过的二进制文件时创建的。如果 html-file 是相对路径名,则会相对于您在其中运行检测过的二进制文件的工作目录放置该文件。要使文件名在您每次运行二进制文件时都是唯一的,请将字符串 %p 添加到文件名中,以指示 discover 运行时包含进程 ID。例如,选项 –H report.%p.html 生成文件名为 report.process-ID.html 的报告文件。如果在文件名中多次包含 %p,则仅将第一个实例替换为进程 ID。
如果您未指定该选项或 –w 选项,则以 HTML 格式将报告写入 output-file.html,其中 output-file 是检测过的二进制文件的基名。该文件位于您运行检测过的二进制文件时所在的工作目录中。
您可以同时指定此选项和 –w 选项,同时以文本和 HTML 格式写入报告。
–m
在报告中显示改编名称(缺省为显示取消改编名称)。
–o file
将检测过的二进制文件写入 file。缺省情况下,检测过的二进制文件会覆盖输入二进制文件。
–S n
仅在报告中显示 n 个堆栈帧(缺省情况下显示 8 个)。
–w text-file
将 discover 有关二进制文件的报告写入 text-file。该文件是在您运行检测过的二进制文件时创建的。如果 text-file 是相对路径名,则会相对于您在其中运行检测过的二进制文件的工作目录放置该文件。要使文件名在您每次运行二进制文件时都是唯一的,请将字符串 %p 添加到文件名中,以指示 discover 运行时包含进程 ID。例如,选项 –w report.%p.txt 生成文件名为 report.process-ID.txt 的报告文件。如果在文件名中多次包含 %p,则仅将第一个实例替换为进程 ID。指定 –w - 将在 stderr 中输出。
如果您未指定该选项或 –H 选项,则以 HTML 格式将报告写入 output-file.html,其中 output-file 是检测过的二进制文件的基名。该文件位于您运行检测过的二进制文件时所在的工作目录中。
您可以同时指定此选项和 –H 选项,同时以文本和 HTML 格式写入报告。
注 -
使用 –w 和 –H 选项时,建议使用完整路径名。如果使用了相对路径,则会在相对于进程运行目录的目录中生成报告。因此,如果应用程序更改了目录并启动新的进程,报告可能会放在不正确的位置。应用程序派生新进程时,discover 在运行时会为子进程创建一个父错误报告副本,子进程继续向该副本写入。如果子进程的运行目录发生变化,且对报告文件使用了相对路径,子进程可能会找不到父进程。使用完整路径名可以防止出现这些问题。
检测选项
–A [on | off]
打开/关闭分配/释放堆栈跟踪(堆栈深度为 8 时缺省值为 on)。仅当针对硬件辅助检查进行检测时,才可以使用 –i adi 选项指定此标志。要获得更好的运行时性能,可以使用此选项关闭分配/释放堆栈跟踪收集。仅当安装了 Oracle Developer Studio 12.5 3/15 平台特定增强 (Platform Specific Enhancement, PSE) 时,才能使用此选项。
–c [ ‐ | library [:scope...] | file]
检查所有库中、指定的 library 中或指定的 file 中列出且由新行分隔的库中的错误。缺省设置为不检查库中的错误。可以通过添加冒号分隔的文件或目录来限制对库进行检查的范围。即使使用了 –-c 标志,可能仍会报告某些严重错误(例如错误内存写入错误),因为这些错误可能会损坏属于应用程序中其他二进制文件的内存。有关更多信息,请参见检查库或可执行文件的部分。
–F [parent | child | both]
指定如果您已使用 discover 检测的二进制文件在运行时派生,您希望发生什么情况。缺省情况下,discover 继续从父进程和子进程收集内存访问错误数据。如果您希望 discover 仅跟随父进程,则指定 –F parent。如果您希望 Discover 仅跟随子进程,则指定 –F child。
–i [datarace | memcheck | adi]
确定 discover 的检测类型(缺省值为 memcheck)。
如果指定了 datarace,则使用线程分析器针对数据争用检测进行检测。如果使用此选项,仅在运行时执行数据争用检测,而不执行其他任何内存检查。必须使用 collect 命令运行检测过的二进制文件,以生成可以在性能分析器中查看的实验。有关更多信息,请参见Oracle Developer Studio 12.5:线程分析器用户指南。 如果指定了 memcheck,则会针对内存错误检查进行检测。 如果指定了 adi,则会使用 SPARC M7 处理器的 ADI 功能针对硬件辅助检查进行检测。只有在 SPARC M7 处理器上运行的 Oracle Solaris 11.3 中,才能使用此功能。
–K
不读取 bit.rc 初始化文件(请参见bit.rc 初始化文件)。
–l
在轻量模式下运行 discover。如果您仅对查找程序中的内存泄露感兴趣,请使用 –l 选项。此模式还可以标识一些内存访问错误,而不会使程序减慢很多。类似错误的示例包括作为参数传递到 memcpy() 函数调用的 double free of a memory area 和 out of bounds access of an allocated area。建议先在 discover 的轻量模式下运行您的程序,然后再在完全模式下运行它。
–n
不检查可执行文件中的错误。即使使用了 –-n 标志,仍可能会报告某些严重错误(例如内存写入错误),因为这些错误可能会损坏属于应用程序中其他二进制文件的内存。
–N library
不检测与前缀 library 匹配的任何相关共享库。如果库名称的前几个字符与 library 匹配,则忽略该库。如果 library 以斜杠 (/) 开头,则在库的完整绝对路径名上执行匹配。否则,根据库的基本名称进行匹配。
–P [on | off]
打开或关闭精确 ADI 模式。缺省值为 on。仅当针对硬件辅助检查进行检测时,才可以使用 –i adi 选项指定此标志。要获得更好的运行时性能,可以使用此选项关闭精确 ADI 模式。
–T
仅检测命名的二进制文件。在运行时不检测任何相关的共享库。
高速缓存选项
–D cache-directory
将 cache-directory 用作用于存储高速缓存的已检测二进制文件的根目录。缺省情况下,高速缓存目录为 $HOME/SUNW_Bit_Cache。
–k
强制重新检测高速缓存中找到的所有库。
其他选项
–h 或 –?
帮助。输出简短的用法消息并退出。
–v
详细。输出 discover 正在执行的操作的日志。指定该选项两次可获取更多信息。
–V
输出 discover 版本信息并退出。
bit.rc 初始化文件
discover 实用程序通过在启动时读取一系列 bit.rc 文件来初始化其状态。系统文件 Oracle-Developer-Studio-installation-directory/lib/compilers/bit.rc 提供了某些变量的缺省值。discover 实用程序首先读取该文件,接着读取 $HOME/.bit.rc(如果存在),然后读取 current-directory/.bit.rc(如果存在)。
bit.rc 文件包含用于设置、附加或删除某些变量值的命令。当 discover 读取 set 命令时,会放弃变量以前的值(如果有)。当读取 append 命令时,会将参数附加到变量的现有值(该参数置于冒号分隔符后面)。当读取 remove 命令时,将从变量的现有值中删除参数及其冒号分隔符。
bit.rc 文件中设置的变量包括检测时要忽略的库列表,以及计算二进制文件中无注释代码百分比时要忽略的函数或函数前缀的列表。
有关更多信息,请参阅系统 bit.rc 文件头中的注释。