1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3 2*2f2c4c7aSAndroid Build Coastguard Worker# SPDX-License-Identifier: GPL-2.0 3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright (C) 2024 The Android Open Source Project 4*2f2c4c7aSAndroid Build Coastguard Worker# 5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*2f2c4c7aSAndroid Build Coastguard Worker# 9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*2f2c4c7aSAndroid Build Coastguard Worker# 11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License. 16*2f2c4c7aSAndroid Build Coastguard Worker 17*2f2c4c7aSAndroid Build Coastguard Worker"""This utility generates a single lcov tracefile from a gcov tar file.""" 18*2f2c4c7aSAndroid Build Coastguard Worker 19*2f2c4c7aSAndroid Build Coastguard Workerimport argparse 20*2f2c4c7aSAndroid Build Coastguard Workerimport collections 21*2f2c4c7aSAndroid Build Coastguard Workerimport fnmatch 22*2f2c4c7aSAndroid Build Coastguard Workerimport glob 23*2f2c4c7aSAndroid Build Coastguard Workerimport json 24*2f2c4c7aSAndroid Build Coastguard Workerimport logging 25*2f2c4c7aSAndroid Build Coastguard Workerimport os 26*2f2c4c7aSAndroid Build Coastguard Workerimport pathlib 27*2f2c4c7aSAndroid Build Coastguard Workerimport re 28*2f2c4c7aSAndroid Build Coastguard Workerimport shutil 29*2f2c4c7aSAndroid Build Coastguard Workerimport sys 30*2f2c4c7aSAndroid Build Coastguard Workerimport tarfile 31*2f2c4c7aSAndroid Build Coastguard Worker 32*2f2c4c7aSAndroid Build Coastguard Worker 33*2f2c4c7aSAndroid Build Coastguard WorkerLCOV = "lcov" 34*2f2c4c7aSAndroid Build Coastguard Worker 35*2f2c4c7aSAndroid Build Coastguard Worker# Relative to the root of the source tree. 36*2f2c4c7aSAndroid Build Coastguard WorkerOUTPUT_COV_DIR = os.path.join("out", "coverage") 37*2f2c4c7aSAndroid Build Coastguard Worker 38*2f2c4c7aSAndroid Build Coastguard WorkerBUILD_CONFIG_CONSTANTS_PATH = os.path.join("common", "build.config.constants") 39*2f2c4c7aSAndroid Build Coastguard Worker 40*2f2c4c7aSAndroid Build Coastguard WorkerPREBUILT_CLANG_DIR = os.path.join("prebuilts", "clang", "host", "linux-x86") 41*2f2c4c7aSAndroid Build Coastguard Worker 42*2f2c4c7aSAndroid Build Coastguard WorkerPREBUILT_LLVM_COV_PATH_FORMAT = os.path.join( 43*2f2c4c7aSAndroid Build Coastguard Worker PREBUILT_CLANG_DIR, "clang-%s", "bin", "llvm-cov" 44*2f2c4c7aSAndroid Build Coastguard Worker) 45*2f2c4c7aSAndroid Build Coastguard Worker 46*2f2c4c7aSAndroid Build Coastguard WorkerPREBUILT_STABLE_LLVM_COV_PATH = os.path.join( 47*2f2c4c7aSAndroid Build Coastguard Worker PREBUILT_CLANG_DIR, "llvm-binutils-stable", "llvm-cov" 48*2f2c4c7aSAndroid Build Coastguard Worker) 49*2f2c4c7aSAndroid Build Coastguard Worker 50*2f2c4c7aSAndroid Build Coastguard WorkerEXCLUDED_FILES = [ 51*2f2c4c7aSAndroid Build Coastguard Worker "*/security/selinux/av_permissions.h", 52*2f2c4c7aSAndroid Build Coastguard Worker "*/security/selinux/flask.h", 53*2f2c4c7aSAndroid Build Coastguard Worker] 54*2f2c4c7aSAndroid Build Coastguard Worker 55*2f2c4c7aSAndroid Build Coastguard Worker 56*2f2c4c7aSAndroid Build Coastguard Workerdef create_llvm_gcov_sh( 57*2f2c4c7aSAndroid Build Coastguard Worker llvm_cov_filename: str, 58*2f2c4c7aSAndroid Build Coastguard Worker llvm_gcov_sh_filename: str, 59*2f2c4c7aSAndroid Build Coastguard Worker) -> None: 60*2f2c4c7aSAndroid Build Coastguard Worker """Create a shell script that is compatible with gcov. 61*2f2c4c7aSAndroid Build Coastguard Worker 62*2f2c4c7aSAndroid Build Coastguard Worker Args: 63*2f2c4c7aSAndroid Build Coastguard Worker llvm_cov_filename: The absolute path to llvm-cov. 64*2f2c4c7aSAndroid Build Coastguard Worker llvm_gcov_sh_filename: The path to the script to be created. 65*2f2c4c7aSAndroid Build Coastguard Worker """ 66*2f2c4c7aSAndroid Build Coastguard Worker file_path = pathlib.Path(llvm_gcov_sh_filename) 67*2f2c4c7aSAndroid Build Coastguard Worker file_path.parent.mkdir(parents=True, exist_ok=True) 68*2f2c4c7aSAndroid Build Coastguard Worker file_path.write_text(f'#!/bin/bash\nexec {llvm_cov_filename} gcov "$@"') 69*2f2c4c7aSAndroid Build Coastguard Worker os.chmod(llvm_gcov_sh_filename, 0o755) 70*2f2c4c7aSAndroid Build Coastguard Worker 71*2f2c4c7aSAndroid Build Coastguard Worker 72*2f2c4c7aSAndroid Build Coastguard Workerdef generate_lcov_tracefile( 73*2f2c4c7aSAndroid Build Coastguard Worker gcov_dir: str, 74*2f2c4c7aSAndroid Build Coastguard Worker kernel_source: str, 75*2f2c4c7aSAndroid Build Coastguard Worker gcov_filename: str, 76*2f2c4c7aSAndroid Build Coastguard Worker tracefile_filename: str, 77*2f2c4c7aSAndroid Build Coastguard Worker included_files: [], 78*2f2c4c7aSAndroid Build Coastguard Worker) -> None: 79*2f2c4c7aSAndroid Build Coastguard Worker """Call lcov to create tracefile based on gcov data files. 80*2f2c4c7aSAndroid Build Coastguard Worker 81*2f2c4c7aSAndroid Build Coastguard Worker Args: 82*2f2c4c7aSAndroid Build Coastguard Worker gcov_dir: Directory that contains the extracted gcov data files as retrieved 83*2f2c4c7aSAndroid Build Coastguard Worker from debugfs. 84*2f2c4c7aSAndroid Build Coastguard Worker kernel_source: Directory containing the kernel source same as what was used 85*2f2c4c7aSAndroid Build Coastguard Worker to build system under test. 86*2f2c4c7aSAndroid Build Coastguard Worker gcov_filename: The absolute path to gcov or a compatible script. 87*2f2c4c7aSAndroid Build Coastguard Worker tracefile_filename: The name of tracefile to create. 88*2f2c4c7aSAndroid Build Coastguard Worker included_files: List of source file pattern to include in tracefile. Can be 89*2f2c4c7aSAndroid Build Coastguard Worker empty in which case include allo source. 90*2f2c4c7aSAndroid Build Coastguard Worker """ 91*2f2c4c7aSAndroid Build Coastguard Worker exclude_args = " ".join([f'--exclude "{f}"' for f in EXCLUDED_FILES]) 92*2f2c4c7aSAndroid Build Coastguard Worker include_args = ( 93*2f2c4c7aSAndroid Build Coastguard Worker " ".join([f'--include "{f[0]}"' for f in included_files]) 94*2f2c4c7aSAndroid Build Coastguard Worker if included_files is not None 95*2f2c4c7aSAndroid Build Coastguard Worker else "" 96*2f2c4c7aSAndroid Build Coastguard Worker ) 97*2f2c4c7aSAndroid Build Coastguard Worker 98*2f2c4c7aSAndroid Build Coastguard Worker logging.info("Running lcov on %s", gcov_dir) 99*2f2c4c7aSAndroid Build Coastguard Worker lcov_cmd = ( 100*2f2c4c7aSAndroid Build Coastguard Worker f"{LCOV} -q " 101*2f2c4c7aSAndroid Build Coastguard Worker "--ignore-errors=source " 102*2f2c4c7aSAndroid Build Coastguard Worker "--rc branch_coverage=1 " 103*2f2c4c7aSAndroid Build Coastguard Worker f"-b {kernel_source} " 104*2f2c4c7aSAndroid Build Coastguard Worker f"-d {gcov_dir} " 105*2f2c4c7aSAndroid Build Coastguard Worker f"--gcov-tool {gcov_filename} " 106*2f2c4c7aSAndroid Build Coastguard Worker f"{exclude_args} " 107*2f2c4c7aSAndroid Build Coastguard Worker f"{include_args} " 108*2f2c4c7aSAndroid Build Coastguard Worker "--ignore-errors gcov,gcov,unused,unused " 109*2f2c4c7aSAndroid Build Coastguard Worker "--capture " 110*2f2c4c7aSAndroid Build Coastguard Worker f"-o {tracefile_filename} " 111*2f2c4c7aSAndroid Build Coastguard Worker ) 112*2f2c4c7aSAndroid Build Coastguard Worker os.system(lcov_cmd) 113*2f2c4c7aSAndroid Build Coastguard Worker 114*2f2c4c7aSAndroid Build Coastguard Worker 115*2f2c4c7aSAndroid Build Coastguard Workerdef update_symlink_from_mapping(filepath: str, prefix_mappings: {}) -> bool: 116*2f2c4c7aSAndroid Build Coastguard Worker """Update symbolic link based on prefix mappings. 117*2f2c4c7aSAndroid Build Coastguard Worker 118*2f2c4c7aSAndroid Build Coastguard Worker It will attempt to update the given symbolic link based on the prefix 119*2f2c4c7aSAndroid Build Coastguard Worker mappings. For every "from" prefix that matches replace with the new "to" 120*2f2c4c7aSAndroid Build Coastguard Worker value. If the resulting path doesn't exist, try the next. 121*2f2c4c7aSAndroid Build Coastguard Worker 122*2f2c4c7aSAndroid Build Coastguard Worker Args: 123*2f2c4c7aSAndroid Build Coastguard Worker filepath: Path of symbolic link to update. 124*2f2c4c7aSAndroid Build Coastguard Worker prefix_mappings: A multimap where the key is the "from" prefix to match, and 125*2f2c4c7aSAndroid Build Coastguard Worker the value is an array of "to" values to attempt to replace with. 126*2f2c4c7aSAndroid Build Coastguard Worker 127*2f2c4c7aSAndroid Build Coastguard Worker Returns: 128*2f2c4c7aSAndroid Build Coastguard Worker True or false depending on the whether symbolic link was successfully 129*2f2c4c7aSAndroid Build Coastguard Worker updated to a new path that exists. 130*2f2c4c7aSAndroid Build Coastguard Worker """ 131*2f2c4c7aSAndroid Build Coastguard Worker 132*2f2c4c7aSAndroid Build Coastguard Worker link_target = os.readlink(filepath) 133*2f2c4c7aSAndroid Build Coastguard Worker for old_prefix, new_prefix_list in prefix_mappings.items(): 134*2f2c4c7aSAndroid Build Coastguard Worker for new_prefix in new_prefix_list: 135*2f2c4c7aSAndroid Build Coastguard Worker if link_target.startswith(old_prefix): 136*2f2c4c7aSAndroid Build Coastguard Worker new_target = os.path.abspath( 137*2f2c4c7aSAndroid Build Coastguard Worker link_target.replace(old_prefix, new_prefix) 138*2f2c4c7aSAndroid Build Coastguard Worker ) 139*2f2c4c7aSAndroid Build Coastguard Worker if not os.path.exists(new_target): 140*2f2c4c7aSAndroid Build Coastguard Worker continue 141*2f2c4c7aSAndroid Build Coastguard Worker os.unlink(filepath) # Remove the old symbolic link 142*2f2c4c7aSAndroid Build Coastguard Worker os.symlink(new_target, filepath) # Create the updated link 143*2f2c4c7aSAndroid Build Coastguard Worker return True 144*2f2c4c7aSAndroid Build Coastguard Worker 145*2f2c4c7aSAndroid Build Coastguard Worker return False 146*2f2c4c7aSAndroid Build Coastguard Worker 147*2f2c4c7aSAndroid Build Coastguard Worker 148*2f2c4c7aSAndroid Build Coastguard Workerdef correct_symlinks_in_directory(directory: str, prefix_mappings: {}) -> None: 149*2f2c4c7aSAndroid Build Coastguard Worker """Recursively traverses a directory, updating symbolic links. 150*2f2c4c7aSAndroid Build Coastguard Worker 151*2f2c4c7aSAndroid Build Coastguard Worker Replaces 'old_prefix' in the link destination with 'new_prefix'. 152*2f2c4c7aSAndroid Build Coastguard Worker 153*2f2c4c7aSAndroid Build Coastguard Worker Args: 154*2f2c4c7aSAndroid Build Coastguard Worker directory: The root directory to traverse. 155*2f2c4c7aSAndroid Build Coastguard Worker prefix_mappings: Dictionary where the keys are the old prefixes and the 156*2f2c4c7aSAndroid Build Coastguard Worker values are the new prefixes 157*2f2c4c7aSAndroid Build Coastguard Worker """ 158*2f2c4c7aSAndroid Build Coastguard Worker 159*2f2c4c7aSAndroid Build Coastguard Worker logging.info("Fixing up symbolic links in %s", directory) 160*2f2c4c7aSAndroid Build Coastguard Worker 161*2f2c4c7aSAndroid Build Coastguard Worker for root, _, files in os.walk(directory): 162*2f2c4c7aSAndroid Build Coastguard Worker for filename in files: 163*2f2c4c7aSAndroid Build Coastguard Worker filepath = os.path.join(root, filename) 164*2f2c4c7aSAndroid Build Coastguard Worker if os.path.islink(filepath): 165*2f2c4c7aSAndroid Build Coastguard Worker if not update_symlink_from_mapping(filepath, prefix_mappings): 166*2f2c4c7aSAndroid Build Coastguard Worker logging.error( 167*2f2c4c7aSAndroid Build Coastguard Worker "Unable to update link at %s with any prefix mappings: %s", 168*2f2c4c7aSAndroid Build Coastguard Worker filepath, 169*2f2c4c7aSAndroid Build Coastguard Worker prefix_mappings, 170*2f2c4c7aSAndroid Build Coastguard Worker ) 171*2f2c4c7aSAndroid Build Coastguard Worker sys.exit(-1) 172*2f2c4c7aSAndroid Build Coastguard Worker 173*2f2c4c7aSAndroid Build Coastguard Worker 174*2f2c4c7aSAndroid Build Coastguard Workerdef find_most_recent_tarfile(path: str, pattern: str = "*.tar.gz") -> str: 175*2f2c4c7aSAndroid Build Coastguard Worker """Attempts to find a valid tar file given the location. 176*2f2c4c7aSAndroid Build Coastguard Worker 177*2f2c4c7aSAndroid Build Coastguard Worker If location is a directory finds the most recent tarfile or if location is a 178*2f2c4c7aSAndroid Build Coastguard Worker a valid tar file returns, if neither of these return None. 179*2f2c4c7aSAndroid Build Coastguard Worker 180*2f2c4c7aSAndroid Build Coastguard Worker Args: 181*2f2c4c7aSAndroid Build Coastguard Worker path (str): The path to either a tarfile or a directory. 182*2f2c4c7aSAndroid Build Coastguard Worker pattern (str, optional): Glob pattern for matching tarfiles. Defaults to 183*2f2c4c7aSAndroid Build Coastguard Worker "*.tar.gz". 184*2f2c4c7aSAndroid Build Coastguard Worker 185*2f2c4c7aSAndroid Build Coastguard Worker Returns: 186*2f2c4c7aSAndroid Build Coastguard Worker str: The path to the most recent tarfile found, or the original path 187*2f2c4c7aSAndroid Build Coastguard Worker if it was a valid tarfile. None if no matching tarfiles are found. 188*2f2c4c7aSAndroid Build Coastguard Worker """ 189*2f2c4c7aSAndroid Build Coastguard Worker 190*2f2c4c7aSAndroid Build Coastguard Worker if os.path.isfile(path): 191*2f2c4c7aSAndroid Build Coastguard Worker if tarfile.is_tarfile(path): 192*2f2c4c7aSAndroid Build Coastguard Worker return path # Path is a valid tarfile 193*2f2c4c7aSAndroid Build Coastguard Worker return None # Path is a file but not a tar file 194*2f2c4c7aSAndroid Build Coastguard Worker 195*2f2c4c7aSAndroid Build Coastguard Worker if os.path.isdir(path): 196*2f2c4c7aSAndroid Build Coastguard Worker results = [] 197*2f2c4c7aSAndroid Build Coastguard Worker for root, _, files in os.walk(path): 198*2f2c4c7aSAndroid Build Coastguard Worker for file in files: 199*2f2c4c7aSAndroid Build Coastguard Worker if fnmatch.fnmatch(file, pattern): 200*2f2c4c7aSAndroid Build Coastguard Worker full_path = os.path.join(root, file) 201*2f2c4c7aSAndroid Build Coastguard Worker results.append((full_path, os.path.getmtime(full_path))) 202*2f2c4c7aSAndroid Build Coastguard Worker 203*2f2c4c7aSAndroid Build Coastguard Worker if results: 204*2f2c4c7aSAndroid Build Coastguard Worker return max(results, key=lambda item: item[1])[ 205*2f2c4c7aSAndroid Build Coastguard Worker 0 206*2f2c4c7aSAndroid Build Coastguard Worker ] # Return path of the most recent one 207*2f2c4c7aSAndroid Build Coastguard Worker else: 208*2f2c4c7aSAndroid Build Coastguard Worker return None # No tarfiles found in the directory 209*2f2c4c7aSAndroid Build Coastguard Worker 210*2f2c4c7aSAndroid Build Coastguard Worker return None # Path is neither a tarfile nor a directory 211*2f2c4c7aSAndroid Build Coastguard Worker 212*2f2c4c7aSAndroid Build Coastguard Worker 213*2f2c4c7aSAndroid Build Coastguard Workerdef make_absolute(path: str, base_dir: str) -> str: 214*2f2c4c7aSAndroid Build Coastguard Worker if os.path.isabs(path): 215*2f2c4c7aSAndroid Build Coastguard Worker return path 216*2f2c4c7aSAndroid Build Coastguard Worker 217*2f2c4c7aSAndroid Build Coastguard Worker return os.path.join(base_dir, path) 218*2f2c4c7aSAndroid Build Coastguard Worker 219*2f2c4c7aSAndroid Build Coastguard Worker 220*2f2c4c7aSAndroid Build Coastguard Workerdef append_slash(path: str) -> str: 221*2f2c4c7aSAndroid Build Coastguard Worker if path is not None and path[-1] != "/": 222*2f2c4c7aSAndroid Build Coastguard Worker path += "/" 223*2f2c4c7aSAndroid Build Coastguard Worker return path 224*2f2c4c7aSAndroid Build Coastguard Worker 225*2f2c4c7aSAndroid Build Coastguard Worker 226*2f2c4c7aSAndroid Build Coastguard Workerdef update_multimap_from_json( 227*2f2c4c7aSAndroid Build Coastguard Worker json_file: str, base_dir: str, result_multimap: collections.defaultdict 228*2f2c4c7aSAndroid Build Coastguard Worker) -> None: 229*2f2c4c7aSAndroid Build Coastguard Worker """Reads 'to' and 'from' fields from a JSON file and updates a multimap. 230*2f2c4c7aSAndroid Build Coastguard Worker 231*2f2c4c7aSAndroid Build Coastguard Worker 'from' refers to a bazel sandbox directory. 232*2f2c4c7aSAndroid Build Coastguard Worker 'to' refers to the output directory of gcno files. 233*2f2c4c7aSAndroid Build Coastguard Worker The multimap is implemented as a dictionary of lists allowing multiple 'to' 234*2f2c4c7aSAndroid Build Coastguard Worker values for each 'from' key. 235*2f2c4c7aSAndroid Build Coastguard Worker 236*2f2c4c7aSAndroid Build Coastguard Worker Sample input: 237*2f2c4c7aSAndroid Build Coastguard Worker [ 238*2f2c4c7aSAndroid Build Coastguard Worker { 239*2f2c4c7aSAndroid Build Coastguard Worker "from": "/sandbox/1/execroot/_main/out/android-mainline/common", 240*2f2c4c7aSAndroid Build Coastguard Worker "to": "bazel-out/k8-fastbuild/bin/common/kernel_x86_64/kernel_x86_64_gcno" 241*2f2c4c7aSAndroid Build Coastguard Worker }, 242*2f2c4c7aSAndroid Build Coastguard Worker { 243*2f2c4c7aSAndroid Build Coastguard Worker "from": "/sandbox/2/execroot/_main/out/android-mainline/common", 244*2f2c4c7aSAndroid Build Coastguard Worker "to": "bazel-out/k8-fastbuild/bin/common-modules/virtual-device/virtual_device_x86_64/virtual_device_x86_64_gcno" 245*2f2c4c7aSAndroid Build Coastguard Worker } 246*2f2c4c7aSAndroid Build Coastguard Worker ] 247*2f2c4c7aSAndroid Build Coastguard Worker 248*2f2c4c7aSAndroid Build Coastguard Worker Args: 249*2f2c4c7aSAndroid Build Coastguard Worker json_file: The path to the JSON file. 250*2f2c4c7aSAndroid Build Coastguard Worker base_dir: Used if either of the 'to' or 'from' paths are relative to make 251*2f2c4c7aSAndroid Build Coastguard Worker them absolute by prepending this base_dir value. 252*2f2c4c7aSAndroid Build Coastguard Worker result_multimap: A multimap that is updated with every 'to' and 'from' 253*2f2c4c7aSAndroid Build Coastguard Worker found. 254*2f2c4c7aSAndroid Build Coastguard Worker 255*2f2c4c7aSAndroid Build Coastguard Worker Returns: 256*2f2c4c7aSAndroid Build Coastguard Worker The updated dictionary. 257*2f2c4c7aSAndroid Build Coastguard Worker """ 258*2f2c4c7aSAndroid Build Coastguard Worker with open(json_file, "r") as file: 259*2f2c4c7aSAndroid Build Coastguard Worker data = json.load(file) 260*2f2c4c7aSAndroid Build Coastguard Worker 261*2f2c4c7aSAndroid Build Coastguard Worker for item in data: 262*2f2c4c7aSAndroid Build Coastguard Worker to_value = append_slash(item.get("to")) 263*2f2c4c7aSAndroid Build Coastguard Worker from_value = append_slash(item.get("from")) 264*2f2c4c7aSAndroid Build Coastguard Worker if to_value and from_value: 265*2f2c4c7aSAndroid Build Coastguard Worker to_value = make_absolute(to_value, base_dir) 266*2f2c4c7aSAndroid Build Coastguard Worker from_value = make_absolute(from_value, base_dir) 267*2f2c4c7aSAndroid Build Coastguard Worker result_multimap[from_value].append(to_value) 268*2f2c4c7aSAndroid Build Coastguard Worker 269*2f2c4c7aSAndroid Build Coastguard Worker 270*2f2c4c7aSAndroid Build Coastguard Workerdef read_gcno_mapping_files( 271*2f2c4c7aSAndroid Build Coastguard Worker search_dir_pattern: str, 272*2f2c4c7aSAndroid Build Coastguard Worker base_dir: str, 273*2f2c4c7aSAndroid Build Coastguard Worker result_multimap: collections.defaultdict 274*2f2c4c7aSAndroid Build Coastguard Worker) -> None: 275*2f2c4c7aSAndroid Build Coastguard Worker """Search a directory for gcno_mapping.""" 276*2f2c4c7aSAndroid Build Coastguard Worker found = False 277*2f2c4c7aSAndroid Build Coastguard Worker pattern = os.path.join(search_dir_pattern, "gcno_mapping.*.json") 278*2f2c4c7aSAndroid Build Coastguard Worker for filepath in glob.iglob(pattern, recursive=False): 279*2f2c4c7aSAndroid Build Coastguard Worker found = True 280*2f2c4c7aSAndroid Build Coastguard Worker logging.info("Reading %s", filepath) 281*2f2c4c7aSAndroid Build Coastguard Worker update_multimap_from_json(filepath, base_dir, result_multimap) 282*2f2c4c7aSAndroid Build Coastguard Worker 283*2f2c4c7aSAndroid Build Coastguard Worker if not found: 284*2f2c4c7aSAndroid Build Coastguard Worker logging.error("No gcno_mapping in %s", search_dir_pattern) 285*2f2c4c7aSAndroid Build Coastguard Worker 286*2f2c4c7aSAndroid Build Coastguard Worker 287*2f2c4c7aSAndroid Build Coastguard Workerdef read_gcno_dir( 288*2f2c4c7aSAndroid Build Coastguard Worker gcno_dir: str, result_multimap: collections.defaultdict 289*2f2c4c7aSAndroid Build Coastguard Worker) -> None: 290*2f2c4c7aSAndroid Build Coastguard Worker """Read a directory containing gcno_mapping and gcno files.""" 291*2f2c4c7aSAndroid Build Coastguard Worker multimap = collections.defaultdict(list) 292*2f2c4c7aSAndroid Build Coastguard Worker read_gcno_mapping_files(gcno_dir, gcno_dir, multimap) 293*2f2c4c7aSAndroid Build Coastguard Worker 294*2f2c4c7aSAndroid Build Coastguard Worker to_value = append_slash(os.path.abspath(gcno_dir)) 295*2f2c4c7aSAndroid Build Coastguard Worker for from_value in multimap: 296*2f2c4c7aSAndroid Build Coastguard Worker result_multimap[from_value].append(to_value) 297*2f2c4c7aSAndroid Build Coastguard Worker 298*2f2c4c7aSAndroid Build Coastguard Worker 299*2f2c4c7aSAndroid Build Coastguard Workerdef get_testname_from_filename(file_path: str) -> str: 300*2f2c4c7aSAndroid Build Coastguard Worker filename = os.path.basename(file_path) 301*2f2c4c7aSAndroid Build Coastguard Worker if "_kernel_coverage" in filename: 302*2f2c4c7aSAndroid Build Coastguard Worker tmp = filename[: filename.find("_kernel_coverage")] 303*2f2c4c7aSAndroid Build Coastguard Worker testname = tmp[: tmp.rfind("_")] 304*2f2c4c7aSAndroid Build Coastguard Worker else: 305*2f2c4c7aSAndroid Build Coastguard Worker testname = filename[: filename.rfind("_")] 306*2f2c4c7aSAndroid Build Coastguard Worker return testname 307*2f2c4c7aSAndroid Build Coastguard Worker 308*2f2c4c7aSAndroid Build Coastguard Worker 309*2f2c4c7aSAndroid Build Coastguard Workerdef unpack_gcov_tar(file_path: str, output_dir: str) -> str: 310*2f2c4c7aSAndroid Build Coastguard Worker """Unpack the tar file into the specified directory. 311*2f2c4c7aSAndroid Build Coastguard Worker 312*2f2c4c7aSAndroid Build Coastguard Worker Args: 313*2f2c4c7aSAndroid Build Coastguard Worker file_path: The path of the tar file to be unpacked. 314*2f2c4c7aSAndroid Build Coastguard Worker output_dir: The root directory where the unpacked folder will reside. 315*2f2c4c7aSAndroid Build Coastguard Worker 316*2f2c4c7aSAndroid Build Coastguard Worker Returns: 317*2f2c4c7aSAndroid Build Coastguard Worker The path of extracted data. 318*2f2c4c7aSAndroid Build Coastguard Worker """ 319*2f2c4c7aSAndroid Build Coastguard Worker 320*2f2c4c7aSAndroid Build Coastguard Worker testname = get_testname_from_filename(file_path) 321*2f2c4c7aSAndroid Build Coastguard Worker logging.info( 322*2f2c4c7aSAndroid Build Coastguard Worker "Unpacking %s for test %s...", os.path.basename(file_path), testname 323*2f2c4c7aSAndroid Build Coastguard Worker ) 324*2f2c4c7aSAndroid Build Coastguard Worker 325*2f2c4c7aSAndroid Build Coastguard Worker test_dest_dir = os.path.join(output_dir, testname) 326*2f2c4c7aSAndroid Build Coastguard Worker if os.path.exists(test_dest_dir): 327*2f2c4c7aSAndroid Build Coastguard Worker shutil.rmtree(test_dest_dir) 328*2f2c4c7aSAndroid Build Coastguard Worker os.makedirs(test_dest_dir) 329*2f2c4c7aSAndroid Build Coastguard Worker shutil.unpack_archive(file_path, test_dest_dir, "tar") 330*2f2c4c7aSAndroid Build Coastguard Worker return test_dest_dir 331*2f2c4c7aSAndroid Build Coastguard Worker 332*2f2c4c7aSAndroid Build Coastguard Worker 333*2f2c4c7aSAndroid Build Coastguard Workerdef get_parent_path(path: str, levels_up: int) -> str: 334*2f2c4c7aSAndroid Build Coastguard Worker """Goes up a specified number of levels from a given path. 335*2f2c4c7aSAndroid Build Coastguard Worker 336*2f2c4c7aSAndroid Build Coastguard Worker Args: 337*2f2c4c7aSAndroid Build Coastguard Worker path: The path to find desired ancestor. 338*2f2c4c7aSAndroid Build Coastguard Worker levels_up: The number of levels up to go. 339*2f2c4c7aSAndroid Build Coastguard Worker 340*2f2c4c7aSAndroid Build Coastguard Worker Returns: 341*2f2c4c7aSAndroid Build Coastguard Worker The desired ancestor of the given path. 342*2f2c4c7aSAndroid Build Coastguard Worker """ 343*2f2c4c7aSAndroid Build Coastguard Worker p = pathlib.Path(path) 344*2f2c4c7aSAndroid Build Coastguard Worker for _ in range(levels_up): 345*2f2c4c7aSAndroid Build Coastguard Worker p = p.parent 346*2f2c4c7aSAndroid Build Coastguard Worker return str(p) 347*2f2c4c7aSAndroid Build Coastguard Worker 348*2f2c4c7aSAndroid Build Coastguard Worker 349*2f2c4c7aSAndroid Build Coastguard Workerdef get_kernel_repo_dir() -> str: 350*2f2c4c7aSAndroid Build Coastguard Worker # Assume this script is in a kernel source tree: 351*2f2c4c7aSAndroid Build Coastguard Worker # kernel_repo/kernel/tests/tools/<this_script> 352*2f2c4c7aSAndroid Build Coastguard Worker return get_parent_path(os.path.abspath(__file__), 4) 353*2f2c4c7aSAndroid Build Coastguard Worker 354*2f2c4c7aSAndroid Build Coastguard Worker 355*2f2c4c7aSAndroid Build Coastguard Workerdef load_kernel_clang_version(repo_dir: str) -> str: 356*2f2c4c7aSAndroid Build Coastguard Worker """Load CLANG_VERSION from build.config.constants.""" 357*2f2c4c7aSAndroid Build Coastguard Worker config_path = os.path.join(repo_dir, BUILD_CONFIG_CONSTANTS_PATH) 358*2f2c4c7aSAndroid Build Coastguard Worker if not os.path.isfile(config_path): 359*2f2c4c7aSAndroid Build Coastguard Worker return "" 360*2f2c4c7aSAndroid Build Coastguard Worker clang_version = "" 361*2f2c4c7aSAndroid Build Coastguard Worker with open(config_path, "r") as config_file: 362*2f2c4c7aSAndroid Build Coastguard Worker for line in config_file: 363*2f2c4c7aSAndroid Build Coastguard Worker match = re.fullmatch(r"\s*CLANG_VERSION=(\S*)\s*", line) 364*2f2c4c7aSAndroid Build Coastguard Worker if match: 365*2f2c4c7aSAndroid Build Coastguard Worker clang_version = match.group(1) 366*2f2c4c7aSAndroid Build Coastguard Worker return clang_version 367*2f2c4c7aSAndroid Build Coastguard Worker 368*2f2c4c7aSAndroid Build Coastguard Worker 369*2f2c4c7aSAndroid Build Coastguard Workerclass Config: 370*2f2c4c7aSAndroid Build Coastguard Worker """The input and output paths of this script.""" 371*2f2c4c7aSAndroid Build Coastguard Worker 372*2f2c4c7aSAndroid Build Coastguard Worker def __init__(self, repo_dir: str, llvm_cov_path: str, tmp_dir: str): 373*2f2c4c7aSAndroid Build Coastguard Worker """Each argument can be empty.""" 374*2f2c4c7aSAndroid Build Coastguard Worker self._repo_dir = os.path.abspath(repo_dir) if repo_dir else None 375*2f2c4c7aSAndroid Build Coastguard Worker self._llvm_cov_path = ( 376*2f2c4c7aSAndroid Build Coastguard Worker os.path.abspath(llvm_cov_path) if llvm_cov_path else None 377*2f2c4c7aSAndroid Build Coastguard Worker ) 378*2f2c4c7aSAndroid Build Coastguard Worker self._tmp_dir = os.path.abspath(tmp_dir) if tmp_dir else None 379*2f2c4c7aSAndroid Build Coastguard Worker self._repo_out_dir = None 380*2f2c4c7aSAndroid Build Coastguard Worker 381*2f2c4c7aSAndroid Build Coastguard Worker @property 382*2f2c4c7aSAndroid Build Coastguard Worker def repo_dir(self) -> str: 383*2f2c4c7aSAndroid Build Coastguard Worker if not self._repo_dir: 384*2f2c4c7aSAndroid Build Coastguard Worker self._repo_dir = get_kernel_repo_dir() 385*2f2c4c7aSAndroid Build Coastguard Worker return self._repo_dir 386*2f2c4c7aSAndroid Build Coastguard Worker 387*2f2c4c7aSAndroid Build Coastguard Worker def _get_repo_path(self, rel_path: str) -> str: 388*2f2c4c7aSAndroid Build Coastguard Worker repo_path = os.path.join(self.repo_dir, rel_path) 389*2f2c4c7aSAndroid Build Coastguard Worker if not os.path.exists(repo_path): 390*2f2c4c7aSAndroid Build Coastguard Worker logging.error( 391*2f2c4c7aSAndroid Build Coastguard Worker "%s does not exist. If this script is not in the source directory," 392*2f2c4c7aSAndroid Build Coastguard Worker " specify --repo-dir. If you do not have full kernel source," 393*2f2c4c7aSAndroid Build Coastguard Worker " specify --llvm-cov, --gcno-dir, and --tmp-dir.", 394*2f2c4c7aSAndroid Build Coastguard Worker repo_path, 395*2f2c4c7aSAndroid Build Coastguard Worker ) 396*2f2c4c7aSAndroid Build Coastguard Worker sys.exit(-1) 397*2f2c4c7aSAndroid Build Coastguard Worker return repo_path 398*2f2c4c7aSAndroid Build Coastguard Worker 399*2f2c4c7aSAndroid Build Coastguard Worker @property 400*2f2c4c7aSAndroid Build Coastguard Worker def llvm_cov_path(self) -> str: 401*2f2c4c7aSAndroid Build Coastguard Worker if not self._llvm_cov_path: 402*2f2c4c7aSAndroid Build Coastguard Worker # Load the clang version in kernel repo, 403*2f2c4c7aSAndroid Build Coastguard Worker # or use the stable version in platform repo. 404*2f2c4c7aSAndroid Build Coastguard Worker clang_version = load_kernel_clang_version(self.repo_dir) 405*2f2c4c7aSAndroid Build Coastguard Worker self._llvm_cov_path = self._get_repo_path( 406*2f2c4c7aSAndroid Build Coastguard Worker PREBUILT_LLVM_COV_PATH_FORMAT % clang_version if clang_version else 407*2f2c4c7aSAndroid Build Coastguard Worker PREBUILT_STABLE_LLVM_COV_PATH 408*2f2c4c7aSAndroid Build Coastguard Worker ) 409*2f2c4c7aSAndroid Build Coastguard Worker return self._llvm_cov_path 410*2f2c4c7aSAndroid Build Coastguard Worker 411*2f2c4c7aSAndroid Build Coastguard Worker @property 412*2f2c4c7aSAndroid Build Coastguard Worker def repo_out_dir(self) -> str: 413*2f2c4c7aSAndroid Build Coastguard Worker if not self._repo_out_dir: 414*2f2c4c7aSAndroid Build Coastguard Worker self._repo_out_dir = self._get_repo_path("out") 415*2f2c4c7aSAndroid Build Coastguard Worker return self._repo_out_dir 416*2f2c4c7aSAndroid Build Coastguard Worker 417*2f2c4c7aSAndroid Build Coastguard Worker @property 418*2f2c4c7aSAndroid Build Coastguard Worker def tmp_dir(self) -> str: 419*2f2c4c7aSAndroid Build Coastguard Worker if not self._tmp_dir: 420*2f2c4c7aSAndroid Build Coastguard Worker # Temporary directory does not have to exist. 421*2f2c4c7aSAndroid Build Coastguard Worker self._tmp_dir = os.path.join(self.repo_dir, OUTPUT_COV_DIR) 422*2f2c4c7aSAndroid Build Coastguard Worker return self._tmp_dir 423*2f2c4c7aSAndroid Build Coastguard Worker 424*2f2c4c7aSAndroid Build Coastguard Worker @property 425*2f2c4c7aSAndroid Build Coastguard Worker def llvm_gcov_sh_path(self) -> str: 426*2f2c4c7aSAndroid Build Coastguard Worker return os.path.join(self.tmp_dir, "tmp", "llvm-gcov.sh") 427*2f2c4c7aSAndroid Build Coastguard Worker 428*2f2c4c7aSAndroid Build Coastguard Worker 429*2f2c4c7aSAndroid Build Coastguard Workerdef main() -> None: 430*2f2c4c7aSAndroid Build Coastguard Worker arg_parser = argparse.ArgumentParser( 431*2f2c4c7aSAndroid Build Coastguard Worker description="Generate lcov tracefiles from gcov file dumps" 432*2f2c4c7aSAndroid Build Coastguard Worker ) 433*2f2c4c7aSAndroid Build Coastguard Worker 434*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 435*2f2c4c7aSAndroid Build Coastguard Worker "-t", 436*2f2c4c7aSAndroid Build Coastguard Worker dest="tar_location", 437*2f2c4c7aSAndroid Build Coastguard Worker required=True, 438*2f2c4c7aSAndroid Build Coastguard Worker help=( 439*2f2c4c7aSAndroid Build Coastguard Worker "Either a path to a gcov tar file or a directory that contains gcov" 440*2f2c4c7aSAndroid Build Coastguard Worker " tar file(s). The gcov tar file is expected to be created from" 441*2f2c4c7aSAndroid Build Coastguard Worker " Tradefed. If a directory is used, will search the entire directory" 442*2f2c4c7aSAndroid Build Coastguard Worker " for files matching *_kernel_coverage*.tar.gz and select the most" 443*2f2c4c7aSAndroid Build Coastguard Worker " recent one." 444*2f2c4c7aSAndroid Build Coastguard Worker ), 445*2f2c4c7aSAndroid Build Coastguard Worker ) 446*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 447*2f2c4c7aSAndroid Build Coastguard Worker "-o", 448*2f2c4c7aSAndroid Build Coastguard Worker dest="out_file", 449*2f2c4c7aSAndroid Build Coastguard Worker required=False, 450*2f2c4c7aSAndroid Build Coastguard Worker help="Name of output tracefile generated. Default: cov.info", 451*2f2c4c7aSAndroid Build Coastguard Worker default="cov.info", 452*2f2c4c7aSAndroid Build Coastguard Worker ) 453*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 454*2f2c4c7aSAndroid Build Coastguard Worker "--include", 455*2f2c4c7aSAndroid Build Coastguard Worker action="append", 456*2f2c4c7aSAndroid Build Coastguard Worker nargs=1, 457*2f2c4c7aSAndroid Build Coastguard Worker required=False, 458*2f2c4c7aSAndroid Build Coastguard Worker help=( 459*2f2c4c7aSAndroid Build Coastguard Worker "File pattern of source file(s) to include in generated tracefile." 460*2f2c4c7aSAndroid Build Coastguard Worker " Multiple patterns can be specified by using multiple --include" 461*2f2c4c7aSAndroid Build Coastguard Worker " command line switches. If no includes are specified all source is" 462*2f2c4c7aSAndroid Build Coastguard Worker " included." 463*2f2c4c7aSAndroid Build Coastguard Worker ), 464*2f2c4c7aSAndroid Build Coastguard Worker ) 465*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 466*2f2c4c7aSAndroid Build Coastguard Worker "--repo-dir", 467*2f2c4c7aSAndroid Build Coastguard Worker required=False, 468*2f2c4c7aSAndroid Build Coastguard Worker help="Root directory of kernel source" 469*2f2c4c7aSAndroid Build Coastguard Worker ) 470*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 471*2f2c4c7aSAndroid Build Coastguard Worker "--dist-dir", 472*2f2c4c7aSAndroid Build Coastguard Worker dest="dist_dirs", 473*2f2c4c7aSAndroid Build Coastguard Worker action="append", 474*2f2c4c7aSAndroid Build Coastguard Worker default=[], 475*2f2c4c7aSAndroid Build Coastguard Worker required=False, 476*2f2c4c7aSAndroid Build Coastguard Worker help="Dist directory containing gcno mapping files" 477*2f2c4c7aSAndroid Build Coastguard Worker ) 478*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 479*2f2c4c7aSAndroid Build Coastguard Worker "--gcno-dir", 480*2f2c4c7aSAndroid Build Coastguard Worker dest="gcno_dirs", 481*2f2c4c7aSAndroid Build Coastguard Worker action="append", 482*2f2c4c7aSAndroid Build Coastguard Worker default=[], 483*2f2c4c7aSAndroid Build Coastguard Worker required=False, 484*2f2c4c7aSAndroid Build Coastguard Worker help="Path to an extracted .gcno.tar.gz" 485*2f2c4c7aSAndroid Build Coastguard Worker ) 486*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 487*2f2c4c7aSAndroid Build Coastguard Worker "--llvm-cov", 488*2f2c4c7aSAndroid Build Coastguard Worker required=False, 489*2f2c4c7aSAndroid Build Coastguard Worker help=( 490*2f2c4c7aSAndroid Build Coastguard Worker "Path to llvm-cov. Default: " 491*2f2c4c7aSAndroid Build Coastguard Worker + os.path.join("<repo_dir>", PREBUILT_LLVM_COV_PATH_FORMAT % "*") 492*2f2c4c7aSAndroid Build Coastguard Worker + " or " + os.path.join("<repo_dir>", PREBUILT_STABLE_LLVM_COV_PATH) 493*2f2c4c7aSAndroid Build Coastguard Worker ) 494*2f2c4c7aSAndroid Build Coastguard Worker ) 495*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 496*2f2c4c7aSAndroid Build Coastguard Worker "--tmp-dir", 497*2f2c4c7aSAndroid Build Coastguard Worker required=False, 498*2f2c4c7aSAndroid Build Coastguard Worker help=( 499*2f2c4c7aSAndroid Build Coastguard Worker "Path to the directory where the temporary files are created." 500*2f2c4c7aSAndroid Build Coastguard Worker " Default: " + os.path.join("<repo_dir>", OUTPUT_COV_DIR) 501*2f2c4c7aSAndroid Build Coastguard Worker ) 502*2f2c4c7aSAndroid Build Coastguard Worker ) 503*2f2c4c7aSAndroid Build Coastguard Worker arg_parser.add_argument( 504*2f2c4c7aSAndroid Build Coastguard Worker "--verbose", 505*2f2c4c7aSAndroid Build Coastguard Worker action="store_true", 506*2f2c4c7aSAndroid Build Coastguard Worker default=False, 507*2f2c4c7aSAndroid Build Coastguard Worker help="Enable verbose logging", 508*2f2c4c7aSAndroid Build Coastguard Worker ) 509*2f2c4c7aSAndroid Build Coastguard Worker 510*2f2c4c7aSAndroid Build Coastguard Worker args = arg_parser.parse_args() 511*2f2c4c7aSAndroid Build Coastguard Worker 512*2f2c4c7aSAndroid Build Coastguard Worker if args.verbose: 513*2f2c4c7aSAndroid Build Coastguard Worker logging.basicConfig(level=logging.DEBUG) 514*2f2c4c7aSAndroid Build Coastguard Worker else: 515*2f2c4c7aSAndroid Build Coastguard Worker logging.basicConfig(level=logging.WARNING) 516*2f2c4c7aSAndroid Build Coastguard Worker 517*2f2c4c7aSAndroid Build Coastguard Worker if shutil.which(LCOV) is None: 518*2f2c4c7aSAndroid Build Coastguard Worker logging.error( 519*2f2c4c7aSAndroid Build Coastguard Worker "%s is not found and is required for this script. Please install from:", 520*2f2c4c7aSAndroid Build Coastguard Worker LCOV, 521*2f2c4c7aSAndroid Build Coastguard Worker ) 522*2f2c4c7aSAndroid Build Coastguard Worker logging.critical(" https://github.com/linux-test-project/lcov") 523*2f2c4c7aSAndroid Build Coastguard Worker sys.exit(-1) 524*2f2c4c7aSAndroid Build Coastguard Worker 525*2f2c4c7aSAndroid Build Coastguard Worker if args.repo_dir and not os.path.isdir(args.repo_dir): 526*2f2c4c7aSAndroid Build Coastguard Worker logging.error("%s is not a directory.", args.repo_dir) 527*2f2c4c7aSAndroid Build Coastguard Worker sys.exit(-1) 528*2f2c4c7aSAndroid Build Coastguard Worker 529*2f2c4c7aSAndroid Build Coastguard Worker if args.llvm_cov and not os.path.isfile(args.llvm_cov): 530*2f2c4c7aSAndroid Build Coastguard Worker logging.error("%s is not a file.", args.llvm_cov) 531*2f2c4c7aSAndroid Build Coastguard Worker sys.exit(-1) 532*2f2c4c7aSAndroid Build Coastguard Worker 533*2f2c4c7aSAndroid Build Coastguard Worker for gcno_dir in args.gcno_dirs + args.dist_dirs: 534*2f2c4c7aSAndroid Build Coastguard Worker if not os.path.isdir(gcno_dir): 535*2f2c4c7aSAndroid Build Coastguard Worker logging.error("%s is not a directory.", gcno_dir) 536*2f2c4c7aSAndroid Build Coastguard Worker sys.exit(-1) 537*2f2c4c7aSAndroid Build Coastguard Worker 538*2f2c4c7aSAndroid Build Coastguard Worker config = Config(args.repo_dir, args.llvm_cov, args.tmp_dir) 539*2f2c4c7aSAndroid Build Coastguard Worker 540*2f2c4c7aSAndroid Build Coastguard Worker gcno_mappings = collections.defaultdict(list) 541*2f2c4c7aSAndroid Build Coastguard Worker if not args.gcno_dirs and not args.dist_dirs: 542*2f2c4c7aSAndroid Build Coastguard Worker dist_dir_pattern = os.path.join(config.repo_out_dir, "**", "dist") 543*2f2c4c7aSAndroid Build Coastguard Worker read_gcno_mapping_files(dist_dir_pattern, config.repo_dir, gcno_mappings) 544*2f2c4c7aSAndroid Build Coastguard Worker 545*2f2c4c7aSAndroid Build Coastguard Worker for dist_dir in args.dist_dirs: 546*2f2c4c7aSAndroid Build Coastguard Worker read_gcno_mapping_files(dist_dir, config.repo_dir, gcno_mappings) 547*2f2c4c7aSAndroid Build Coastguard Worker 548*2f2c4c7aSAndroid Build Coastguard Worker for gcno_dir in args.gcno_dirs: 549*2f2c4c7aSAndroid Build Coastguard Worker read_gcno_dir(gcno_dir, gcno_mappings) 550*2f2c4c7aSAndroid Build Coastguard Worker 551*2f2c4c7aSAndroid Build Coastguard Worker if not gcno_mappings: 552*2f2c4c7aSAndroid Build Coastguard Worker # read_gcno_mapping_files prints the error messages 553*2f2c4c7aSAndroid Build Coastguard Worker sys.exit(-1) 554*2f2c4c7aSAndroid Build Coastguard Worker 555*2f2c4c7aSAndroid Build Coastguard Worker tar_file = find_most_recent_tarfile( 556*2f2c4c7aSAndroid Build Coastguard Worker args.tar_location, pattern="*kernel_coverage_*.tar.gz" 557*2f2c4c7aSAndroid Build Coastguard Worker ) 558*2f2c4c7aSAndroid Build Coastguard Worker if tar_file is None: 559*2f2c4c7aSAndroid Build Coastguard Worker logging.error("Unable to find a gcov tar under %s", args.tar_location) 560*2f2c4c7aSAndroid Build Coastguard Worker sys.exit(-1) 561*2f2c4c7aSAndroid Build Coastguard Worker 562*2f2c4c7aSAndroid Build Coastguard Worker gcov_dir = unpack_gcov_tar(tar_file, config.tmp_dir) 563*2f2c4c7aSAndroid Build Coastguard Worker correct_symlinks_in_directory(gcov_dir, gcno_mappings) 564*2f2c4c7aSAndroid Build Coastguard Worker 565*2f2c4c7aSAndroid Build Coastguard Worker create_llvm_gcov_sh( 566*2f2c4c7aSAndroid Build Coastguard Worker config.llvm_cov_path, 567*2f2c4c7aSAndroid Build Coastguard Worker config.llvm_gcov_sh_path, 568*2f2c4c7aSAndroid Build Coastguard Worker ) 569*2f2c4c7aSAndroid Build Coastguard Worker 570*2f2c4c7aSAndroid Build Coastguard Worker generate_lcov_tracefile( 571*2f2c4c7aSAndroid Build Coastguard Worker gcov_dir, 572*2f2c4c7aSAndroid Build Coastguard Worker config.repo_dir, 573*2f2c4c7aSAndroid Build Coastguard Worker config.llvm_gcov_sh_path, 574*2f2c4c7aSAndroid Build Coastguard Worker args.out_file, 575*2f2c4c7aSAndroid Build Coastguard Worker args.include, 576*2f2c4c7aSAndroid Build Coastguard Worker ) 577*2f2c4c7aSAndroid Build Coastguard Worker 578*2f2c4c7aSAndroid Build Coastguard Worker 579*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__": 580*2f2c4c7aSAndroid Build Coastguard Worker main() 581