1#!/bin/bash 2# Copyright 2023 The gRPC Authors 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16# This tool builds and runs a fuzzer target and generates coverage report under 17# /tmp. 18# 19# Example: 20# Run fuzzer with existing corpus (no fuzzing): 21# $ ./tools/fuzzing/generate_coverage_report.sh //test/core/end2end/fuzzers:api_fuzzer test/core/end2end/fuzzers/api_fuzzer_corpus/* 22# 23# Run with fuzzing: 24# $ ./tools/fuzzing/generate_coverage_report.sh //test/core/end2end/fuzzers:api_fuzzer -max_total_time=10 test/core/end2end/fuzzers/api_fuzzer_corpus 25# 26# Note that if a crash happened during fuzzing, the coverage data will not be dumped. 27# See https://github.com/google/fuzzing/issues/41#issuecomment-1027653690 for workaround. 28 29err() { 30 echo "$*" >&2 31} 32 33if [[ -z "$1" ]]; then 34 err "target not specified" 35 exit 1 36fi 37 38RANDOM=$(date +%s) 39FILENAME="${RANDOM}" 40 41export LLVM_PROFILE_FILE=/tmp/"${FILENAME}".profraw 42OUTPUT_BASE=$(bazel info output_base) 43MIDDLE="execroot/com_github_grpc_grpc/bazel-out/k8-dbg/bin" 44 45CLANG_MAJOR_VERSION=$(clang --version | grep version | sed -r 's/.*version ([^\.]+).*/\1/') 46LLVM_PROFDATA="llvm-profdata-${CLANG_MAJOR_VERSION}" 47LLVM_COV="llvm-cov-${CLANG_MAJOR_VERSION}" 48 49which "${LLVM_PROFDATA}" 50if (( $? != 0 )); then 51 err "${LLVM_PROFDATA} not found" 52 exit 1 53fi 54 55TARGET=$(bazel query "$1") 56TARGET_BINARY_PATH="${OUTPUT_BASE}/${MIDDLE}/$(echo ${TARGET:2} | sed 's/:/\//')" 57 58# Build: 59bazel build --dynamic_mode=off --config=dbg --config=fuzzer_asan --config=coverage "${TARGET}" 60# Run: 61"${TARGET_BINARY_PATH}" ${@:2} 62 63if [[ ! -e "${LLVM_PROFILE_FILE}" ]]; then 64 err "Profile file ${LLVM_PROFILE_FILE} not created" 65 exit 1 66fi 67 68# Create coverage report: 69"${LLVM_PROFDATA}" merge -sparse "${LLVM_PROFILE_FILE}" -o /tmp/"${FILENAME}".profdata 70"${LLVM_COV}" report "${TARGET_BINARY_PATH}" --format=text --instr-profile=/tmp/"${FILENAME}".profdata > /tmp/"${FILENAME}".cov 71 72if (( $? == 0 )); then 73 echo "Coverage summary report created: /tmp/${FILENAME}.cov" 74 echo "Merged profile data file: /tmp/${FILENAME}.profdata" 75 echo "Raw profile data file: /tmp/${FILENAME}.profraw" 76 echo "There are other ways to explore the data, see https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#creating-coverage-reports" 77else 78 err "Something went wrong" 79 exit 1 80fi 81