55 stderr
66)
77from os .path import (
8+ abspath ,
89 getmtime ,
910 relpath ,
1011 dirname ,
1314 basename
1415)
1516from os import (
17+ walk ,
18+ remove ,
1619 makedirs ,
1720 killpg ,
1821 setpgrp
6871 pypath
6972)
7073from debug import (
74+ create_dwarf_cache ,
7175 get_elffile_loading ,
7276 InMemoryELFFile ,
7377 DWARFInfoCache ,
9296 DebugServer ,
9397 TestBuilder
9498)
99+ from qemu import (
100+ qemu_build_dir_by_dwarf ,
101+ qemu_target_dir_by_dwarf
102+ )
95103
96104C2T_ERRMSG_FORMAT = "{prog}:\x1b [31m error:\x1b [0m {msg}\n "
97105
@@ -772,6 +780,18 @@ def main():
772780 metavar = "executable" ,
773781 help = "ignore the option in config"
774782 )
783+ parser .add_argument ("-c" , "--lcov" ,
784+ action = "store_true" ,
785+ help = "estimate TCG frontend coverage by this test session"
786+ )
787+ parser .add_argument ("--coverage-output" ,
788+ default = "c2t.coverage" ,
789+ help = "directory for genhtml (lcov) coverage report"
790+ )
791+ parser .add_argument ("-b" , "--build" ,
792+ nargs = "?" ,
793+ help = "explicitly set QEMU build directory"
794+ )
775795
776796 args = parser .parse_args ()
777797
@@ -833,6 +853,52 @@ def main():
833853 if jobs < 1 :
834854 parser .error ("wrong number of jobs: %s" % jobs )
835855
856+ lcov = args .lcov
857+ if lcov :
858+ # XXX: Coverage estimation is a monkey style code. But it's better
859+ # than working with lcov manually.
860+
861+ # Here we looking for TCG frontend build directory because estimation
862+ # of whole Qemu coverage is time consuming and is not a point of c2t.
863+ qemu_exe = c2t_cfg .qemu .run .executable
864+ dic = create_dwarf_cache (qemu_exe )
865+
866+ build_dir = args .build
867+ if not build_dir :
868+ try :
869+ build_dir = qemu_build_dir_by_dwarf (dic )
870+ except RuntimeError :
871+ print ("Use -b option to set QEMU build directory explicitly" )
872+ raise
873+
874+ arch = qemu_exe .split ('-' )[- 1 ]
875+ if "system" in qemu_exe :
876+ build_dir_suffix = arch + "-softmmu"
877+ else :
878+ build_dir_suffix = arch + "-linux-user"
879+
880+ target_build_dir = join (build_dir , build_dir_suffix )
881+
882+ # find TCG frontend build directory
883+ for frontend_build_dir , __ , files in walk (target_build_dir ):
884+ # TCG frontend build directory normally contains translate.o.
885+ # Name of the directory may vary between qemu version.
886+ if "translate.o" in files :
887+ break
888+ else :
889+ print ("c2t cannot find TCG frontend build directory" )
890+ return
891+
892+ # reset previous coverage
893+ lcov = Popen (["lcov" ,
894+ "--zerocounters" ,
895+ "--directory" , frontend_build_dir
896+ ])
897+ if lcov .wait ():
898+ # lcov likely print an error message, so we only conclude...
899+ print ("c2t stopped because of lcov failure" )
900+ return
901+
836902 # creates tests subdirectories if they don't exist
837903 for sub_dir in (C2T_TEST_IR_DIR , C2T_TEST_BIN_DIR ):
838904 if not exists (sub_dir ):
@@ -841,6 +907,34 @@ def main():
841907 start_cpu_testing (tests , jobs , args .reuse , args .verbose ,
842908 errors2stop = args .errors
843909 )
910+
911+ if lcov :
912+ target_dir = qemu_target_dir_by_dwarf (dic .di )
913+ lcov = Popen (["lcov" ,
914+ "--output-file" , "c2t.coverage.info" ,
915+ "--capture" ,
916+ "--base-directory" , target_dir ,
917+ "--no-external" , # TCG frontend coverage only
918+ "--directory" , frontend_build_dir
919+ ])
920+ if lcov .wait ():
921+ print ("Failed to build coverage report" )
922+ return
923+
924+ genhtml = Popen (["genhtml" ,
925+ "--output-directory" , args .coverage_output ,
926+ "c2t.coverage.info"
927+ ])
928+ if genhtml .wait ():
929+ print ("HTML coverage report generation has failed" )
930+ else :
931+ # Note, genhtml prints some coverage statistic to stdout
932+ print ("HTML coverage report: "
933+ + abspath (join (args .coverage_output , "index.html" ))
934+ )
935+
936+ remove ("c2t.coverage.info" )
937+
844938 killpg (0 , SIGTERM )
845939
846940
0 commit comments