Commit 65105848 authored by Laura Alexandra Sequeira Gouveia's avatar Laura Alexandra Sequeira Gouveia

Merge branch '52-implement-code-coverage-in-gitlab' into dev

parents 6d0594fe cadcacc1
*/o-optimize
**/o-optimize
o-optimize/
......@@ -5,7 +5,7 @@
<Partition PartitionIdentifier="1" PartitionName="part0"
Criticality="LEVEL_A" EntryPoint="entry_point" SystemPartition="false">
<PartitionConfiguration Personality="RTEMS5" Cores="1" Mode="source">
<Libs>LIBAIR; LIBPRINTF</Libs>
<Libs>LIBAIR; LIBPRINTF; LIBCOV</Libs>
<Devices></Devices>
<Cache>CODE; DATA</Cache>
<Memory Size="0x900000" />
......
......@@ -13,7 +13,6 @@
#define CONFIGURE_INIT
#include <air.h>
#define RTEMS48I
#ifdef RTEMS48I
#include <pprintf.h>
......@@ -52,7 +51,7 @@ void entry_point(void)
printf( "Time is : %s:%ld\n", my_ctime(start.tv_sec), start.tv_nsec);
#endif
i++;
i++;
rtems_task_wake_after(10);
}
......
/*This code is based on the GCOV-related code of the Linux kernel (kept under
* "kernel/gcov"). It basically uses the convert_to_gcda function to generate
* * the .gcda files information upon application completion, and dump it on the
* * host filesystem via GDB scripting.
* *
* * Original Linux banner follows below - but note that the Linux guys have
* * nothing to do with these modifications, so blame me (and contact me)
* * if something goes wrong.
* *
* * Thanassis Tsiodras
* * Real-time Embedded Software Engineer
* * System, Software and Technology Department
* * European Space Agency
* *
* * e-mail: ttsiodras@gmail.com / Thanassis.Tsiodras@esa.int (work)
* *
* */
/*
* * This code maintains a list of active profiling data structures.
* *
* * Copyright IBM Corp. 2009
* * Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
* *
* * Uses gcc-internal data definitions.
* * Based on the gcov-kernel patch by:
* * Hubertus Franke <frankeh@us.ibm.com>
* * Nigel Hinds <nhinds@us.ibm.com>
* * Rajan Ravindran <rajancr@us.ibm.com>
* * Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
* * Paul Larson
* */
#include "gcov_public.h"
#include <pprintf.h>
#include "malloc.h"
typedef struct tagGcovInfo {
struct gcov_info *info;
struct tagGcovInfo *next;
} GcovInfo;
struct GcovInfo *headGcov = 0;
void get_filename(char * original, char * new){
int i =0;
int j=0;
//original filename format .../../[filename].gcda
//new filename format [filename].gcda
while(original[i]!='\0')
i++;
if(i<5)
return;
i=i-6;
while(original[i]!='/')
i--;
i++;
while(original[i]!='\0'){
new[j]=original[i];
i++;
j++;
}
new[j]='\0';
for(i=0; i<j+1;i++)
original[i]=new[i];
return;
}
/*
* * __gcov_init is called by gcc-generated constructor code for each object
* * file compiled with -fprofile-arcs.
* */
void __gcov_init(struct gcov_info *info)
{
char name[24];
get_filename(gcov_info_filename(info), name);
pprintf("__gcov_init called for %s!\n", gcov_info_filename(info));
GcovInfo *newHead = malloc(sizeof(GcovInfo));
if (!newHead) {
pprintf("Out of memory!\n");
return;
}
newHead->info=info;
newHead->next = headGcov;
headGcov = newHead;
}
void __gcov_exit()
{
GcovInfo *tmp = headGcov;
pprintf("head gcov %d %d\n", headGcov, tmp->next);
pprintf("on gcov_exit for %s\n", gcov_info_filename(tmp->info));
while(tmp) {
unsigned bytesNeeded = convert_to_gcda(0, tmp->info);
char buffer[bytesNeeded];
if (!buffer) {
pprintf("Out of memory!");
return;
}
convert_to_gcda(buffer, tmp->info);
pprintf("Emitting %6d bytes for %s\n", bytesNeeded, gcov_info_filename(tmp->info));
tmp = tmp->next;
}
}
/*
* * This code provides functions to handle gcc's profiling data format
* * introduced with gcc 4.7.
* *
* * This file is based heavily on gcc_3_4.c file.
* *
* * For a better understanding, refer to gcc source:
* * gcc/gcov-io.h
* * libgcc/libgcov.c
* *
* * Uses gcc-internal data definitions.
* */
#include <memory.h>
#include "gcov.h"
#include "gcov_public.h"
#if (__GNUC__ >= 7)
#define GCOV_COUNTERS 9
#elif (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)
#define GCOV_COUNTERS 10
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9
#define GCOV_COUNTERS 9
#else
#define GCOV_COUNTERS 8
#endif
#define GCOV_TAG_FUNCTION_LENGTH 3
typedef unsigned int u32;
typedef unsigned long long u64;
#define EINVAL 22
/**
* * struct gcov_ctr_info - information about counters for a single function
* * @num: number of counter values for this type
* * @values: array of counter values for this type
* *
* * This data is generated by gcc during compilation and doesn't change
* * at run-time with the exception of the values array.
* */
struct gcov_ctr_info {
unsigned int num;
gcov_type *values;
};
/**
* * struct gcov_fn_info - profiling meta data per function
* * @key: comdat key
* * @ident: unique ident of function
* * @lineno_checksum: function lineo_checksum
* * @cfg_checksum: function cfg checksum
* * @ctrs: instrumented counters
* *
* * This data is generated by gcc during compilation and doesn't change
* * at run-time.
* *
* * Information about a single function. This uses the trailing array
* * idiom. The number of counters is determined from the merge pointer
* * array in gcov_info. The key is used to detect which of a set of
* * comdat functions was selected -- it points to the gcov_info object
* * of the object file containing the selected comdat function.
* */
struct gcov_fn_info {
const struct gcov_info *key;
unsigned int ident;
unsigned int lineno_checksum;
unsigned int cfg_checksum;
struct gcov_ctr_info ctrs[0];
};
/**
* * struct gcov_info - profiling data per object file
* * @version: gcov version magic indicating the gcc version used for compilation
* * @next: list head for a singly-linked list
* * @stamp: uniquifying time stamp
* * @filename: name of the associated gcov data file
* * @merge: merge functions (null for unused counter type)
* * @n_functions: number of instrumented functions
* * @functions: pointer to pointers to function information
* *
* * This data is generated by gcc during compilation and doesn't change
* * at run-time with the exception of the next pointer.
* */
struct gcov_info {
unsigned int version;
struct gcov_info *next;
unsigned int stamp;
const char *filename;
void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int);
unsigned int n_functions;
struct gcov_fn_info **functions;
};
/*
* * Determine whether a counter is active. Doesn't change at run-time.
* */
static int counter_active(struct gcov_info *info, unsigned int type)
{
return info->merge[type] ? 1 : 0;
}
/**
* * gcov_info_filename - return info filename
* * @info: profiling data set
* */
const char *gcov_info_filename(struct gcov_info *info)
{
return info->filename;
}
/**
* * store_gcov_u32 - store 32 bit number in gcov format to buffer
* * @buffer: target buffer or NULL
* * @off: offset into the buffer
* * @v: value to be stored
* *
* * Number format defined by gcc: numbers are recorded in the 32 bit
* * unsigned binary form of the endianness of the machine generating the
* * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
* * store anything.
* */
static size_t store_gcov_u32(void *buffer, size_t off, u32 v)
{
u32 *data;
if (buffer) {
data = buffer + off;
*data = v;
}
return sizeof(*data);
}
/**
* * store_gcov_u64 - store 64 bit number in gcov format to buffer
* * @buffer: target buffer or NULL
* * @off: offset into the buffer
* * @v: value to be stored
* *
* * Number format defined by gcc: numbers are recorded in the 32 bit
* * unsigned binary form of the endianness of the machine generating the
* * file. 64 bit numbers are stored as two 32 bit numbers, the low part
* * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store
* * anything.
* */
static size_t store_gcov_u64(void *buffer, size_t off, u64 v)
{
u32 *data;
if (buffer) {
data = buffer + off;
data[0] = (v & 0xffffffffUL);
data[1] = (v >> 32);
}
return sizeof(*data) * 2;
}
/**
* * convert_to_gcda - convert profiling data set to gcda file format
* * @buffer: the buffer to store file data or %NULL if no data should be stored
* * @info: profiling data set to be converted
* *
* * Returns the number of bytes that were/would have been stored into the buffer.
* */
unsigned int convert_to_gcda(char *buffer, struct gcov_info *info)
{
struct gcov_fn_info *fi_ptr;
struct gcov_ctr_info *ci_ptr;
unsigned int fi_idx;
unsigned int ct_idx;
unsigned int cv_idx;
size_t pos = 0;
/* File header. */
pos += store_gcov_u32(buffer, pos, GCOV_DATA_MAGIC);
pos += store_gcov_u32(buffer, pos, info->version);
pos += store_gcov_u32(buffer, pos, info->stamp);
for (fi_idx = 0; fi_idx < info->n_functions; fi_idx++) {
fi_ptr = info->functions[fi_idx];
/* Function record. */
pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION);
pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION_LENGTH);
pos += store_gcov_u32(buffer, pos, fi_ptr->ident);
pos += store_gcov_u32(buffer, pos, fi_ptr->lineno_checksum);
pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);
ci_ptr = fi_ptr->ctrs;
for (ct_idx = 0; ct_idx < GCOV_COUNTERS; ct_idx++) {
if (!counter_active(info, ct_idx))
continue;
/* Counter record. */
pos += store_gcov_u32(buffer, pos,
GCOV_TAG_FOR_COUNTER(ct_idx));
pos += store_gcov_u32(buffer, pos, ci_ptr->num * 2);
for (cv_idx = 0; cv_idx < ci_ptr->num; cv_idx++) {
pos += store_gcov_u64(buffer, pos, ci_ptr->values[cv_idx]);
}
ci_ptr++;
}
}
return pos;
}
/*Thiss code is based on the GCOV-related code of the Linux kernel (kept under
* "kernel/gcov"). It basically uses the convert_to_gcda function to generate
* * the .gcda files information upon application completion, and dump it on the
* * host filesystem via GDB scripting.
* *
* * Original Linux banner follows below - but note that the Linux guys have
* * nothing to do with these modifications, so blame me (and contact me)
* * if something goes wrong.
* *
* * Thanassis Tsiodras
* * Real-time Embedded Software Engineer
* * System, Software and Technology Department
* * European Space Agency
* *
* * e-mail: ttsiodras@gmail.com / Thanassis.Tsiodras@esa.int (work)
* *
* */
/*
* * Profiling infrastructure declarations.
* *
* * This file is based on gcc-internal definitions. Data structures are
* * defined to be compatible with gcc counterparts. For a better
* * understanding, refer to gcc source: gcc/gcov-io.h.
* *
* * Copyright IBM Corp. 2009
* * Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
* *
* * Uses gcc-internal data definitions.
* */
#ifndef GCOV_H
#define GCOV_H GCOV_H
#include "gcov_public.h"
/*
* * Profiling data types used for gcc 3.4 and above - these are defined by
* * gcc and need to be kept as close to the original definition as possible to
* * remain compatible.
* */
#define GCOV_DATA_MAGIC ((unsigned int) 0x67636461)
#define GCOV_TAG_FUNCTION ((unsigned int) 0x01000000)
#define GCOV_TAG_COUNTER_BASE ((unsigned int) 0x01a10000)
#define GCOV_TAG_FOR_COUNTER(count) \
(GCOV_TAG_COUNTER_BASE + ((unsigned int) (count) << 17))
/* 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;
/* Interface to access gcov_info data */
const char *gcov_info_filename(struct gcov_info *info);
unsigned int gcov_info_version(struct gcov_info *info);
struct gcov_info *gcov_info_next(struct gcov_info *info);
void gcov_info_link(struct gcov_info *info);
void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info);
/* Base interface. */
enum gcov_action {
GCOV_ADD,
GCOV_REMOVE,
};
void gcov_event(enum gcov_action action, struct gcov_info *info);
void gcov_enable_events(void);
/* Iterator control. */
struct seq_file;
struct gcov_iterator;
struct gcov_iterator *gcov_iter_new(struct gcov_info *info);
void gcov_iter_free(struct gcov_iterator *iter);
void gcov_iter_start(struct gcov_iterator *iter);
int gcov_iter_next(struct gcov_iterator *iter);
int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq);
struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter);
/* gcov_info control. */
void gcov_info_reset(struct gcov_info *info);
int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2);
void gcov_info_add(struct gcov_info *dest, struct gcov_info *source);
void gcov_info_free(struct gcov_info *info);
struct gcov_link {
enum {
OBJ_TREE,
SRC_TREE,
} dir;
const char *ext;
};
extern const struct gcov_link gcov_link[];
#endif /* GCOV_H */
#ifndef __GCOV_PUBLIC_H__
#define __GCOV_PUBLIC_H__
struct gcov_info;
typedef long long gcov_type;
void __gcov_init(struct gcov_info *info);
void __gcov_exit(void);
void __gcov_merge_add(gcov_type *counters, unsigned int n_counters);
unsigned int convert_to_gcda(char *buffer, struct gcov_info *info);
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/*
* * linux/compr_mm.h
* *
* * Memory management for pre-boot and ramdisk uncompressors
* *
* * Authors: Alain Knaff <alain@knaff.lu>
* *
* */
#ifndef DECOMPR_MM_H
#define DECOMPR_MM_H
/* A trivial malloc implementation, adapted from
* * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
* */
#ifndef STATIC_RW_DATA
#define STATIC_RW_DATA static
#endif
static char aux[2048];
unsigned long free_mem_ptr=&aux[0];
unsigned long free_mem_end_ptr=&aux[2047];
STATIC_RW_DATA unsigned long malloc_ptr;
STATIC_RW_DATA int malloc_count;
static void *malloc(int size)
{
void *p;
if (size < 0)
return 0;
if (!malloc_ptr)
malloc_ptr = free_mem_ptr;
malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */
p = (void *)malloc_ptr;
malloc_ptr += size;
if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
return 0;
malloc_count++;
return p;
}
static void free(void *where)
{
malloc_count--;
if (!malloc_count)
malloc_ptr = free_mem_ptr;
}
#endif /* DECOMPR_MM_H */
##
# @package air.libraries.libcov
# @author lasg
# @brief libtest configuration
__author__ = 'lasg'
import os
import utils
from air import *
import utils.file as file_tools
# @brief Name
name = "libcov"
# @brief Description
description = "Coverage support library"
# @brief Library Source files
source_files = set(utils.flatten([
file_tools.getFilesByExtensions(os.path.join(SOURCE_LIBS_DIRECTORY, 'libcov'), ['.c']),
]))
# @brief Library Header files
header_files = set(utils.flatten([
file_tools.getFilesByExtensions(
os.path.join(SOURCE_LIBS_DIRECTORY, 'libcov', 'include'), ['.h']),
]))
# @brief Library dependencies
dependencies = ['libprintf']
# @brief Custom Makefile
makefile = None
# @brief Requires POS
requires_pos = None
......@@ -96,6 +96,10 @@ rtems_task Init(rtems_task_argument ignored) {
${partition.entry_point}();
}
#ifdef COVERAGE_ENABLED
__gcov_exit();
#endif
rtems_task_delete(RTEMS_SELF);
}
......
......@@ -76,6 +76,9 @@ CPPFLAGS+=${'\\'}
-I../common/${'\\'}
-B../common/${'\\'}
-DRTEMS5${'\\'}
% if 'libcov' in partition.libraries:
-fprofile-arcs -ftest-coverage -DCOVERAGE_ENABLED${'\\'}
% endif
${template.LibraryIncludes(partition.libraries)}\
# build LD falgs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment