Skip to content

Commit 45da397

Browse files
committed
c2t: coverage estimation
Signed-off-by: Efimov Vasily <laer.18@gmail.com>
1 parent 7027cc5 commit 45da397

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

c2t.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
stderr
66
)
77
from os.path import (
8+
abspath,
89
getmtime,
910
relpath,
1011
dirname,
@@ -13,6 +14,8 @@
1314
basename
1415
)
1516
from os import (
17+
walk,
18+
remove,
1619
makedirs,
1720
killpg,
1821
setpgrp
@@ -68,6 +71,7 @@
6871
pypath
6972
)
7073
from debug import (
74+
create_dwarf_cache,
7175
get_elffile_loading,
7276
InMemoryELFFile,
7377
DWARFInfoCache,
@@ -92,6 +96,10 @@
9296
DebugServer,
9397
TestBuilder
9498
)
99+
from qemu import (
100+
qemu_build_dir_by_dwarf,
101+
qemu_target_dir_by_dwarf
102+
)
95103

96104
C2T_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

Comments
 (0)