PC6下载站

分类分类

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

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

12 页 dump_file 函数分析

2.2 dump_file 函数分析

 

gcov-dump 程序的主函数 main ,是靠调用 dump_file() 函数来完成文件内容的输出。该函数定义如下。其中的注释为笔者所加。

static void

dump_file ( const char * filename )

{

    unsigned tags [ 4 ];

    unsigned depth = 0 ;

 

    if ( ! gcov_open ( filename , 1 ))  /* it will open .gcda/.gcno file, and save information into gcov_var */

    {

        fprintf ( stderr , "%s:cannot open/n" , filename );

        return ;

    }

 

    /* magic */

    {

        unsigned magic = gcov_read_unsigned ();

        unsigned version ;

        const char * type = NULL ;

        int endianness = 0 ;

        char m [ 4 ], v [ 4 ];

 

        /***** compare magic read just now with "gcda" or "gcno" to confirm file type */

        if (( endianness = gcov_magic ( magic , GCOV_DATA_MAGIC )))

            type = "data" ;

        else if (( endianness = gcov_magic ( magic , GCOV_NOTE_MAGIC )))

             type = "note" ;

        else

        {

            printf ( "%s:not a gcov file/n" , filename );

            gcov_close ();

            return ;

        }

        /***** read version, an unsigned word */

        version = gcov_read_unsigned ();

 

        /***** Convert a magic or version number to a 4 character string with ASCII */

        GCOV_UNSIGNED2STRING ( v , version );

        GCOV_UNSIGNED2STRING ( m , magic );

        printf ("%s:%s:magic `%.4s':version `%.4s'%s/n", filename , type ,

                m , v , endianness < 0 ? " (swapped endianness)" : "");

        if ( version != GCOV_VERSION )

        {

              char e [ 4 ];

             GCOV_UNSIGNED2STRING ( e , GCOV_VERSION );

             printf ( "%s:warning:current version is `%.4s'/n" , filename , e );

        }

    }

 

    /* stamp */

    {

        unsigned stamp = gcov_read_unsigned ();

        printf ( "%s:stamp %lu/n" , filename , ( unsigned long ) stamp );

    }

 

    while ( 1 )

    {

        gcov_position_t base , position = gcov_position ();

        unsigned tag , length ; tag_format_t const * format ; unsigned tag_depth ;

        int error ;

        unsigned mask ;

 

        /***** read a tag, for example, 0x01000000, 0x01a10000, 0xa1000000, etc */

        tag = gcov_read_unsigned ();

        if ( ! tag ) /***** tag=0x00000000, then, to the end of file, break *****/

            break ;

 

        /***** read its length tag */

        length = gcov_read_unsigned ();

        base = gcov_position ();

 

        /***** for example, tag=0x01000000, then, tag- 1=0xFFFFFF,

          * then, GCOV_TAG_MASK (tag)=0x1FFFFFF, then, mask = 0x1FFFFFF/ 2 = 0xFFFFFF

        */

        mask = GCOV_TAG_MASK ( tag ) >> 1 ;

 

        /****** validate the tag */

        for ( tag_depth = 4 ; mask ; mask >>= 8 )

        {

            if (( mask & 0xff ) != 0xff )

            {

                printf ( "%s:tag `%08x' is invalid/n" , filename , tag );

                break ;

            }

            tag_depth -- ;

        }

 

        /***** find the tag in tag_table, if found, then call its procedure */

        for ( format = tag_table ; format - >name ; format ++ )

            if ( format - >tag == tag )

                goto found ;

        format = & tag_table [ GCOV_TAG_IS_COUNTER ( tag ) ? 2 : 1 ];

found :

        ;

        if ( tag )

        {

            if ( depth && depth < tag_depth )

            {

                if ( ! GCOV_TAG_IS_SUBTAG ( tags [ depth - 1 ], tag ))

                printf ( "%s:tag `%08x' is incorrectly nested/n" ,

                filename , tag );

            }

            depth = tag_depth ;

            tags [ depth - 1 ] = tag ;

        }

 

        /***** print some spaces to represent the depth level */

        print_prefix ( filename , tag_depth , position );

        printf ( "%08x:%4u:%s" , tag , length , format - >name );

        /***** call the procedure of this tag stored in tag_table */

        if ( format - >proc )

             (*format- >proc) (filename, tag, length);  // 此处调用相应的 tag 处理函数

 

        printf ( "/n" );

        if ( flag_dump_contents && format - >proc )

        {

            unsigned long actual_length = gcov_position () - base ;

            if ( actual_length > length )

                printf ( "%s:record size mismatch %lu bytes overread/n" ,

                    filename , actual_length - length );

            else if ( length > actual_length )

                printf ( "%s:record size mismatch %lu bytes unread/n" ,

                    filename , length - actual_length );

        }

 

        /***** base stands for the base position of a tag, then, synchronize the pointer */

        gcov_sync ( base , length );

        if (( error = gcov_is_error ()))

        {

            printf ( error < 0 ? "%s:counter overflow at %lu/n" :

                "%s:read error at %lu/n" , filename ,

                ( long unsigned ) gcov_position ());

            break ;

        }

    }

    gcov_close ();

}

dump_file 函数首先通过 gcov_open 打开 .gcda/.gcno 文件,将文件信息保存到全局变量 gcov_var( 稍后介绍该变量 ) ,接着读取文件头信息,包括 magic , version , stamp ,然后 循环 读取每个 tag , length ,并通过函数指针处理该 tag ,直到文件结束 (0x00000000) 。下面介绍各种 tag 的 callback 。

展开全部

相关文章

更多+相同厂商

热门推荐

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

    点击查看更多

      点击查看更多

        点击查看更多

        说两句网友评论

          我要评论...
          取消