PC6下载站

分类分类

gcov-dump原理分析_Linux平台代码覆盖率测试

关注+2011-07-12作者:清晨

16 页 LINES tag: tag_lines() 函数
 

 

3.4 LINES tag: tag_lines() 函数

static void

tag_lines ( const char * filename ATTRIBUTE_UNUSED ,

unsigned tag ATTRIBUTE_UNUSED , unsigned length ATTRIBUTE_UNUSED )

{

    if ( flag_dump_contents )

    {

        unsigned blockno = gcov_read_unsigned ();

        char const * sep = NULL ;

 

        while ( 1 )

        {

            gcov_position_t position = gcov_position ();

            const char * source = NULL ;

            unsigned lineno = gcov_read_unsigned ();

 

            if ( ! lineno )  //lineno=0 时才会执行该 clause ,因此 lineno=0 即为以后的新的文件的标志

            {

                  source = gcov_read_string ();  // 该函数读取 length(4 字节 ) 和 length 个 words(4*length 字节 )

                  if ( ! source )                  //source 即为文件名,没有源文件了,就退出

                      break ;

                 sep = NULL ;

            }

 

            if ( ! sep )  //sep=NULL 才会执行该 clause ,那么什么时候会为 NULL 呢?——就是新的文件开始,实际上就是 lineno=0

            {

                 printf ( "/n" );

                  print_prefix ( filename , 0 , position );

                  printf ( "/tblock %u:" , blockno );

                 sep = "" ;

            }

 

            if ( lineno )

            {

                 printf ( "%s%u" , sep , lineno );

                  sep = ", " ;

            }

            else

            {

                  printf ( "%s`%s'" , sep , source );  //lineno=0 时,输出该文件名,之后 sep= " : "

                  sep = ":" ;

            }

        }

    }

}

输出格式:

    block blockno:'filename':lineno1, lineno2, ...

 

例如: block 1:'test.c':4, 7, 9

其中,前面的 block 为提示信息。同上,需要注意前导符或者输出位置。

 

3.5 COUNTER tag: tag_counters() 函数

static void

tag_counters ( const char * filename ATTRIBUTE_UNUSED ,

unsigned tag ATTRIBUTE_UNUSED , unsigned length ATTRIBUTE_UNUSED )

{

    static const char *const counter_names [] = GCOV_COUNTER_NAMES ;

    unsigned n_counts = GCOV_TAG_COUNTER_NUM ( length );

 

    printf ( " %s %u counts" ,

        counter_names [ GCOV_COUNTER_FOR_TAG ( tag )], n_counts );

    if ( flag_dump_contents )

    {

        unsigned ix ;

 

        for ( ix = 0 ; ix != n_counts ; ix ++ )

        {

            gcov_type count ;

            if ( ! ( ix & 7 ))  // 如果 counter 较多,则每 8 个 1 行输出,且按 0 , 8 , 16 , ... 输出序号

            {

                printf ( "/n" );

                print_prefix ( filename , 0 , gcov_position ());

                printf ( "/t/t%u" , ix );  // 输出序号

            }

 

            count = gcov_read_counter ();  // 读取该 counter ,读取 8 字节,但返回 4 字节

            printf ( " " );

            printf ( HOST_WIDEST_INT_PRINT_DEC , count );

        }

    }

}

关于 GCOV_TAG_COUNTER_NUM 和 GCOV_COUNTER_FOR_TAG ,请参考源代码。

 

counter 的名字定义如下。

/* A list of human readable names of the counters */

#define GCOV_COUNTER_NAMES         {"arcs ", "interval", "pow2", "single", "delta"}

输出格式:

    arcs n counts   //arcs 即为 counter 的名字,如上

    0 counter0 counter1 ... counter7   // 每 8 个 1 行输出,前面的 0 表示序号

    8 counter8 counter9 ... counter15  // 前面的 8 表示序号

    ...

同上,需要注意前导符或者输出位置。

 

