qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

scripts/run-coverity-scan: Script to run Coverity Scan build

Add a new script to automate the process of running the Coverity
Scan build tools and uploading the resulting tarball to the
website.

This is intended eventually to be driven from Travis,
but it can be run locally, if you are a maintainer of the
QEMU project on the Coverity Scan website and have the secret
upload token.

The script must be run on a Fedora 30 system. Support for using a
Docker container is added in a following commit.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20200319193323.2038-6-peter.maydell@linaro.org

+316
+5
MAINTAINERS
··· 2038 2038 S: Supported 2039 2039 F: scripts/coverity-model.c 2040 2040 2041 + Coverity Scan integration 2042 + M: Peter Maydell <peter.maydell@linaro.org> 2043 + S: Maintained 2044 + F: scripts/coverity-scan/ 2045 + 2041 2046 Device Tree 2042 2047 M: Alistair Francis <alistair.francis@wdc.com> 2043 2048 R: David Gibson <david@gibson.dropbear.id.au>
+311
scripts/coverity-scan/run-coverity-scan
··· 1 + #!/bin/sh -e 2 + 3 + # Upload a created tarball to Coverity Scan, as per 4 + # https://scan.coverity.com/projects/qemu/builds/new 5 + 6 + # This work is licensed under the terms of the GNU GPL version 2, 7 + # or (at your option) any later version. 8 + # See the COPYING file in the top-level directory. 9 + # 10 + # Copyright (c) 2017-2020 Linaro Limited 11 + # Written by Peter Maydell 12 + 13 + # Note that this script will automatically download and 14 + # run the (closed-source) coverity build tools, so don't 15 + # use it if you don't trust them! 16 + 17 + # This script assumes that you're running it from a QEMU source 18 + # tree, and that tree is a fresh clean one, because we do an in-tree 19 + # build. (This is necessary so that the filenames that the Coverity 20 + # Scan server sees are relative paths that match up with the component 21 + # regular expressions it uses; an out-of-tree build won't work for this.) 22 + # The host machine should have as many of QEMU's dependencies 23 + # installed as possible, for maximum coverity coverage. 24 + 25 + # To do an upload you need to be a maintainer in the Coverity online 26 + # service, and you will need to know the "Coverity token", which is a 27 + # secret 8 digit hex string. You can find that from the web UI in the 28 + # project settings, if you have maintainer access there. 29 + 30 + # Command line options: 31 + # --dry-run : run the tools, but don't actually do the upload 32 + # --update-tools-only : update the cached copy of the tools, but don't run them 33 + # --tokenfile : file to read Coverity token from 34 + # --version ver : specify version being analyzed (default: ask git) 35 + # --description desc : specify description of this version (default: ask git) 36 + # --srcdir : QEMU source tree to analyze (default: current working dir) 37 + # --results-tarball : path to copy the results tarball to (default: don't 38 + # copy it anywhere, just upload it) 39 + # 40 + # User-specifiable environment variables: 41 + # COVERITY_TOKEN -- Coverity token 42 + # COVERITY_EMAIL -- the email address to use for uploads (default: 43 + # looks at your git user.email config) 44 + # COVERITY_BUILD_CMD -- make command (default: 'make -jN' where N is 45 + # number of CPUs as determined by 'nproc') 46 + # COVERITY_TOOL_BASE -- set to directory to put coverity tools 47 + # (default: /tmp/coverity-tools) 48 + # 49 + # You must specify the token, either by environment variable or by 50 + # putting it in a file and using --tokenfile. Everything else has 51 + # a reasonable default if this is run from a git tree. 52 + 53 + check_upload_permissions() { 54 + # Check whether we can do an upload to the server; will exit the script 55 + # with status 1 if the check failed (usually a bad token); 56 + # will exit the script with status 0 if the check indicated that we 57 + # can't upload yet (ie we are at quota) 58 + # Assumes that PROJTOKEN, PROJNAME and DRYRUN have been initialized. 59 + 60 + echo "Checking upload permissions..." 61 + 62 + if ! up_perm="$(wget https://scan.coverity.com/api/upload_permitted --post-data "token=$PROJTOKEN&project=$PROJNAME" -q -O -)"; then 63 + echo "Coverity Scan API access denied: bad token?" 64 + exit 1 65 + fi 66 + 67 + # Really up_perm is a JSON response with either 68 + # {upload_permitted:true} or {next_upload_permitted_at:<date>} 69 + # We do some hacky string parsing instead of properly parsing it. 70 + case "$up_perm" in 71 + *upload_permitted*true*) 72 + echo "Coverity Scan: upload permitted" 73 + ;; 74 + *next_upload_permitted_at*) 75 + if [ "$DRYRUN" = yes ]; then 76 + echo "Coverity Scan: upload quota reached, continuing dry run" 77 + else 78 + echo "Coverity Scan: upload quota reached; stopping here" 79 + # Exit success as this isn't a build error. 80 + exit 0 81 + fi 82 + ;; 83 + *) 84 + echo "Coverity Scan upload check: unexpected result $up_perm" 85 + exit 1 86 + ;; 87 + esac 88 + } 89 + 90 + 91 + update_coverity_tools () { 92 + # Check for whether we need to download the Coverity tools 93 + # (either because we don't have a copy, or because it's out of date) 94 + # Assumes that COVERITY_TOOL_BASE, PROJTOKEN and PROJNAME are set. 95 + 96 + mkdir -p "$COVERITY_TOOL_BASE" 97 + cd "$COVERITY_TOOL_BASE" 98 + 99 + echo "Checking for new version of coverity build tools..." 100 + wget https://scan.coverity.com/download/linux64 --post-data "token=$PROJTOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new 101 + 102 + if ! cmp -s coverity_tool.md5 coverity_tool.md5.new; then 103 + # out of date md5 or no md5: download new build tool 104 + # blow away the old build tool 105 + echo "Downloading coverity build tools..." 106 + rm -rf coverity_tool coverity_tool.tgz 107 + wget https://scan.coverity.com/download/linux64 --post-data "token=$PROJTOKEN&project=$PROJNAME" -O coverity_tool.tgz 108 + if ! (cat coverity_tool.md5.new; echo " coverity_tool.tgz") | md5sum -c --status; then 109 + echo "Downloaded tarball didn't match md5sum!" 110 + exit 1 111 + fi 112 + # extract the new one, keeping it corralled in a 'coverity_tool' directory 113 + echo "Unpacking coverity build tools..." 114 + mkdir -p coverity_tool 115 + cd coverity_tool 116 + tar xf ../coverity_tool.tgz 117 + cd .. 118 + mv coverity_tool.md5.new coverity_tool.md5 119 + fi 120 + 121 + rm -f coverity_tool.md5.new 122 + } 123 + 124 + 125 + # Check user-provided environment variables and arguments 126 + DRYRUN=no 127 + UPDATE_ONLY=no 128 + 129 + while [ "$#" -ge 1 ]; do 130 + case "$1" in 131 + --dry-run) 132 + shift 133 + DRYRUN=yes 134 + ;; 135 + --update-tools-only) 136 + shift 137 + UPDATE_ONLY=yes 138 + ;; 139 + --version) 140 + shift 141 + if [ $# -eq 0 ]; then 142 + echo "--version needs an argument" 143 + exit 1 144 + fi 145 + VERSION="$1" 146 + shift 147 + ;; 148 + --description) 149 + shift 150 + if [ $# -eq 0 ]; then 151 + echo "--description needs an argument" 152 + exit 1 153 + fi 154 + DESCRIPTION="$1" 155 + shift 156 + ;; 157 + --tokenfile) 158 + shift 159 + if [ $# -eq 0 ]; then 160 + echo "--tokenfile needs an argument" 161 + exit 1 162 + fi 163 + COVERITY_TOKEN="$(cat "$1")" 164 + shift 165 + ;; 166 + --srcdir) 167 + shift 168 + if [ $# -eq 0 ]; then 169 + echo "--srcdir needs an argument" 170 + exit 1 171 + fi 172 + SRCDIR="$1" 173 + shift 174 + ;; 175 + --results-tarball) 176 + shift 177 + if [ $# -eq 0 ]; then 178 + echo "--results-tarball needs an argument" 179 + exit 1 180 + fi 181 + RESULTSTARBALL="$1" 182 + shift 183 + ;; 184 + *) 185 + echo "Unexpected argument '$1'" 186 + exit 1 187 + ;; 188 + esac 189 + done 190 + 191 + if [ -z "$COVERITY_TOKEN" ]; then 192 + echo "COVERITY_TOKEN environment variable not set" 193 + exit 1 194 + fi 195 + 196 + if [ -z "$COVERITY_BUILD_CMD" ]; then 197 + NPROC=$(nproc) 198 + COVERITY_BUILD_CMD="make -j$NPROC" 199 + echo "COVERITY_BUILD_CMD: using default '$COVERITY_BUILD_CMD'" 200 + fi 201 + 202 + if [ -z "$COVERITY_TOOL_BASE" ]; then 203 + echo "COVERITY_TOOL_BASE: using default /tmp/coverity-tools" 204 + COVERITY_TOOL_BASE=/tmp/coverity-tools 205 + fi 206 + 207 + if [ -z "$SRCDIR" ]; then 208 + SRCDIR="$PWD" 209 + fi 210 + 211 + PROJTOKEN="$COVERITY_TOKEN" 212 + PROJNAME=QEMU 213 + TARBALL=cov-int.tar.xz 214 + 215 + 216 + if [ "$UPDATE_ONLY" = yes ]; then 217 + # Just do the tools update; we don't need to check whether 218 + # we are in a source tree or have upload rights for this, 219 + # so do it before some of the command line and source tree checks. 220 + update_coverity_tools 221 + exit 0 222 + fi 223 + 224 + cd "$SRCDIR" 225 + 226 + echo "Checking this is a QEMU source tree..." 227 + if ! [ -e "$SRCDIR/VERSION" ]; then 228 + echo "Not in a QEMU source tree?" 229 + exit 1 230 + fi 231 + 232 + # Fill in defaults used by the non-update-only process 233 + if [ -z "$VERSION" ]; then 234 + VERSION="$(git describe --always HEAD)" 235 + fi 236 + 237 + if [ -z "$DESCRIPTION" ]; then 238 + DESCRIPTION="$(git rev-parse HEAD)" 239 + fi 240 + 241 + if [ -z "$COVERITY_EMAIL" ]; then 242 + COVERITY_EMAIL="$(git config user.email)" 243 + fi 244 + 245 + check_upload_permissions 246 + 247 + update_coverity_tools 248 + 249 + TOOLBIN="$(cd "$COVERITY_TOOL_BASE" && echo $PWD/coverity_tool/cov-analysis-*/bin)" 250 + 251 + if ! test -x "$TOOLBIN/cov-build"; then 252 + echo "Couldn't find cov-build in the coverity build-tool directory??" 253 + exit 1 254 + fi 255 + 256 + export PATH="$TOOLBIN:$PATH" 257 + 258 + cd "$SRCDIR" 259 + 260 + echo "Doing make distclean..." 261 + make distclean 262 + 263 + echo "Configuring..." 264 + # We configure with a fixed set of enables here to ensure that we don't 265 + # accidentally reduce the scope of the analysis by doing the build on 266 + # the system that's missing a dependency that we need to build part of 267 + # the codebase. 268 + ./configure --disable-modules --enable-sdl --enable-gtk \ 269 + --enable-opengl --enable-vte --enable-gnutls \ 270 + --enable-nettle --enable-curses --enable-curl \ 271 + --audio-drv-list=oss,alsa,sdl,pa --enable-virtfs \ 272 + --enable-vnc --enable-vnc-sasl --enable-vnc-jpeg --enable-vnc-png \ 273 + --enable-xen --enable-brlapi \ 274 + --enable-linux-aio --enable-attr \ 275 + --enable-cap-ng --enable-trace-backends=log --enable-spice --enable-rbd \ 276 + --enable-xfsctl --enable-libusb --enable-usb-redir \ 277 + --enable-libiscsi --enable-libnfs --enable-seccomp \ 278 + --enable-tpm --enable-libssh --enable-lzo --enable-snappy --enable-bzip2 \ 279 + --enable-numa --enable-rdma --enable-smartcard --enable-virglrenderer \ 280 + --enable-mpath --enable-libxml2 --enable-glusterfs \ 281 + --enable-virtfs --enable-zstd 282 + 283 + echo "Making libqemustub.a..." 284 + make libqemustub.a 285 + 286 + echo "Running cov-build..." 287 + rm -rf cov-int 288 + mkdir cov-int 289 + cov-build --dir cov-int $COVERITY_BUILD_CMD 290 + 291 + echo "Creating results tarball..." 292 + tar cvf - cov-int | xz > "$TARBALL" 293 + 294 + if [ ! -z "$RESULTSTARBALL" ]; then 295 + echo "Copying results tarball to $RESULTSTARBALL..." 296 + cp "$TARBALL" "$RESULTSTARBALL" 297 + fi 298 + 299 + echo "Uploading results tarball..." 300 + 301 + if [ "$DRYRUN" = yes ]; then 302 + echo "Dry run only, not uploading $TARBALL" 303 + exit 0 304 + fi 305 + 306 + curl --form token="$PROJTOKEN" --form email="$COVERITY_EMAIL" \ 307 + --form file=@"$TARBALL" --form version="$VERSION" \ 308 + --form description="$DESCRIPTION" \ 309 + https://scan.coverity.com/builds?project="$PROJNAME" 310 + 311 + echo "Done."