"""
Implements the basic blame report experiment.
The experiment analyses a project with VaRA's blame analysis and generates a
BlameReport.
"""
import typing as tp
from benchbuild import Project
from benchbuild.utils import actions
from benchbuild.utils.cmd import opt
from benchbuild.utils.requirements import Requirement, SlurmMem
import varats.experiments.vara.blame_experiment as BE
from varats.data.reports.blame_report import BlameReport as BR
from varats.data.reports.blame_report import BlameTaintScope
from varats.experiment.experiment_util import (
exec_func_with_pe_error_handler,
VersionExperiment,
ExperimentHandle,
wrap_unlimit_stack_size,
create_default_compiler_error_handler,
create_default_analysis_failure_handler,
create_new_success_result_filepath,
)
from varats.experiment.wllvm import get_cached_bc_file_path, BCFileExtensions
from varats.project.project_util import get_local_project_repos
from varats.project.varats_project import VProject
from varats.report.report import ReportSpecification
[docs]
class BlameReportGeneration(actions.ProjectStep): # type: ignore
"""Analyse a project with VaRA and generate a BlameReport."""
NAME = "BlameReportGeneration"
DESCRIPTION = "Analyses the bitcode with -vara-BR of VaRA."
project: VProject
def __init__(
self, project: Project, experiment_handle: ExperimentHandle,
blame_taint_scope: BlameTaintScope
):
super().__init__(project=project)
self.__experiment_handle = experiment_handle
self.__blame_taint_scope = blame_taint_scope
def __call__(self) -> actions.StepResult:
return self.analyze()
[docs]
def analyze(self) -> actions.StepResult:
"""
This step performs the actual analysis with the correct command line
flags.
Flags used:
* -vara-BR: to run a commit flow report
* -yaml-report-outfile=<path>: specify the path to store the results
"""
for binary in self.project.binaries:
# Add to the user-defined path for saving the results of the
# analysis also the name and the unique id of the project of every
# run.
result_file = create_new_success_result_filepath(
self.__experiment_handle, BR, self.project, binary
)
opt_params = [
"--enable-new-pm=0", "-vara-BD", "-vara-BR",
"-vara-init-commits", "-vara-rewriteMD",
"-vara-git-mappings=" + ",".join([
f'{repo_name}:{repo.repo_path}' for repo_name, repo in
get_local_project_repos(self.project.name).items()
]), "-vara-use-phasar",
f"-vara-blame-taint-scope={self.__blame_taint_scope.name}",
f"-vara-report-outfile={result_file}",
get_cached_bc_file_path(
self.project, binary, [
BCFileExtensions.NO_OPT, BCFileExtensions.TBAA,
BCFileExtensions.BLAME
]
)
]
run_cmd = opt[opt_params]
run_cmd = wrap_unlimit_stack_size(run_cmd)
exec_func_with_pe_error_handler(
run_cmd,
create_default_analysis_failure_handler(
self.__experiment_handle, self.project, BR
)
)
return actions.StepResult.OK
[docs]
class BlameReportExperiment(VersionExperiment, shorthand="BRE"):
"""Generates a blame report of the project(s) specified in the call."""
NAME = "GenerateBlameReport"
REPORT_SPEC = ReportSpecification(BR)
REQUIREMENTS: tp.List[Requirement] = [SlurmMem("250G")]
BLAME_TAINT_SCOPE = BlameTaintScope.COMMIT
[docs]
def actions_for_project(
self, project: VProject
) -> tp.MutableSequence[actions.Step]:
"""
Returns the specified steps to run the project(s) specified in the call
in a fixed order.
Args:
project: to analyze
"""
# Try, to build the project without optimizations to get more precise
# blame annotations. Note: this does not guarantee that a project is
# build without optimizations because the used build tool/script can
# still add optimizations flags after the experiment specified cflags.
project.cflags += ["-O1", "-Xclang", "-disable-llvm-optzns", "-g0"]
bc_file_extensions = [
BCFileExtensions.NO_OPT,
BCFileExtensions.TBAA,
BCFileExtensions.BLAME,
]
BE.setup_basic_blame_experiment(self, project, BR)
analysis_actions = BE.generate_basic_blame_experiment_actions(
project,
bc_file_extensions,
extraction_error_handler=create_default_compiler_error_handler(
self.get_handle(), project, self.REPORT_SPEC.main_report
)
)
analysis_actions.append(
BlameReportGeneration(
project, self.get_handle(), self.BLAME_TAINT_SCOPE
)
)
analysis_actions.append(actions.Clean(project))
return analysis_actions
[docs]
class BlameReportExperimentRegion(BlameReportExperiment, shorthand="BRER"):
"""Generates a blame report with region scoped taints."""
NAME = "GenerateBlameReportRegion"
BLAME_TAINT_SCOPE = BlameTaintScope.REGION
[docs]
class BlameReportExperimentCommitInFunction(
BlameReportExperiment, shorthand="BRECIF"
):
"""Generates a blame report with commit-in-function scoped taints."""
NAME = "GenerateBlameReportCommitInFunction"
BLAME_TAINT_SCOPE = BlameTaintScope.COMMIT_IN_FUNCTION