Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package kcov for openSUSE:Factory checked in at 2023-04-30 16:08:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kcov (Old) and /work/SRC/openSUSE:Factory/.kcov.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kcov" Sun Apr 30 16:08:04 2023 rev:6 rq:1083736 version:41 Changes: -------- --- /work/SRC/openSUSE:Factory/kcov/kcov.changes 2022-09-30 17:58:46.865375158 +0200 +++ /work/SRC/openSUSE:Factory/.kcov.new.1533/kcov.changes 2023-04-30 16:08:16.092332797 +0200 @@ -1,0 +2,16 @@ +Mon Apr 24 12:39:15 UTC 2023 - Antoine Belvire <[email protected]> + +- Update to 41: + * Output the codecov file format. + * Fix handling of symlinks. + * Add support for RISC-V. + * Fix gcc-13 build. + * Correct the license for Debian. + * Add --cobertura-only output option. + * Fix build with binutils >= 2.39. + * Clear BFD state between files to avoid breakpoint trashing atomic + instructions. +- Remove kcov-40-binutils-2.39.patch: Fixed upstream. +- Add -lsframe, -lzstd to build flags: Fix linking. + +------------------------------------------------------------------- Old: ---- kcov-40-binutils-2.39.patch v40.tar.gz New: ---- v41.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kcov.spec ++++++ --- /var/tmp/diff_new_pack.4VZLWv/_old 2023-04-30 16:08:16.476335140 +0200 +++ /var/tmp/diff_new_pack.4VZLWv/_new 2023-04-30 16:08:16.480335164 +0200 @@ -1,7 +1,7 @@ # # spec file for package kcov # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: kcov -Version: 40 +Version: 41 Release: 0 Summary: Code coverage tool without special compilation options License: GPL-2.0-only @@ -25,8 +25,6 @@ URL: https://github.com/SimonKagstrom/kcov Source0: https://github.com/SimonKagstrom/kcov/archive/v%{version}.tar.gz Patch0: link_order.patch -# PATCH-FIX-UPSTREAM kcov-40-binutils-2.39.patch -- Fix build with binutils 2.39 (gh#SimonKagstrom#381, gh#SimonKagstrom!383) -Patch1: kcov-40-binutils-2.39.patch BuildRequires: binutils-devel BuildRequires: c++_compiler BuildRequires: cmake @@ -50,6 +48,9 @@ rm -frv external/ %build +%if 0%{?suse_version} > 1500 +export CFLAGS="%{optflags} -lsframe -lzstd" +%endif %cmake %cmake_build ++++++ v40.tar.gz -> v41.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/.github/workflows/ci.yml new/kcov-41/.github/workflows/ci.yml --- old/kcov-40/.github/workflows/ci.yml 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/.github/workflows/ci.yml 2023-02-23 13:55:55.000000000 +0100 @@ -61,13 +61,13 @@ sudo .github/workflows/ci-run-tests.sh build-freebsd: - runs-on: macos-10.15 + runs-on: macos-12 name: Build and test FreeBSD executable steps: - uses: actions/checkout@v2 - name: FreeBSD id: test - uses: vmactions/[email protected] + uses: vmactions/freebsd-vm@v0 with: usesh: true sync: rsync diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/.github/workflows/generic-build.sh new/kcov-41/.github/workflows/generic-build.sh --- old/kcov-40/.github/workflows/generic-build.sh 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/.github/workflows/generic-build.sh 2023-02-23 13:55:55.000000000 +0100 @@ -18,7 +18,7 @@ apt-get update apt-mark hold php* google* libobjc* libpq* libidn* postgresql* python3-httplib2 samba* >/dev/null apt-get upgrade -y - apt-get install -y binutils-dev libcurl4-openssl-dev libdw-dev libiberty-dev gcc g++ make cmake libssl-dev git python python3 $EXTRA_PACKAGES + apt-get install -y binutils-dev libcurl4-openssl-dev libdw-dev libiberty-dev gcc g++ make cmake libssl-dev git python3 $EXTRA_PACKAGES export PATH="${PATH}:${HOME}/kcov/bin" mkdir build build-tests cd build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/ChangeLog new/kcov-41/ChangeLog --- old/kcov-40/ChangeLog 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/ChangeLog 2023-02-23 13:55:55.000000000 +0100 @@ -1,4 +1,21 @@ +Kcov (41): + * Add support for RISC-V (rvalue) + + * Fix gcc-13 build (Sergei Trofimovich) + + * Correct the license for Debian (Rui Chen) + + * Add --cobertura-only output option + + * Fix build with binutils >= 2.39 (oreo639) + + * Clear BFD state between files to avoid breakpoint trashing atomic + instructions (Andy Caldwell) + + -- Simon Kagstrom <[email protected]>, Thu Feb 23 13:52:46 CET 2023 + Kcov (40): + * Make libbfd non-required to avoid GPLv3 -- Simon Kagstrom <[email protected]>, Sat Dec 18 09:25:21 CET 2021 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/INSTALL.md new/kcov-41/INSTALL.md --- old/kcov-40/INSTALL.md 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/INSTALL.md 2023-02-23 13:55:55.000000000 +0100 @@ -14,8 +14,11 @@ Ubuntu ------ -Install binutils-dev libcurl4-openssl-dev zlib1g-dev libdw-dev libiberty-dev +Install +``` + apt-get install binutils-dev libssl-dev libcurl4-openssl-dev zlib1g-dev libdw-dev libiberty-dev +``` Fedora / Centos / RHEL ---------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/README.md new/kcov-41/README.md --- old/kcov-40/README.md 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/README.md 2023-02-23 13:55:55.000000000 +0100 @@ -101,4 +101,4 @@ More information ---------------- kcov is written by Simon Kagstrom <[email protected]> and more -information can be found at [the web page](http://simonkagstrom.github.com/kcov/index.html) +information can be found at [the web page](http://simonkagstrom.github.io/kcov/index.html) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/debian/copyright new/kcov-41/debian/copyright --- old/kcov-40/debian/copyright 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/debian/copyright 2023-02-23 13:55:55.000000000 +0100 @@ -5,16 +5,16 @@ Files: * Copyright: <years> <put author's name and email here> <years> <likewise for another author> -License: GPL-3.0+ +License: GPL-2.0+ Files: debian/* Copyright: 2018 Paul Dreik <[email protected]> -License: GPL-3.0+ +License: GPL-2.0+ -License: GPL-3.0+ +License: GPL-2.0+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, @@ -26,7 +26,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. . On Debian systems, the complete text of the GNU General - Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". # Please also look if there are files or directories which have a # different copyright/license attached and list them here. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/doc/kcov.1 new/kcov-41/doc/kcov.1 --- old/kcov-40/doc/kcov.1 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/doc/kcov.1 2023-02-23 13:55:55.000000000 +0100 @@ -88,6 +88,11 @@ exit when the first process exits, i.e., honor the behavior of daemons. The default behavior is to return to the console when the last process exits. .TP +\fB\-\-cobertura\-only +Generate only cobertura output, as cov.xml, in the output directory. The intended usage is for e.g., +vscode coverage gutters, where the output directory can then be pointed to somewhere in the project +directory to get coverage with little droppings. +.TP \fB\-\-python\-parser\fP=\fIPARSER\fP Set the python parser to use for Python programs (the default is python). Can be used to run with Python 3 on systems where Python 2 is the default. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/CMakeLists.txt new/kcov-41/src/CMakeLists.txt --- old/kcov-40/src/CMakeLists.txt 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/CMakeLists.txt 2023-02-23 13:55:55.000000000 +0100 @@ -39,6 +39,8 @@ message (FATAL_ERROR "Could NOT find M") endif (M_LIBRARY) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + set (KCOV kcov) @@ -94,6 +96,7 @@ ) set (HAS_LIBBFD "0") +set (HAS_LIBBFD_DISASM_STYLED "0") if (CMAKE_TARGET_ARCHITECTURES STREQUAL "i386" OR CMAKE_TARGET_ARCHITECTURES STREQUAL "x86_64") if (LIBBFD_FOUND) @@ -106,6 +109,23 @@ ${LIBBFD_BFD_LIBRARY} ${LIBBFD_IBERTY_LIBRARY} ) + include(CheckCSourceCompiles) + set(CMAKE_REQUIRED_LIBRARIES ${DISASSEMBLER_LIBRARIES}) + check_c_source_compiles(" + #define PACKAGE + #define PACKAGE_VERSION + #include <stdio.h> + #include <dis-asm.h> + + int main(int argc, char **argv){ + struct disassemble_info info; + init_disassemble_info(&info, stdout, NULL, NULL); + return 0; + } + " TEST_LIBBFD_DISASM_STYLED) + if (TEST_LIBBFD_DISASM_STYLED) + set (HAS_LIBBFD_DISASM_STYLED "1") + endif (TEST_LIBBFD_DISASM_STYLED) endif (LIBBFD_FOUND) endif (CMAKE_TARGET_ARCHITECTURES STREQUAL "i386" OR CMAKE_TARGET_ARCHITECTURES STREQUAL "x86_64") @@ -221,6 +241,7 @@ source-file-cache.cc utils.cc writers/cobertura-writer.cc + writers/codecov-writer.cc writers/json-writer.cc ${coveralls_SRCS} writers/html-writer.cc @@ -283,7 +304,7 @@ set (KCOV_LIBRARY_PREFIX "/tmp") -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -g -Wall -D_GLIBCXX_USE_NANOSLEEP -DKCOV_LIBRARY_PREFIX=${KCOV_LIBRARY_PREFIX} -DKCOV_HAS_LIBBFD=${HAS_LIBBFD}") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -g -Wall -D_GLIBCXX_USE_NANOSLEEP -DKCOV_LIBRARY_PREFIX=${KCOV_LIBRARY_PREFIX} -DKCOV_HAS_LIBBFD=${HAS_LIBBFD} -DKCOV_LIBFD_DISASM_STYLED=${HAS_LIBBFD_DISASM_STYLED}") include_directories( include/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/configuration.cc new/kcov-41/src/configuration.cc --- old/kcov-40/src/configuration.cc 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/configuration.cc 2023-02-23 13:55:55.000000000 +0100 @@ -127,6 +127,7 @@ { "clang", no_argument, 0, 'c' }, { "configure", required_argument, 0, 'M' }, { "clean", no_argument, 0, 'E' }, + { "cobertura-only", no_argument, 0, 'o' }, { "exclude-pattern", required_argument, 0, 'x' }, { "include-pattern", required_argument, 0, 'i' }, { "exclude-path", required_argument, 0, 'X' }, @@ -177,7 +178,7 @@ */ for (lastArg = 1; lastArg < argc; lastArg++) { - if (IParserManager::getInstance().matchParser(argv[lastArg])) + if (IParserManager::getInstance().matchParser(get_real_path(argv[lastArg]))) break; bool found = false; @@ -288,6 +289,9 @@ setKey("output-interval", stoul(std::string(optarg))); break; + case 'o': + setKey("cobertura-only", 1); + break; case 'S': { if (!isInteger(std::string(optarg))) @@ -526,10 +530,17 @@ setKey("binary-path", tmp.first); binaryName = tmp.second; - setKey("target-directory", - fmt("%s/%s.%08zx", outDirectory.c_str(), binaryName.c_str(), - (size_t)hash_file(path))); - + if (!keyAsInt("cobertura-only")) + { + setKey("target-directory", + fmt("%s/%s.%08zx", outDirectory.c_str(), binaryName.c_str(), + (size_t)hash_file(path))); + } + else + { + // No directory structure if only cobertura is used + setKey("target-directory", outDirectory); + } if (keyAsInt("running-mode") == IConfiguration::MODE_REPORT_ONLY && !file_exists(keyAsString("target-directory"))) { @@ -626,6 +637,8 @@ setKey("patchelf-command", "patchelf"); setKey("coveralls-service-name", "travis-ci"); setKey("cobertura-full-paths", 0); + setKey("codecov-full-paths", 0); + setKey("cobertura-only", 0); } void setKey(const std::string &key, const std::string &val) @@ -664,7 +677,8 @@ { if (key == "low-limit" || key == "high-limit" || key == "bash-use-basic-parser" - || key == "cobertura-full-paths") + || key == "cobertura-full-paths" + || key == "codecov-full-paths") { if (!isInteger(value)) panic("Value for %s must be integer\n", key.c_str()); @@ -692,6 +706,8 @@ setKey(key, std::string(value)); else if (key == "cobertura-full-paths") setKey(key, stoul(std::string(value))); + else if (key == "codecov-full-paths") + setKey(key, stoul(std::string(value))); else panic("Unknown key %s\n", key.c_str()); } @@ -717,6 +733,7 @@ " found after the :\n" " --path-strip-level=num path levels to show for common paths (default: %d)\n" "\n" + " --cobertura-only Only produce cobertura output in the output dir\n" " --gcov use gcov parser instead of DWARF debugging info\n" " --clang use Clang Sanitizer-coverage parser\n" " --system-record perform full-system instrumentation\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/engines/ptrace.cc new/kcov-41/src/engines/ptrace.cc --- old/kcov-40/src/engines/ptrace.cc 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/engines/ptrace.cc 2023-02-23 13:55:55.000000000 +0100 @@ -50,6 +50,8 @@ unsigned long shift = 8 * offs; val = (old_data & ~(0xffffffffUL << shift)) | (0xd4200000UL << shift); +#elif defined(__riscv) + val = 0x00100073; /* ebreak */ // No width problem, prefer ebreak than c.ebreak for ISA w/o C extension. #else # error Unsupported architecture #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/engines/ptrace_linux.cc new/kcov-41/src/engines/ptrace_linux.cc --- old/kcov-40/src/engines/ptrace_linux.cc 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/engines/ptrace_linux.cc 2023-02-23 13:55:55.000000000 +0100 @@ -20,6 +20,7 @@ enum { i386_EIP = 12, x86_64_RIP = 16, ppc_NIP = 32, arm_PC = 15, aarch64_PC = 32, // See Linux arch/arm64/include/asm/ptrace.h + riscv_EPC = 0 }; static void arch_adjustPcAfterBreakpoint(unsigned long *regs); @@ -40,7 +41,7 @@ regs[i386_EIP]--; #elif defined(__x86_64__) regs[x86_64_RIP]--; -#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__) +#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__) || defined(__riscv) // Do nothing #else # error Unsupported architecture @@ -61,6 +62,8 @@ out = regs[aarch64_PC]; #elif defined(__powerpc__) out = regs[ppc_NIP]; +#elif defined(__riscv) + out = regs[riscv_EPC]; #else # error Unsupported architecture #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/include/collector.hh new/kcov-41/src/include/collector.hh --- old/kcov-40/src/include/collector.hh 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/include/collector.hh 2023-02-23 13:55:55.000000000 +0100 @@ -2,6 +2,8 @@ #include <string> +#include <stdint.h> + namespace kcov { class IFileParser; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/include/reporter.hh new/kcov-41/src/include/reporter.hh --- old/kcov-40/src/include/reporter.hh 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/include/reporter.hh 2023-02-23 13:55:55.000000000 +0100 @@ -3,6 +3,7 @@ #include <string> #include <stddef.h> +#include <stdint.h> namespace kcov { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/include/source-file-cache.hh new/kcov-41/src/include/source-file-cache.hh --- old/kcov-40/src/include/source-file-cache.hh 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/include/source-file-cache.hh 2023-02-23 13:55:55.000000000 +0100 @@ -3,6 +3,8 @@ #include <vector> #include <string> +#include <stdint.h> + namespace kcov { /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/main.cc new/kcov-41/src/main.cc --- old/kcov-40/src/main.cc 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/main.cc 2023-02-23 13:55:55.000000000 +0100 @@ -20,6 +20,7 @@ #include "merge-parser.hh" #include "engines/system-mode-file-format.hh" +#include "writers/codecov-writer.hh" #include "writers/html-writer.hh" #include "writers/json-writer.hh" #include "writers/coveralls-writer.hh" @@ -189,6 +190,8 @@ mergeReporter, base + "kcov-merged/sonarqube.xml"); IWriter &mergeCoverallsWriter = createCoverallsWriter(mergeParser, mergeReporter); + IWriter &mergeCodecovWriter = createCodecovWriter(mergeParser, mergeReporter, + base + "kcov-merged/codecov.json"); (void) mkdir(fmt("%s/kcov-merged", base.c_str()).c_str(), 0755); output.registerWriter(mergeParser); @@ -197,6 +200,7 @@ output.registerWriter(mergeCoberturaWriter); output.registerWriter(mergeSonarqubeWriter); output.registerWriter(mergeCoverallsWriter); + output.registerWriter(mergeCodecovWriter); output.start(); output.stop(); @@ -220,8 +224,9 @@ return 1; } - if (parser->getParserType() == "bash" || - parser->getParserType() == "python") + if ((parser->getParserType() == "bash" || + parser->getParserType() == "python") && + !conf.keyAsInt("cobertura-only")) { // Use the path as the hash for non-compiled languages conf.setKey("target-directory", @@ -256,7 +261,10 @@ filter); IReporter &mergeReporter = IReporter::create(mergeParser, mergeParser, basicFilter); - (void) mkdir(fmt("%s/kcov-merged", base.c_str()).c_str(), 0755); + if (!conf.keyAsInt("cobertura-only")) + { + (void) mkdir(fmt("%s/kcov-merged", base.c_str()).c_str(), 0755); + } // Register writers if (runningMode != IConfiguration::MODE_COLLECT_ONLY) @@ -269,6 +277,8 @@ out); IWriter &sonarqubeWriter = createSonarqubeWriter(*parser, reporter, out + "/sonarqube.xml"); + IWriter &codecovWriter = createCodecovWriter(*parser, reporter, + out + "/codecov.json"); IWriter &mergeHtmlWriter = createHtmlWriter(mergeParser, mergeReporter, base, base + "/kcov-merged", conf.keyAsString("merged-name"), @@ -279,30 +289,45 @@ mergeReporter, base + "kcov-merged"); IWriter &mergeSonarqubeWriter = createSonarqubeWriter(mergeParser, mergeReporter, base + "kcov-merged/sonarqube.xml"); + IWriter &mergeCodecovWriter = createCodecovWriter(mergeParser, + mergeReporter, base + "kcov-merged/codecov.json"); - // Multiple binaries? Register the merged mode stuff - if (countMetadata() > 0) + if (!conf.keyAsInt("cobertura-only")) { - output.registerWriter(mergeHtmlWriter); - output.registerWriter(mergeJsonWriter); - output.registerWriter(mergeCoberturaWriter); - output.registerWriter(mergeSonarqubeWriter); - output.registerWriter( - createCoverallsWriter(mergeParser, mergeReporter)); + // Multiple binaries? Register the merged mode stuff + if (countMetadata() > 0) + { + output.registerWriter(mergeHtmlWriter); + output.registerWriter(mergeJsonWriter); + output.registerWriter(mergeCoberturaWriter); + output.registerWriter(mergeSonarqubeWriter); + output.registerWriter( + createCoverallsWriter(mergeParser, mergeReporter)); + output.registerWriter(mergeCodecovWriter); + } + else + { + output.registerWriter(createCoverallsWriter(*parser, reporter)); + } + + output.registerWriter(coberturaWriter); + output.registerWriter(htmlWriter); + output.registerWriter(jsonWriter); + output.registerWriter(sonarqubeWriter); + output.registerWriter(codecovWriter); } else { - output.registerWriter(createCoverallsWriter(*parser, reporter)); + // Nothing else, if only cobertura is requested + output.registerWriter(coberturaWriter); } - - output.registerWriter(htmlWriter); - output.registerWriter(jsonWriter); - output.registerWriter(coberturaWriter); - output.registerWriter(sonarqubeWriter); } reporter.registerListener(mergeParser); - output.registerWriter(mergeParser); + if (!conf.keyAsInt("cobertura-only")) + { + output.registerWriter(mergeParser); + } g_engine = engine; g_output = &output; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/output-handler.cc new/kcov-41/src/output-handler.cc --- old/kcov-40/src/output-handler.cc 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/output-handler.cc 2023-02-23 13:55:55.000000000 +0100 @@ -37,10 +37,13 @@ (void)mkdir(m_baseDirectory.c_str(), 0755); (void)mkdir(m_outDirectory.c_str(), 0755); - (void)unlink(readableName.c_str()); - if (symlink(m_outDirectory.c_str(), readableName.c_str()) < 0) + if (!conf.keyAsInt("cobertura-only")) { - kcov_debug(INFO_MSG, "Can't symlink readable name\n"); + (void)unlink(readableName.c_str()); + if (symlink(m_outDirectory.c_str(), readableName.c_str()) < 0) + { + kcov_debug(INFO_MSG, "Can't symlink readable name\n"); + } } if (collector) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/parsers/bfd-disassembler.cc new/kcov-41/src/parsers/bfd-disassembler.cc --- old/kcov-40/src/parsers/bfd-disassembler.cc 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/parsers/bfd-disassembler.cc 2023-02-23 13:55:55.000000000 +0100 @@ -5,6 +5,7 @@ #include <set> #include <map> #include <algorithm> +#include <stdexcept> #ifndef ATTRIBUTE_FPTR_PRINTF_2 # define ATTRIBUTE_FPTR_PRINTF_2 @@ -50,15 +51,11 @@ "jpo", "js", "jz", - "jczx" - "jezx" - + "jczx", + "jezx", "loop", - "jmp", - "call", - "ret", }; @@ -75,7 +72,11 @@ BfdDisassembler() { memset(&m_info, 0, sizeof(m_info)); +#if KCOV_LIBFD_DISASM_STYLED + init_disassemble_info(&m_info, (void *)this, BfdDisassembler::opcodesFprintFuncStatic, BfdDisassembler::opcodesFprintStyledFuncStatic); +#else init_disassemble_info(&m_info, (void *)this, BfdDisassembler::opcodesFprintFuncStatic); +#endif m_disassembler = print_insn_i386; m_info.arch = bfd_arch_i386; @@ -86,6 +87,12 @@ virtual void setup(const void *header, size_t headerSize) { + // New ELF file, clear any state from the previous instance + m_cache.clear(); + m_instructions.clear(); + m_orderedInstructions.clear(); + m_bbs.clear(); + const uint8_t *data = (const uint8_t *)header; panic_if(headerSize <= EI_CLASS, @@ -293,24 +300,35 @@ Section *lookupSection(uint64_t address) { + // Iterator to the lowest-addressed section that starts at or above + // `address` SectionCache_t::iterator it = m_cache.lower_bound(address); - if (it == m_cache.end()) - return NULL; + // Rare case, the searched for address might be exactly the base address of + // this section + if (it != m_cache.end() && it->first == address) { + return it->second; + } + + // Go back one section (this might be too far, but we'll check later) --it; - // Above the last symbol + // If there was no previous section, the address isn't in a section (it's + // before the lowest section's baseAddress) if (it == m_cache.end()) return NULL; + // We've found the highest-starting section that's lower than the target + // address, check it actually contains the address Section *cur = it->second; uint64_t end = cur->getBase() + cur->getSize() - 1; - // Below nearest (possible?) + // Address is below the section's baseAddress (impossible from the above + // logic) if (address < cur->getBase()) - return NULL; + throw std::logic_error("Section search invariant broken"); - // Above section + // Address is above section's end if (address > end) return NULL; @@ -373,7 +391,6 @@ } } - Instruction *getInstruction(uint64_t address) { if (m_instructions.find(address) == m_instructions.end()) @@ -382,8 +399,6 @@ return &m_instructions[address]; } - - void opcodesFprintFunc(const char *str) { std::string stdStr(str); @@ -407,6 +422,25 @@ return out; } +#if KCOV_LIBFD_DISASM_STYLED + static int opcodesFprintStyledFuncStatic(void *info, enum disassembler_style style, const char *fmt, ...) + { + (void)style; + BfdDisassembler *pThis = (BfdDisassembler *)info; + char str[64]; + int out; + + va_list args; + va_start (args, fmt); + out = vsnprintf( str, sizeof(str) - 1, fmt, args ); + va_end (args); + + pThis->opcodesFprintFunc(str); + + return out; + } +#endif + typedef std::map<uint64_t, Section *> SectionCache_t; typedef std::unordered_map<uint64_t, Instruction> InstructionAddressMap_t; typedef std::map<uint64_t, Instruction *> InstructionOrderedMap_t; @@ -414,7 +448,6 @@ struct disassemble_info m_info; disassembler_ftype m_disassembler; - std::vector<std::string> m_instructionVector; SectionCache_t m_cache; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/solib-parser/lib.c new/kcov-41/src/solib-parser/lib.c --- old/kcov-40/src/solib-parser/lib.c 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/solib-parser/lib.c 2023-02-23 13:55:55.000000000 +0100 @@ -95,6 +95,8 @@ ".long 0xfedeffe7\n" /* undefined insn */ #elif defined(__aarch64__) ".long 0xd4200000\n" /* From https://github.com/scottt/debugbreak */ +#elif defined(__riscv) + "ebreak\n" #else # error Unsupported architecture #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/writers/cobertura-writer.cc new/kcov-41/src/writers/cobertura-writer.cc --- old/kcov-40/src/writers/cobertura-writer.cc 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/src/writers/cobertura-writer.cc 2023-02-23 13:55:55.000000000 +0100 @@ -27,7 +27,11 @@ CoberturaWriter(IFileParser &parser, IReporter &reporter, const std::string &outDir) : WriterBase(parser, reporter), m_maxPossibleHits(parser.maxPossibleHits()) { - m_outFiles.push_back(outDir + "/cobertura.xml"); + if (!IConfiguration::getInstance().keyAsInt("cobertura-only")) + { + // cobertura-only is used for vscode, normally + m_outFiles.push_back(outDir + "/cobertura.xml"); + } m_outFiles.push_back(outDir + "/cov.xml"); // For vscode coverage gutters } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/writers/codecov-writer.cc new/kcov-41/src/writers/codecov-writer.cc --- old/kcov-40/src/writers/codecov-writer.cc 1970-01-01 01:00:00.000000000 +0100 +++ new/kcov-41/src/writers/codecov-writer.cc 2023-02-23 13:55:55.000000000 +0100 @@ -0,0 +1,200 @@ +namespace std +{ +class type_info; +} + +#include <reporter.hh> +#include <file-parser.hh> +#include <configuration.hh> +#include <writer.hh> +#include <utils.hh> + +#include <string> +#include <list> +#include <vector> +#include <unordered_map> +#include <iostream> +#include <fstream> +#include <sstream> + +#include "writer-base.hh" + +namespace kcov +{ + +namespace +{ + +// Outputs a coverage file that conforms to the Codecov Custom Coverage Format +// as described here: https://docs.codecov.com/docs/codecov-custom-coverage-format +// +// Noteably, while this file format can be consumed by Codecov, it is most +// useful for interoperating with other services that expect this format, as +// Codecov intentionally can consume multiple formats. +class CodecovWriter : public WriterBase +{ +public: + CodecovWriter(IFileParser &parser, IReporter &reporter, const std::string &outFile) : + WriterBase(parser, reporter), m_outFile(outFile), m_maxPossibleHits(parser.maxPossibleHits()) + { + } + + void onStartup() + { + } + + void onStop() + { + } + + void write() + { + std::stringstream out; + + setupCommonPaths(); + + for (FileMap_t::const_iterator it = m_files.begin(); it != m_files.end(); ++it) + { + File *file = it->second; + + // Fixup file->m_codeLines etc + sumOne(file); + } + out << getHeader(); + + bool first_time = true; + for (FileMap_t::const_iterator it = m_files.begin(); it != m_files.end(); ++it) + { + if (!first_time) { + out << ",\n"; + } + File *file = it->second; + out << writeOne(file); + first_time = false; + } + out << "\n"; + + out << getFooter(); + + std::ofstream cur(m_outFile); + cur << out.str(); + } + +private: + void sumOne(File *file) + { + unsigned int nExecutedLines = 0; + unsigned int nCodeLines = 0; + + for (unsigned int n = 1; n < file->m_lastLineNr; n++) + { + if (!m_reporter.lineIsCode(file->m_name, n)) + continue; + + IReporter::LineExecutionCount cnt = m_reporter.getLineExecutionCount(file->m_name, n); + + nExecutedLines += !!cnt.m_hits; + nCodeLines++; + + // Update the execution count + file->m_executedLines = nExecutedLines; + file->m_codeLines = nCodeLines; + } + } + + std::string writeOne(File *file) + { + unsigned int nExecutedLines = 0; + unsigned int nCodeLines = 0; + IConfiguration& conf = IConfiguration::getInstance(); + + // Compute filename, stripping paths + std::string filename = file->m_name; + + if (conf.keyAsInt("codecov-full-paths") == 0) + { + std::string stripPath = conf.keyAsString("strip-path"); + if (stripPath.size() == 0) + { + stripPath = m_commonPath; + } + size_t pos = filename.find(stripPath); + if (pos != std::string::npos && filename.size() > stripPath.size()) + { + filename = filename.substr(stripPath.size() + 1); + } + } + + // Produce each line score. + std::vector<std::string> lineEntries; + for (unsigned int n = 1; n < file->m_lastLineNr; n++) + { + if (m_reporter.lineIsCode(file->m_name, n)) + { + IReporter::LineExecutionCount cnt = m_reporter.getLineExecutionCount(file->m_name, n); + std::string hitScore = "0"; + + if (m_maxPossibleHits == IFileParser::HITS_UNLIMITED || m_maxPossibleHits == IFileParser::HITS_SINGLE) + { + if (cnt.m_hits) { + hitScore = fmt("%u", cnt.m_hits); + } + } + else + { // One or multiple for a line + hitScore = fmt("\"%u/%u\"", cnt.m_hits, cnt.m_possibleHits); + } + lineEntries.push_back(fmt(" \"%u\": %s", n, hitScore.c_str())); + + nExecutedLines += !!cnt.m_hits; + nCodeLines++; + } else { + // We could emit '"linenum": null,' though that seems wasteful in storage. + } + + // Update the execution count. + file->m_executedLines = nExecutedLines; + file->m_codeLines = nCodeLines; + } + + std::string linesBlock; + for (std::vector<std::string>::const_iterator lineEntry = lineEntries.begin(); lineEntry != lineEntries.end(); ++lineEntry) { + if (!linesBlock.empty()) { + linesBlock += ",\n"; + } + linesBlock += *lineEntry; + } + linesBlock += "\n"; + + + std::string out = + " \"" + filename + "\": {\n" + + linesBlock + + " }"; + + return out; + } + + std::string getHeader() + { + return "{\n" + " \"coverage\": {\n"; + } + + const std::string getFooter() + { + return " }\n" + "}\n"; + } + + std::string m_outFile; + IFileParser::PossibleHits m_maxPossibleHits; +}; + +} // namespace anonymous + +IWriter &createCodecovWriter(IFileParser &parser, IReporter &reporter, const std::string &outFile) +{ + return *new CodecovWriter(parser, reporter, outFile); +} +} // namespace kcov diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/src/writers/codecov-writer.hh new/kcov-41/src/writers/codecov-writer.hh --- old/kcov-40/src/writers/codecov-writer.hh 1970-01-01 01:00:00.000000000 +0100 +++ new/kcov-41/src/writers/codecov-writer.hh 2023-02-23 13:55:55.000000000 +0100 @@ -0,0 +1,13 @@ +#pragma once + +#include <string> + +namespace kcov +{ + class IFileParser; + class IReporter; + class IOutputHandler; + + IWriter &createCodecovWriter(IFileParser &elf, IReporter &reporter, + const std::string &outFile); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/tests/python/link_main new/kcov-41/tests/python/link_main --- old/kcov-40/tests/python/link_main 1970-01-01 01:00:00.000000000 +0100 +++ new/kcov-41/tests/python/link_main 2023-04-30 16:08:16.592335847 +0200 @@ -0,0 +1 @@ +symbolic link to main diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kcov-40/tests/tools/python.py new/kcov-41/tests/tools/python.py --- old/kcov-40/tests/tools/python.py 2021-12-18 09:25:42.000000000 +0100 +++ new/kcov-41/tests/tools/python.py 2023-02-23 13:55:55.000000000 +0100 @@ -24,6 +24,13 @@ assert b"Cannot find Python parser 'python3'" not in o +class python_issue_368_can_handle_symlink_target(testbase.KcovTestCase): + def runTest(self): + self.setUp() + rv,o = self.do(testbase.kcov + " --python-parser=python3 " + testbase.outbase + "/kcov " + testbase.sources + "/tests/python/link_main 5 --foo") + + assert b"unrecognized option '--foo'" not in o + class python_unittest(testbase.KcovTestCase): def runTest(self): self.setUp()
