2025-10-10 16:07:00 +08:00

270 lines
10 KiB
C

/**********************************************************************/
/** @addtogroup embedded_gcov
* @{
* @file
* @version $Id: $
*
* @author 2021-08-31 kjpeters Working and cleaned up version.
* @author 2021-09-20 kjpeters Provide optional printf imitation.
* @author 2022-01-03 kjpeters Add file output.
*
* @note Based on GCOV-related code of the Linux kernel,
* as described online by Thanassis Tsiodras (April 2016)
* https://www.thanassis.space/coverage.html
* and by Alexander Tarasikov
* http://allsoftwaresucks.blogspot.com/2015/05/gcov-is-amazing-yet-undocumented.html
* with additional investigation, updating, cleanup, and portability
* by Ken Peters.
*
* @brief Public header file for embedded gcov.
*
**********************************************************************/
#ifndef __GCOV_PUBLIC_H__
#define __GCOV_PUBLIC_H__
/* User-selectable compile-time options for the embedded gcov */
/* Not all have been fully tested */
/* select internal customizations ------------------------------------ */
/* needed to adapt to your system */
/* Allow functions to use malloc to get data buffers.
* Not all embedded systems allow that, but instead
* must declare all data in advance.
* If not allowing malloc, might require your custom code
* in gcov_public.c to set buffer sizes.
*/
#define GCOV_OPT_USE_MALLOC
/* Allow functions to use othe stdlib functions.
* Not all embedded systems allow that, but instead
* haave their own functions or imitations.
* If not allowing stdlib, might require your custom code
* in gcov_public.c to call appropriate functions.
*/
//#define GCOV_OPT_USE_STDLIB
/* Allow functions to print status and error messages.
* Not all embedded systems support that.
* If not enabled, you might want custom code in gcov_public.c
* to indicate some other way.
* If defined, you must also provide defs below
* for GCOV_PRINT_STR and GCOV_PRINT_NUM.
*/
#define GCOV_OPT_PRINT_STATUS
/* Reset watchdog timeout during gcov tree scanning.
* Might be needed if you enable serial output on a slow port,
* or if you have a very short watchdog timeout.
* Requires your custom code in gcov_gcc.c
*/
//#define GCOV_OPT_RESET_WATCHDOG
/* Provide function to call constructor list (even in plain C)
* (to call the gcc-generated code that calls __gcov_init).
* Might be needed if you are not running a standard
* C program startup that already does this (such as in boot code).
* If defined, requires your custom linker file code as described below.
*/
#define GCOV_OPT_PROVIDE_CALL_CONSTRUCTORS
#ifdef GCOV_OPT_PROVIDE_CALL_CONSTRUCTORS
/* start and end of constructor section defined in link file */
/* you have to provide appropriate linker file code to define these,
* if your compiler/runtime environment does not automatically.
* An example linker file segment:
.ctors : {
__ctor_list = . ;
*(SORT(.ctors.*))
*(.ctors)
__ctor_end = . ;
. = ALIGN(16);
} > ram
*/
extern void *__init_array_start;
extern void *__init_array_end;
#endif // GCOV_OPT_PROVIDE_CALL_CONSTRUCTORS
/* Provide function to clear the counter data.
* This is only needed if you want to be able to clear
* the counter data after startup (the counters start up at zero).
* Might be needed if you want to avoid counting your FSW startup,
* or if you want to clear the counters between tests.
* You might NOT want this if you are extremely memory constrained
* (such as in PROM) and do not need this function to take up some bytes.
*/
#define GCOV_OPT_PROVIDE_CLEAR_COUNTERS
/* Provide small imitation printf function.
* This is only needed if you want serial port outputs and
* do not have already-existing functions to do the printing.
* If you select this, then you need to provide a function
* write_bytes() that does the actual serial output in your system.
* See gcov_printf.c
*/
#define GCOV_OPT_PROVIDE_PRINTF_IMITATION
/* select data output method(s) ------------------------------------ */
/* Other output methods might be imagined,
* if you have flash that can be written directly, etc.
* Can be nice to write the concatenated results
* to one file instead of a bunch of separate .gcda files.
*/
/* Output gcda data as binary format in file.
* Might require your custom code in gcov_public.c
* if your file headers and functions are non-standard.
* Can be combined with other GCOV_OPT_OUTPUT_* options.
*/
//#define GCOV_OPT_OUTPUT_BINARY_FILE
/* Modify this output filename if desired */
/* Not used if you do not define GCOV_OPT_OUTPUT_BINARY_FILE */
#define GCOV_OUTPUT_BINARY_FILENAME "gcov_output.bin"
/* Modify file headers, data type and functions, if needed */
/* Not used if you do not define GCOV_OPT_OUTPUT_BINARY_FILE */
#ifdef GCOV_OPT_OUTPUT_BINARY_FILE
#if 1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
typedef int GCOV_FILE_TYPE;
#define GCOV_OPEN_FILE(filename) open((filename), (O_CREAT|O_WRONLY), (S_IRWXU|S_IRWXG|S_IRWXO))
#define GCOV_OPEN_ERROR(fileref) ((fileref) < 0)
#define GCOV_CLOSE_FILE(fileref) close((fileref))
#define GCOV_WRITE_BYTE(fileref, char_var) write((fileref), &(char_var), (1))
#else
#include <stdio.h>
typedef FILE * GCOV_FILE_TYPE;
#define GCOV_OPEN_FILE(filename) fopen((filename), ("wb"))
#define GCOV_OPEN_ERROR(fileref) ((fileref) == NULL)
#define GCOV_CLOSE_FILE(fileref) fclose((fileref))
#define GCOV_WRITE_BYTE(fileref, char_var) fprintf((fileref), "%c", (char_var))
#endif
#endif // GCOV_OPT_OUTPUT_BINARY_FILE
/* Output gcda data as binary format in memory block.
* Requires your custom code in gcov_public.c
* to set the starting address of the block.
* Can be combined with other GCOV_OPT_OUTPUT_* options.
*/
//#define GCOV_OPT_OUTPUT_BINARY_MEMORY
/* Output gcda data as hexdump format ASCII on serial port.
* Might require your custom code in gcov_public.c
* if your serial headers and functions are not stdio.h,
* puts, and printf.
* If defined, you must also provide defs below
* for GCOV_PRINT_STR and GCOV_PRINT_NUM.
* Can be combined with other GCOV_OPT_OUTPUT_* options.
*/
#define GCOV_OPT_OUTPUT_SERIAL_HEXDUMP
/* Function to print a string without newline.
* Not used if you don't define either GCOV_OPT_PRINT_STATUS
* or GCOV_OPT_OUTPUT_SERIAL_HEXDUMP.
* If you do, you need to set this as appropriate for your system.
* You might need to add header files to gcc_public.c
*/
//#define GCOV_PRINT_STR(str) fputs((str), stdout)
#define GCOV_PRINT_STR(str) os_printf("%s", str)
//#define GCOV_PRINT_STR(str) gcov_printf("%s", str)
//#define GCOV_PRINT_STR(str) puts((str))
/* Function to print a number without newline.
* Not used if you don't define either GCOV_OPT_PRINT_STATUS
* or GCOV_OPT_OUTPUT_SERIAL_HEXDUMP.
* If you do, you need to set this as appropriate for your system.
* You might need to add header files to gcc_public.c
*/
#define GCOV_PRINT_NUM(num) os_printf("%d", (num))
//#define GCOV_PRINT_NUM(num) gcov_printf("%d", (num))
//#define GCOV_PRINT_NUM(num) print_num((num))
/* Function to print hexdump address.
* Not used if you don't define GCOV_OPT_OUTPUT_SERIAL_HEXDUMP.
* If you do, you need to set this as appropriate for your system.
* You might need to add header files to gcc_public.c
*/
#define GCOV_PRINT_HEXDUMP_ADDR(num) os_printf("%08x: ", (num))
//#define GCOV_PRINT_HEXDUMP_ADDR(num) gcov_printf("%08x: ", (num))
/* Function to print hexdump data value.
* Not used if you don't define GCOV_OPT_OUTPUT_SERIAL_HEXDUMP.
* If you do, you need to set this as appropriate for your system.
* You might need to add header files to gcc_public.c
*/
#define GCOV_PRINT_HEXDUMP_DATA(num) os_printf("%02x ", (num))
//#define GCOV_PRINT_HEXDUMP_DATA(num) gcov_printf("%02x ", (num))
/* End of user settings ---------------------------------- */
/* Opaque gcov_info. The gcov structures can change as for example in gcc 4.7 so
* we cannot use full definition here and they need to be placed in gcc specific
* implementation of gcov. This also means no direct access to the members in
* generic code and usage of the interface below.*/
struct gcov_info;
/* Compare to gcc/gcov-io.h */
typedef unsigned gcov_unsigned_t;
typedef long long gcov_type;
/* Compare to libgcc/libgcov.h */
void __gcov_init(struct gcov_info *info);
void __gcov_exit(void);
void __gcov_merge_add(gcov_type *counters, gcov_unsigned_t n_counters);
/* Our own creations */
#ifdef GCOV_OPT_PROVIDE_CLEAR_COUNTERS
void __gcov_clear(void);
#endif
#ifdef GCOV_OPT_PROVIDE_CALL_CONSTRUCTORS
void __gcov_call_constructors(void);
#endif
#ifdef GCOV_OPT_PROVIDE_PRINTF_IMITATION
void gcov_printf(const char *fmt, ...);
#endif
#endif // __GCOV_PUBLIC_H__
/** @}
*/
/*
* embedded-gcov gcov_public.h gcov application interface code
*
* Copyright (c) 2021 California Institute of Technology (“Caltech”).
* U.S. Government sponsorship acknowledged.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Caltech nor its operating division, the Jet Propulsion Laboratory,
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/