From 9235be68b52ee7b321d985fe2d82a38d685ffb4f Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 13 Nov 2020 22:01:14 +0100 Subject: [PATCH 2/2] gcov: Add __gcov_info_to_gdca() libgcc/ Makefile.in: Add libgcov-info-to-gcda.c to libgcov.a. gcov.h (gcov_info): Declare. (__gcov_info_to_gdca): Likewise. libgcov-info-to-gcda.c: New. --- libgcc/Makefile.in | 7 ++- libgcc/gcov.h | 9 +++ libgcc/libgcov-info-to-gcda.c | 106 ++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 libgcc/libgcov-info-to-gcda.c diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index d6075d32bd4..ae8ddc23955 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -909,13 +909,16 @@ LIBGCOV_INTERFACE = _gcov_dump _gcov_fork \ _gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset \ _gcov_lock_unlock LIBGCOV_DRIVER = _gcov +LIBGCOV_INFO_TO_GCDA = _gcov_info_to_gcda libgcov-merge-objects = $(patsubst %,%$(objext),$(LIBGCOV_MERGE)) libgcov-profiler-objects = $(patsubst %,%$(objext),$(LIBGCOV_PROFILER)) libgcov-interface-objects = $(patsubst %,%$(objext),$(LIBGCOV_INTERFACE)) libgcov-driver-objects = $(patsubst %,%$(objext),$(LIBGCOV_DRIVER)) +libgcov-info-to-gcda-objects = $(patsubst %,%$(objext),$(LIBGCOV_INFO_TO_GCDA)) libgcov-objects = $(libgcov-merge-objects) $(libgcov-profiler-objects) \ - $(libgcov-interface-objects) $(libgcov-driver-objects) + $(libgcov-interface-objects) $(libgcov-driver-objects) \ + $(libgcov-info-to-gcda-objects) $(libgcov-merge-objects): %$(objext): $(srcdir)/libgcov-merge.c $(srcdir)/gcov.h $(srcdir)/libgcov.h $(gcc_compile) -DL$* -c $(srcdir)/libgcov-merge.c @@ -926,6 +929,8 @@ $(libgcov-interface-objects): %$(objext): $(srcdir)/libgcov-interface.c $(srcdir $(libgcov-driver-objects): %$(objext): $(srcdir)/libgcov-driver.c \ $(srcdir)/libgcov-driver-system.c $(srcdir)/gcov.h $(srcdir)/libgcov.h $(gcc_compile) -DL$* -c $(srcdir)/libgcov-driver.c +$(libgcov-info-to-gcda-objects): %$(objext): $(srcdir)/libgcov-info-to-gcda.c $(srcdir)/gcov.h $(srcdir)/libgcov.h + $(gcc_compile) -DL$* -c $(srcdir)/libgcov-info-to-gcda.c # Static libraries. diff --git a/libgcc/gcov.h b/libgcc/gcov.h index 0e3eed31032..f5ee7d49052 100644 --- a/libgcc/gcov.h +++ b/libgcc/gcov.h @@ -25,6 +25,8 @@ #ifndef GCC_GCOV_H #define GCC_GCOV_H +struct gcov_info; + /* Set all counters to zero. */ extern void __gcov_reset (void); @@ -33,4 +35,11 @@ extern void __gcov_reset (void); extern void __gcov_dump (void); +/* Output gcov information as gcda data stream. */ + +extern void __gcov_info_to_gcda (const struct gcov_info *, + void (*) (const char *, void *), + void (*) (const void *, unsigned, void *), + void *); + #endif /* GCC_GCOV_H */ diff --git a/libgcc/libgcov-info-to-gcda.c b/libgcc/libgcov-info-to-gcda.c new file mode 100644 index 00000000000..d40d279b372 --- /dev/null +++ b/libgcc/libgcov-info-to-gcda.c @@ -0,0 +1,106 @@ +/* Routines required for instrumenting a program. */ +/* Compile this one with gcc. */ +/* Copyright (C) 2020 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "libgcov.h" + +static void +gcov_fn_info_to_gcda (const struct gcov_info *gi_ptr, + const struct gcov_fn_info *gfi_ptr, + void (*dump) (const void *, unsigned, void *), + void *arg) +{ + const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; + + for (unsigned t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + if (t_ix != GCOV_COUNTER_V_TOPN && t_ix != GCOV_COUNTER_V_INDIR) + { + gcov_unsigned_t word = GCOV_TAG_FOR_COUNTER (t_ix); + (*dump) (&word, sizeof (word), arg); + gcov_position_t n_counts = ci_ptr->num; + + if (gcov_are_all_counters_zero (ci_ptr)) + { + /* Do not stream when all counters are zero. */ + word = GCOV_TAG_COUNTER_LENGTH (-n_counts); + (*dump) (&word, sizeof (word), arg); + } + else + { + word = GCOV_TAG_COUNTER_LENGTH (n_counts); + (*dump) (&word, sizeof (word), arg); + + for (unsigned i = 0; i < n_counts; i++) + { + gcov_type value = ci_ptr->values[i]; + word = (gcov_unsigned_t) value; + (*dump) (&word, sizeof (word), arg); + + if (sizeof (value) > sizeof (word)) + word = (gcov_unsigned_t) (value >> 32); + else + word = 0; + + (*dump) (&word, sizeof (word), arg); + } + } + } + + ci_ptr++; + } +} + +void +__gcov_info_to_gcda (const struct gcov_info *gi_ptr, + void (*filename) (const char *, void *), + void (*dump) (const void *, unsigned, void *), + void *arg) +{ + (*filename) (gi_ptr->filename, arg); + gcov_unsigned_t word = GCOV_DATA_MAGIC; + (*dump) (&word, sizeof (word), arg); + (*dump) (&gi_ptr->version, sizeof (gi_ptr->version), arg); + (*dump) (&gi_ptr->stamp, sizeof (gi_ptr->stamp), arg); + + for (unsigned f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++) + { + const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; + word = GCOV_TAG_FUNCTION; + (*dump) (&word, sizeof (word), arg); + word = GCOV_TAG_FUNCTION_LENGTH; + (*dump) (&word, sizeof (word), arg); + (*dump) (&gfi_ptr->ident, sizeof (gfi_ptr->ident), arg); + (*dump) (&gfi_ptr->lineno_checksum, + sizeof (gfi_ptr->lineno_checksum), arg); + (*dump) (&gfi_ptr->cfg_checksum, sizeof (gfi_ptr->cfg_checksum), arg); + gcov_fn_info_to_gcda (gi_ptr, gfi_ptr, dump, arg); + } + + word = 0; + (*dump) (&word, sizeof (word), arg); +} -- 2.26.2