#!/usr/software/bin/python2.7 -utt from struct import * import commands import re import os import sys global func_dict func_dict = {} def read_gcno_data(fh, big_endian, length, type, reset_pos): if (type == "string"): #print "Length: read_gcno_data" length = read_gcno_data(fh, big_endian, -1, "value", False) if length is None: return None elif length == 0: return "" else: length = length * 4 string = fh.read(length) if string is None: return None return string.replace("\0","") elif (type == "value"): word = read_gcno_data(fh, big_endian, -1, "word", reset_pos) if word is None: return None #print unpack("=L", word) if (big_endian == 1): return unpack("!L", word)[0] else: return unpack("=L", word)[0] elif (type == "word"): if(reset_pos): pos = fh.tell() #prev_pos = fh.tell() #print "Tell = %d" % fh.tell() data = fh.read(4) #curr_pos = fh.tell() #print "Tell = %d %s" % (fh.tell(), data) if(reset_pos): seek = fh.seek(pos, 0) return data elif (type == "skip"): return fh.read(length) def is_func_checksum(fh, big_endian, length): cmd = "/usr/software/build/compilers/i386-unknown-freebsd7-gcc-4.2.1_p11/bin/i386-unknown-freebsd7-gcov -v" (status, output) = commands.getstatusoutput(cmd) if(status != 0): print "Get GCOV version using 'gcov -v' : FAILED" match = re.search("(\d+)\.(\d+)\.?(\d+)?", output) version = match.group().split(".") if(int(version[0]) >= 4 and int(version[1]) >= 7): print match.group() return True #print "str_len: is_func_checksum" str_len = read_gcno_data(fh, big_endian, -1, "value", True) if (str_len * 4) >= (length - 12): return True return False def read_gcno_func_data(fh, big_endian, length): global func_dict #Skip 8 bytes of Function Ident and Checksum read_gcno_data(fh, big_endian, 8, "skip", False) if(is_func_checksum(fh, big_endian, length)): #Skip 4 bytes Function Cfg Checksum read_gcno_data(fh, big_endian, 4, "skip", False) function = read_gcno_data(fh, big_endian, -1, "string", False) file = read_gcno_data(fh, big_endian, -1, "string", False) #print "Line Num: Func Data" line_num = read_gcno_data(fh, big_endian, -1, "value", False) if (not (function is None) and not (file is None) and not (line_num is None)): if function not in func_dict: func_dict[function] = list() func_dict[function].append(line_num) return (file, function, line_num) else: return (None, None, None) def read_gcno_line_data(fh, big_endian, file_name, function): global func_dict line_nums = [] empty_data = [] #Skip 4 bytes of basic block index read_gcno_data(fh, big_endian, 4, "skip", False) while (1): #print "Line Num: Line Data" line_num = read_gcno_data(fh, big_endian, -1, "value", False) if line_num is None: return (None, empty_data) if line_num == 0: string = read_gcno_data(fh, big_endian, -1, "string", False) if string is None: return (None, empty_data) if string == "": return (file_name, line_nums) file_name = string if function not in func_dict: func_dict[function] = list() continue if file_name is None: print "WARNING: unassigned line number in " continue func_dict[function].append(line_num) line_nums.append(line_num) #print "%s %s %d" % (file_name, function, line_num) def read_gcno_file(filename): big_endian_check = 0x67636e6f tag_function = 0x01000000 tag_lines = 0x01450000 file_name = None function = None fh = open(filename, 'rb') #First 4 Bytes File Magic data data = read_gcno_data(fh, -1, -1, "word", False) if (unpack("!L", data)[0] == big_endian_check): big_endian = 1 elif (unpack("=L", data)[0] == big_endian_check): big_endian = 0 else: print "found unrecognized gcno file magic" return False print big_endian # Skip 8 bytes of version and stamp data read_gcno_data(fh, big_endian, 8, "skip", False) base = read_gcno_data(fh, big_endian, -1, "string", False) print base sys.exit(0) file_data = {} empty_data = {} while (fh.tell() != os.fstat(fh.fileno()).st_size): #print "tag: read_gcno_file" tag = read_gcno_data(fh, big_endian, -1, "value", False) if (tag is None): print "Unexpected end of file" return empty_data #print "length: read_gcno_file" length = read_gcno_data(fh, big_endian, -1, "value", False) if (length is None): print "Unexpected end of file" return empty_data length = length * 4 next_pos = fh.tell() if next_pos == -1: print "Could not determine the file position" return empty_data next_pos = next_pos + length if (tag == tag_function): (file_name, function, line_num) = read_gcno_func_data(fh, big_endian, length) abs_file_name = "%s/%s" % (base, file_name) if abs_file_name not in file_data: file_data[abs_file_name] = {} file_data[abs_file_name]['function'] = {} file_data[abs_file_name]['line'] = [] #print "%s %s %d" % (file_name, function, line_num) if function is None: print "Unexpected end of file" return empty_data file_data[abs_file_name]['function'][function] = line_num #print "New Entry" #print abs_file_name #print file_data[abs_file_name]['function'] elif (tag == tag_lines): (file_name, line_num) = read_gcno_line_data(fh, big_endian, file_name, function) abs_file_name = "%s/%s" % (base, file_name) if file_name is None: print "Unexpected end of file" return empty_data file_data[abs_file_name]['line'].extend(line_num) else: read_gcno_data(fh, big_endian, length, "skip", False) curr_pos = fh.tell() if curr_pos == -1: print "Could not determine the file position" return empty_data if curr_pos == next_pos: continue if curr_pos > next_pos: print "found unrecognized gcno file magic" return empty_data read_gcno_data(fh, big_endian, next_pos - curr_pos, "skip", False) fh.close() return file_data #file_data = read_gcno_file("/u/rathishk/ccode/files/rotatedarray.gcno") file_data = read_gcno_file("/x/eng/nrlse43/DOT/nightly/mainN_130126_2059/scsi_blade/scsit/bedrock/obj/x86_64.debug.gcov/scsit_bb_ds_fsm.gcno") print "Before Print" for file in file_data.keys(): print file for func_name in file_data[file]['function'].keys(): print "%s,%s\n" % (file_data[file]['function'][func_name], func_name) for i in file_data[file]['line']: print i print "After Print" sys.exit(0) file_data = read_gcno_file("/u/rathishk/test.gcno") print file_data['/u/rathishk/ccode/test.c']['function'] print file_data['/u/rathishk/ccode/test.c']['line']