3.6 OBJECT/PROGRAM SUMMARY tag: tag_summary() 函数

static void  

tag_summary ( const char * filename ATTRIBUTE_UNUSED ,

unsigned tag ATTRIBUTE_UNUSED , unsigned length ATTRIBUTE_UNUSED )

{

    struct gcov_summary summary ;

    unsigned ix ;

 

    /***** initialize all members with 0 *****/

    memset( & summary , 0 , sizeof ( summary ));

 

    unsigned count = gcov_read_summary ( & summary );  // 读取该 summary

    printf ( " checksum=0x%08x" , summary .checksum );

 

    /* for (ix = 0; ix ! = GCOV_COUNTERS; ix++) */  /* 原来的代码 */

    for ( ix = 0 ; ix < count ; ix ++ )                  /* 应该如此修改 */

    {

        printf ( "/n" );

        print_prefix ( filename , 0 , 0 );

        printf ( "/t/tcounts=%u, runs=%u" , summary .ctrs [ ix ] .num , summary .ctrs [ ix ] .runs );

        printf ( ", sum_all=" HOST_WIDEST_INT_PRINT_DEC , ( HOST_WIDEST_INT ) summary .ctrs [ ix ] .sum_all );

        printf ( ", run_max=" HOST_WIDEST_INT_PRINT_DEC , ( HOST_WIDEST_INT ) summary .ctrs [ ix ] .run_max );

        printf ( ", sum_max=" HOST_WIDEST_INT_PRINT_DEC , ( HOST_WIDEST_INT ) summary .ctrs [ ix ] .sum_max );

    }

}

输出格式:

    checksum=0x51924f98

    counts=5, runs=1, sum_all=12, run_max=10, sum_max=10

同上,也需要注意前导符或者输出位置。

 

其中, gcov_read_summary 函数是修改后的函数,在 " Linux 平台代码覆盖率测试 -GCC 如何编译生成 gcov/gcov-dump 程序及其 bug 分析 " 一文没有列出该修改后的函数,其实这篇文章中的 bug 与该函数有关。此处列出其代码。

GCOV_LINKAGE unsigned

gcov_read_summary ( struct gcov_summary * summary )

{

    unsigned ix ;

    struct gcov_ctr_summary * csum ;

 

    summary - >checksum = gcov_read_unsigned (); /***** checksum is a words (4Bytes) *****/

 

    /***** that is, a summry is 32Bytes (sizeof(gcov_type)=4) or 20Bytes (sizeof(gcov_type)=8) *****/

    for ( csum = summary - >ctrs , ix = GCOV_COUNTERS_SUMMABLE ; ix -- ; csum ++ )

    {

        csum - >num = gcov_read_unsigned (); /***** 4Bytes *****/

        csum - >runs = gcov_read_unsigned (); /***** 4Bytes *****/

        csum - >sum_all = gcov_read_counter (); /***** 8Bytes , but return 4Bytes *****/

        csum - >run_max = gcov_read_counter (); /***** 8Bytes , but return 4Bytes *****/

        csum - >sum_max = gcov_read_counter (); /***** 8Bytes , but return 4Bytes *****/

    }

 

    return GCOV_COUNTERS_SUMMABLE ; /* zubo modified to return the nubmer */

}

gcov_summary 及 gcov_ctr_summary 结构的定义可参考源代码或者 " Linux 平台代码覆盖率测试工具 GCOV 相关文件分析 " 。

 

4. 小结

 

本文详细叙述了 gcov-dump 程序的结构和实现原理。也从中学习了其处理各种 tag 用到的 callback 方法,如果你想深入跟踪或学习 gcc 源码,请注意 callback 的使用,因为 gcc 源码中大量地使用了 callback 。

展开全部

相关文章

更多+相同厂商

热门推荐

  • 最新排行
  • 最热排行
  • 评分最高
排行榜

    点击查看更多

      点击查看更多

        点击查看更多

        说两句网友评论

          我要评论...
          取消