Oracle Solaris Studio 12.4 Man Pages

Exit Print View

Updated: January 2015
 
 

discover(1)

Name

discover - 内存错误搜索工具

Synopsis

 discover [-?] [-h] [-a] [-b browser] [-c [- | lib [:scope...]| file] [-D dir] [-e num] [-E num] [-f] [-F [parent|child|both]] [-H html_file] [-i] [-k] [-K] [-l] [-m] [-n] [-N lib] [-o file] [-s] [-S num] [-T] [-v] [-V] [-w txt_file] target[:scope] 

Description

内存错误搜索工具 (Discover) 是软件开发者使用的一款工具,用于在运行时检测与程序内存的分配和使用相关的编程错误。

Discover 可以检测到的错误示例包括:

  • 访问未初始化的内存

  • 对未分配的内存执行读写

  • 访问超出分配数组边界的内存

  • 使用释放的内存

  • 释放错误的内存块

  • 内存泄漏

下面是准备、检测和运行可执行文件的简单示例:

 
% cc -g -O2 test.c -o test.prep
% discover -w - -o test.disc test.prep
% ./test.disc
ERROR (UMR): accessing uninitialized data from address 0x5000c
(4 bytes) at:
     foo() + 0xdc  <ui.c:6>
          3:    int *t;
          4:    foo() {
          5:     t = malloc(5*sizeof(int));
          6:=>   printf("%d0, t[1]);
          7:    }
          8:
          9:    main()
     main() + 0x1c
     _start() + 0x108
    block at 0x50008 (20 bytes long) was allocated at:
     malloc() + 0x260
     foo() + 0x24  <ui.c:5>
          2:
          3:    int *t;
          4:    foo() {
          5:=>   t = malloc(5*sizeof(int));
          6:     printf("%d0, t[1]);
          7:    }
          8:
     main() + 0x1c
     _start() + 0x108

***************** Discover Memory Report *****************

1 block at 1 location left allocated on heap with a total size of
20 bytes

    1 block with total size of 20 bytes
     malloc() + 0x260
     foo() + 0x24  <ui.c:5>
          2:
          3:    int *t;
          4:    foo() {
          5:=>   t = malloc(5*sizeof(int));
          6:     printf("%d0, t[1]);
          7:    }
          8:
     main() + 0x1c
     _start() + 0x108

DISCOVER SUMMARY:
     unique errors   : 1 (1 total, 0 filtered)
     unique warnings : 0 (0 total, 0 filtered)

要使用 Discover,必须在安装有 Oracle Solaris 10 Update 6 或更高 Update 版本(或者 Oracle Solaris 11 Express)的计算机上使用 Sun Studio 12 Update 1、Oracle Solaris Studio 12.2 或更高 Update 版本,或者 GCC for Oracle Solaris Systems 4.2.0 或更高版本的编译器编译输入二进制文件。在更早的操作系统上,尝试 -xbinopt=prepare 标志(仅限 SPARC 平台)。使用 -g 选项允许 Discover 生成更多信息性消息。Discover 与使用 -xlinkopt 编译的二进制文件不兼容。

消息

消息

Discover 可生成以下错误消息:

 
ERROR (UAR) reading from unallocated memory
ERROR (UAW) writing to unallocated memory
ERROR (FMR) reading from freed memory
ERROR (FMW) writing to freed memory
ERROR (UMR) accessing uninitialized data
ERROR (PIR) accessing partially initialized data
ERROR (ABR) reading memory beyond array bounds
ERROR (ABW) writing to memory beyond array bounds
ERROR (DFM) double freeing memory
ERROR (BFM) freeing wrong memory block
ERROR (BRP) bad address parameter for realloc
ERROR (SBR) read is beyond current stack bounds
ERROR (SBW) write is beyond current stack bounds
ERROR (IMR) read from invalid memory address
ERROR (IMW) write to invalid memory address
ERROR (FRP) freed pointer passed to realloc
ERROR (CGB) corrupted array guard block
ERROR (OLP) overlapping source and destination
WARNING (AZS) allocating zero size memory block
WARNING (NAR) non-annotated read
WARNING (NAW) non-annotated write
WARNING (SMR) speculative memory read
WARNING (UFR) unknown stack frame read
WARNING (UFW) unknown stack frame write
WARNING (USR) unknown status while reading
WARNING (USW) unknown status while writing

Options

支持以下选项:

?
-h

输出帮助消息。

-a

将错误数据写入 binary_name.analyze/dynamic 目录以供代码分析器使用。

-b browser

运行检测过的程序时,将自动启动 Web 浏览器 browser(缺省情况下关闭)。

-c [- | lib [:scope...]| file]

检查所有库中、lib 中或者 file 中所列出的库(用新行分隔)中的错误。缺省设置是不检查库中的错误。

通过添加冒号分隔的文件或目录来限制对库检查的范围。scope 可以是 ELF 文件或目录。如果指定了 ELF 文件,将检查文件中定义的所有函数。如果指定了目录,将递归使用目录中的所有文件。例如,-c libt.so:/abc/t1.o:t2.o:dir 只在库 libt.so 中检查在 /abc/t1.ot2.o 以及 dir 下的所有 ELF 文件中定义的函数。如果库是使用 -c 文件选项的列表,则可将 scope 添加到列表中的任何行。

-D dir

高速缓存目录。缺省为 $HOME/SUNW_Bit_Cache。

-e n

仅在报告中显示 n 个内存错误(缺省情况下显示所有错误)。

-E n

仅在报告中显示n个内存泄漏(缺省情况下显示 100 个)

-f

在报告中显示偏移(缺省情况下隐藏)。

-F [parent | child | both]

确定如果使用 Discover 检测过的二进制文件在运行时派生会出现什么情况。缺省情况下,Discover 继续从父进程和子进程收集内存访问错误数据。如果希望 Discover 仅跟踪父进程,请指定 -F parent。如果希望 Discover 仅跟踪子进程,请指定 -F child。

-H html_file

HTML 文件的输出分析。如果 html_file 是相对路径名,则它位于相对于运行检测过的二进制文件时所在工作目录的位置。如果文件名包含 %p,它将替换为进程 ID。有关更多详细信息,请参见 -w

-i

执行检测以便检测数据争用。请参见 Oracle Studio 线程分析器文档。

-k

强制重新检测。

-K

不读取 bit.rc 初始化文件。

-l

在轻量模式下运行 Discover。实现更快的程序执行,但是检测的错误数有限。输入二进制文件无需特殊准备。

-m

在报告中显示改编名称(缺省情况下隐藏)。

-n

不检查可执行文件中的错误。缺省设置是检测可执行文件中的错误。

-N lib

忽略 lib

-o file

检测过的输出文件名。

-s

如果从属库不可检测,属于正常现象。

-S n

仅在报告中显示 n 个堆栈帧(缺省情况下显示 8 个)。

-T

在运行时不检测库。

-v

详细模式。

-V

输出版本信息并退出而不执行任何进一步处理。

-w txt_file

将 Discover 分析写入文本文件。使用 "-" 可指定 stderr。如果 txt_file 是相对路径名,则它位于相对于运行检测过的二进制文件时所在工作目录的位置。您可以使文件名对于进程唯一,方法是要求 Discover 运行时将进程 ID 添加到文件名。这可通过将 %p 字符串添加到文件名来完成。例如,-w report.%p.txt 标志生成文件 report.process_ID.txt。如果文件名中有多个 %p 宏,将仅替换第一个。

target[:scope]

通过添加冒号分隔的文件或目录来限制目标的检查范围。scope 可以是 ELF 文件或目录。如果指定了 ELF 文件,将检查文件中定义的所有函数。如果指定了目录,将递归使用目录中的所有文件。例如,a.out:/abc/t1.o:t2.o:dir 只在目标 a.out 中检查在 /abc/t1.ot2.o 以及 dir 下的所有 ELF 文件中定义的函数。

Usage

Discover 可以使用 -w txtfile 选项生成文本报告,或者使用 -H html_file 选项生成 HTML 报告,亦或同时使用这两个选项生成两种报告。

如果两个选项都未使用,则缺省输出为 html 文件 outfile.html,其中 outfile 是检测过的输出文件的基名。该文件位于运行检测过的二进制文件时所在的工作目录中。

Exit Status

返回以下退出值:

0

所有输入文件都已成功输出。

1

出错。

Environment Variables

SUNW_DISCOVER_OPTIONS

通过将该环境变量设置为一系列搜索标志 (-a, -b, -e, -E, -f, -F, -H, -l, -L, -m, -S, -w) 可更改检测过的二进制文件的运行时行为。例如,如果要将报告的错误数更改为 50 并将报告中的堆栈深度限制到 3,应将设置 SUNW_DISCOVER_OPTIONS 设置为 "-E 50 -S 3"。

Examples

Example 1 将输出发送到 HTML 文件中。

缺省情况下,Discover 会将输出发送到 HTML 文件。

 
% cat dtest_2.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    char *cp;
    cp = (char *)malloc(10);
    cp[11] = 't';
    return 0;
}

% cc -g -O1 -o dtest_2.prep dtest_2.c
% discover -o dtest_2.disc dtest_2.prep
% ./dtest_2.disc
% ls
dtest_2.c
dtest_2.prep*
dtest_2.disc*
dtest_2.disc.html

请注意,Discover 不输出消息但生成 HTML 文件,提供摘要和易于使用的单击即可查看详细信息的界面。

Example 2 将文本形式的报告输出到 stderr

本例使用的程序与示例 #1 中相同,但是使用 "-w -" 选项将文本格式的报告输出到 stderr

% discover -w - -o dtest_2.disc dtest_2.prep
% ./dtest_2.disc
ERROR (ABW): writing to memory beyond array bounds at address 0x50013 (1 byte) at:
     main() + 0x138  <dtest_2.c:7>
           4:    {
           5:        char *cp;
           6:        cp = (char *)malloc(10);
           7:=>      cp[11] = 't';
           8:        return 0;
           9:    }
     _start() + 0x108
    block at 0x50008 (10 bytes long) was allocated at:
     malloc() + 0x260
     main() + 0x94  <dtest_2.c:6>
          3:    int main(int argc, char *argv[])
          4:    {
          5:        char *cp;
          6:=>      cp = (char *)malloc(10);
          7:        cp[11] = 't';
          8:        return 0;
          9:    }
     _start() + 0x108

***************** Discover Memory Report *****************

1 block at 1 location left allocated on heap with a total size of 
10 bytes

    1 block with total size of 10 bytes
     malloc() + 0x260
     main() + 0x94  <dtest_2.c:6>
          3:    int main(int argc, char *argv[])
          4:    {
          5:        char *cp;
          6:=>      cp = (char *)malloc(10);
          7:        cp[11] = 't';
          8:        return 0;
          9:    }
     _start() + 0x108

DISCOVER SUMMARY:
     unique errors   : 1 (1 total, 0 filtered)
     unique warnings : 0 (0 total, 0 filtered)
          
           
Example 3 检查包含未初始化数据使用的程序。

本例检查包含未初始化数据使用的程序:

 
% cat dtest_3.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    char s[10];
    printf("s[1] = %d\n",s[1]);
    return 0;
}

% cc -g -O1 -o dtest_3.prep dtest_3.c
% ./dtest_3.prep
s[1] = 5

% discover -w - -o dtest_3.disc dtest_3.prep
% ./dtest_3.disc
ERROR (UMR): accessing uninitialized data from address 0xffbff023
(1 byte) at:
        main() + 0x4c [dtest_3.disc:0x3004c]
          <dtest_3.c:7>:
                 4:    int main(int argc, char *argv[])
                 5:    {
                 6:        char s[10];
                 7:=>      printf("s[1] = %d\n",s[1]);
                 8:        return 0;
                 9:    }
                10:
        _start() + 0x108 [dtest_3.disc:0x107cc]
s[1] = 5

***************** Discover Memory Report *****************
No allocated memory left on program exit.
DISCOVER SUMMARY:
        unique errors   : 1 (1 total)
        unique warnings : 0 (0 total)

要求

要求

操作系统要求

Discover 软件可在 Oracle Solaris 10 Update 6 或更高的 Update 版本以及 Oracle Solaris 11 Express 上运行。

编译器要求

Discover 软件只能与使用 Sun Studio 12 Update 1、Oracle Solaris Studio 12.2、Oracle Solaris Studio 12.3 或 Oracle Solaris Studio 13 编译器编译的二进制文件一起使用。如果尝试对并非按上述方式编译的二进制文件运行 Discover,Discover 会发出错误并且不检测二进制文件。强烈建议在生成二进制文件时使用 -g 选项。如果不使用 -g 选项,Discover 在报告错误和警告时不会显示源代码和行号信息,而仅显示相应计算机级指令的程序计数器 (program counter, PC),这些信息可能不是那么有用。此外,使用 -g 选项还有助于 Discover 软件生成更准确的结果。使用 -xlinkopt 标志编译的二进制文件与 Discover 不兼容。

检测共享库

如果检测了整个程序(包括所有共享库),Discover 可生成最准确的结果。缺省情况下,Discover 仅检查并报告可执行文件中的内存错误。Discover 运行时使用链接程序审计接口(又称为 rtld-audit)或 LD_AUDIT 环境变量自动从 Discover 的高速缓存目录装入检测过的共享库。在 Oracle Solaris 上,缺省情况下使用审计接口。在 Linux 上,当运行检测过的二进制文件时,需要在命令行上设置 LD_AUDIT

对于 Oracle Linux 上的 32 位应用程序,请使用以下命令:

% LD_AUDIT=/compiler/prod/lib/postopt/bitdl.so a.out

对于 Oracle Linux 上的 64 位应用程序,请使用以下命令:

% LD_AUDIT=/compiler/prod/lib/postopt/amd64/bitdl.so a.out

此机制并非适用于所有运行 Oracle Enterprise Linux 5.x 的环境。如果不需要库检测并且未设置 LD_AUDIT,则可以在 Oracle Enterprise Linux 5.x 上使用 Discover。有关正确准备二进制文件的更多信息,请参见《Oracle Solaris Studio:Discover 和 Uncover 用户指南》。

Files

Discover 和 bit.rc 文件

Discover 通过在启动时读取一系列 .rc 文件来初始化自身的状态。系统文件 compiler_area/prod/lib/postopt/bit.rc 为某些变量提供了缺省值。Discover 先读取此文件,然后读取 $HOME/.bit.rc(如果有),最后读取 `pwd`/.bit.rc(如果有)。

.rc 文件包含命令 to setappend to 和 remove from 变量。每当看到 set 命令,都会丢弃变量以前的值(如果有)。append 命令可将参数附加到变量的现有值(在冒号分隔符后面)。remove 命令可从变量的现有值中删除参数(连同冒号分隔符)。

.rc 文件中设置的变量包括检测时要忽略的库列表,以及计算库中无注释代码百分比时要忽略的函数或函数前缀的列表。

有关更多信息,请参见系统 .rc 文件中的标题。

See also

code-analyzer (1) 、 CC (1) 、 cc (1) 、 f77 (1) 、 f90 (1) 、 f95 (1) 、gcc(1)、 bit (3F)