PC6下载站

分类分类

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

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

2 页 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 。

展开全部

相关文章

更多+相同厂商

热门推荐

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

    点击查看更多

      点击查看更多

        点击查看更多

        说两句网友评论

          我要评论...
          取消