diff --git a/.gitignore b/.gitignore index 48e380fd77..22fdef5fe1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ *.dSYM *.elf *.exe +*.gcno +*.gcda *.hex *.i *.ihx diff --git a/arch/Kconfig b/arch/Kconfig index b2a933fd19..73a37d2a54 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -217,6 +217,14 @@ config ARCH_SIZET_LONG C++ library routines because the NuttX size_t might not have the same underlying type as your toolchain's size_t. +config ARCH_COVERAGE + bool "Enable code coverage analysis" + select HAVE_CXX + select HAVE_CXXINITIALIZE + default n + ---help--- + Generate code coverage + comment "Architecture Options" config ARCH_NOINTC diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile index 71a8c4c921..a549a50085 100644 --- a/arch/sim/src/Makefile +++ b/arch/sim/src/Makefile @@ -89,6 +89,10 @@ ifeq ($(CONFIG_STACK_COLORATION),y) CSRCS += up_checkstack.c endif +ifeq ($(CONFIG_ARCH_COVERAGE),y) + STDLIBS += -lgcov +endif + ifeq ($(CONFIG_SPINLOCK),y) HOSTSRCS += up_testset.c endif diff --git a/arch/sim/src/nuttx-names.in b/arch/sim/src/nuttx-names.in index 2c43b3a0bf..3b3629a9e9 100644 --- a/arch/sim/src/nuttx-names.in +++ b/arch/sim/src/nuttx-names.in @@ -31,7 +31,9 @@ #endif NXSYMBOLS(__cxa_atexit) +NXSYMBOLS(abort) NXSYMBOLS(accept) +NXSYMBOLS(access) NXSYMBOLS(atexit) NXSYMBOLS(bind) NXSYMBOLS(calloc) @@ -46,14 +48,24 @@ NXSYMBOLS(dup) NXSYMBOLS(exit) NXSYMBOLS(fchmod) NXSYMBOLS(fchown) +NXSYMBOLS(fclose) NXSYMBOLS(fcntl) +NXSYMBOLS(fdopen) +NXSYMBOLS(fopen) +NXSYMBOLS(fprintf) +NXSYMBOLS(fread) NXSYMBOLS(free) +NXSYMBOLS(fseek) NXSYMBOLS(fstat) NXSYMBOLS(fsync) +NXSYMBOLS(ftell) NXSYMBOLS(ftruncate) NXSYMBOLS(futimens) +NXSYMBOLS(fwrite) NXSYMBOLS(getpeername) NXSYMBOLS(getsockname) +NXSYMBOLS(getenv) +NXSYMBOLS(getpid) NXSYMBOLS(getsockopt) NXSYMBOLS(if_nametoindex) NXSYMBOLS(ioctl) @@ -89,6 +101,7 @@ NXSYMBOLS(pthread_mutex_lock) NXSYMBOLS(pthread_mutex_unlock) NXSYMBOLS(pthread_setspecific) NXSYMBOLS(pthread_sigmask) +NXSYMBOLS(puts) NXSYMBOLS(read) NXSYMBOLS(readdir) NXSYMBOLS(readv) @@ -102,6 +115,7 @@ NXSYMBOLS(select) NXSYMBOLS(sendmsg) NXSYMBOLS(sendto) NXSYMBOLS(setitimer) +NXSYMBOLS(setbuf) NXSYMBOLS(setjmp) NXSYMBOLS(setsockopt) NXSYMBOLS(shutdown) @@ -113,7 +127,12 @@ NXSYMBOLS(sleep) NXSYMBOLS(socket) NXSYMBOLS(stat) NXSYMBOLS(statvfs) +NXSYMBOLS(stderr) +NXSYMBOLS(strcat) +NXSYMBOLS(strchr) NXSYMBOLS(strerror) +NXSYMBOLS(strlen) +NXSYMBOLS(strtol) NXSYMBOLS(syslog) NXSYMBOLS(tcgetattr) NXSYMBOLS(tcsetattr) diff --git a/boards/sim/sim/sim/scripts/Make.defs b/boards/sim/sim/sim/scripts/Make.defs index 38ddbe107a..080eb70492 100644 --- a/boards/sim/sim/sim/scripts/Make.defs +++ b/boards/sim/sim/sim/scripts/Make.defs @@ -55,6 +55,10 @@ ifeq ($(CONFIG_SIM_SANITIZE),y) ARCHOPTIMIZATION += -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer endif +ifeq ($(CONFIG_ARCH_COVERAGE),y) + ARCHOPTIMIZATION += -fprofile-arcs -ftest-coverage +endif + ARCHCPUFLAGS = -fno-builtin ARCHCPUFLAGSXX = -fno-builtin -nostdinc++ ifeq ($(CONFIG_CXX_EXCEPTION),) diff --git a/tools/Config.mk b/tools/Config.mk index 6adbebf21a..770950a6c1 100644 --- a/tools/Config.mk +++ b/tools/Config.mk @@ -461,6 +461,10 @@ endef # CLEAN - Default clean target +ifeq ($(CONFIG_ARCH_COVERAGE),y) + EXTRA = *.gcno *.gcda +endif + ifeq ($(CONFIG_WINDOWS_NATIVE),y) define CLEAN $(Q) if exist *$(OBJEXT) (del /f /q *$(OBJEXT)) @@ -469,10 +473,11 @@ define CLEAN $(Q) if exist (del /f /q .*.swp) $(Q) if exist $(OBJS) (del /f /q $(OBJS)) $(Q) if exist $(BIN) (del /f /q $(BIN)) + $(Q) if exist $(EXTRA) (del /f /q $(EXTRA)) endef else define CLEAN - $(Q) rm -f *$(OBJEXT) *$(LIBEXT) *~ .*.swp $(OBJS) $(BIN) + $(Q) rm -f *$(OBJEXT) *$(LIBEXT) *~ .*.swp $(OBJS) $(BIN) $(EXTRA) endef endif diff --git a/tools/gcov.sh b/tools/gcov.sh new file mode 100755 index 0000000000..341cf7c996 --- /dev/null +++ b/tools/gcov.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# tools/gcov.sh +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +ROOT_DIR=$(cd $(dirname $0)/../../; pwd) + +if [ $# == 1 ]; then + GCOV_DIR=$1 +else + GCOV_DIR=${ROOT_DIR}/gcov +fi + +files=$(find -name "*.gcda" 2> /dev/null | wc -l) +if [ "$files" == "0" ] ;then + echo "Please run ./nuttx before using gcov.sh to generate the coverage report" + exit 1 +fi + +type lcov +if [ $? -ne 0 ]; then + echo "Code coverage generation tool is not detected, please install lcov" + exit 1 +fi + +mkdir -p ${GCOV_DIR} +cd ${GCOV_DIR} + +# Generate coverage text report +lcov -c -d ${ROOT_DIR} -o coverage.info --rc lcov_branch_coverage=1 +# Generate coverage page report +genhtml --branch-coverage -o result coverage.info + +if [ $? -ne 0 ]; then + echo "Failed to generate coverage file" + exit 1 +fi + +echo -e "Copy the following link and open it in the browser to view the coverage report" +echo "file://${GCOV_DIR}/result/index.html"