gcov support, based on work contributed by Anton Kuijsten.
This commit is contained in:
parent
d8466ce31f
commit
5d6c2aae0a
23 changed files with 504 additions and 9 deletions
|
@ -12,7 +12,7 @@ SUBDIR= aal add_route adduser advent arp ash at autil awk \
|
|||
dhrystone diff dirname dis88 diskctl du dumpcore easypack \
|
||||
ed eject elle elvis env expand factor file \
|
||||
find finger fingerd fix fold format fortune fsck.mfs \
|
||||
fsck1 ftp101 ftpd200 getty grep gomoku head host \
|
||||
fsck1 ftp101 ftpd200 gcov-pull getty grep gomoku head host \
|
||||
hostaddr id ifconfig ifdef indent install \
|
||||
intr ipcrm ipcs irdpd isoread join kill last leave \
|
||||
less lex life loadkeys loadramdisk logger login look lp \
|
||||
|
|
4
commands/gcov-pull/Makefile
Normal file
4
commands/gcov-pull/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
PROG=gcov-pull
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
131
commands/gcov-pull/gcov-pull.c
Normal file
131
commands/gcov-pull/gcov-pull.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* gcov-pull - Request gcov data from server and write it to gcda files
|
||||
* Author: Anton Kuijsten
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <lib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <alloca.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <minix/gcov.h>
|
||||
|
||||
#define BUFF_SZ (4 * 1024 * 1024) /* 4MB */
|
||||
|
||||
int read_int(void);
|
||||
|
||||
char *buff_p;
|
||||
|
||||
/* helper function to read int from the buffer */
|
||||
int read_int(void)
|
||||
{
|
||||
int res;
|
||||
memcpy(&res, buff_p, sizeof(int));
|
||||
buff_p += sizeof(int);
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
int i, server_nr, command, size, result;
|
||||
char buff[BUFF_SZ]; /* Buffer for all the metadata and file data sent */
|
||||
message msg; /* message sent to vfs */
|
||||
|
||||
if(argc!=2 || sscanf(argv[1], "%d", &server_nr)!=1) {
|
||||
fprintf(stderr, "Usage: %s <pid>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
When making a GCOV call to a server, the gcov library linked into
|
||||
the server will try to write gcov data to disk. This writing is
|
||||
normally done with calls to the vfs, using stdio library calls.
|
||||
This is not correct behaviour for servers, especially vfs itself.
|
||||
Therefore, the server catches those attempts. The messages used for
|
||||
this communication are stored in a buffer. When the gcov operation
|
||||
is done, the buffer is copied from the server to this user space,
|
||||
from where the calls are finally made to the vfs. GCOV calls to the
|
||||
various servers are all routed trough vfs. For more information, see
|
||||
the <minix/gcov.h> header file.
|
||||
*/
|
||||
|
||||
/* visit complete buffer, so vm won't has to
|
||||
manage the pages while flushing
|
||||
*/
|
||||
memset(buff, 'a', sizeof(buff));
|
||||
|
||||
buff_p = buff;
|
||||
|
||||
result = gcov_flush_svr(buff_p, BUFF_SZ, server_nr);
|
||||
|
||||
if(result >= BUFF_SZ) {
|
||||
fprintf(stderr, "Too much data to hold in buffer: %d\n", result);
|
||||
fprintf(stderr, "Maximum: %d\n", BUFF_SZ);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(result < 0) {
|
||||
fprintf(stderr, "Call failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* At least GCOVOP_END opcode expected. */
|
||||
if(result < sizeof(int)) {
|
||||
fprintf(stderr, "Invalid gcov data from pid %d\n", server_nr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Only GCOVOP_END is valid but empty. */
|
||||
if(result == sizeof(int)) {
|
||||
fprintf(stderr, "no gcov data.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Iterate through the system calls contained in the buffer,
|
||||
* and execute them
|
||||
*/
|
||||
while((command=read_int()) != GCOVOP_END) {
|
||||
char *fn;
|
||||
switch(command) {
|
||||
case GCOVOP_OPEN:
|
||||
size = read_int();
|
||||
fn = buff_p;
|
||||
if(strchr(fn, '/')) {
|
||||
fn = strrchr(fn, '/');
|
||||
assert(fn);
|
||||
fn++;
|
||||
}
|
||||
assert(fn);
|
||||
if(!(fd = fopen(fn, "w+"))) {
|
||||
perror(buff_p);
|
||||
exit(1);
|
||||
}
|
||||
buff_p += size;
|
||||
break;
|
||||
case GCOVOP_CLOSE:
|
||||
if(!fd) {
|
||||
fprintf(stderr, "bogus close\n");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fd);
|
||||
fd = NULL;
|
||||
break;
|
||||
case GCOVOP_WRITE:
|
||||
size = read_int();
|
||||
fwrite(buff_p, size, 1, fd);
|
||||
buff_p += size;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "bogus command %d in buffer.\n",
|
||||
command);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -24,7 +24,7 @@ INCS+= minix/a.out.h minix/bitmap.h minix/callnr.h minix/cdrom.h \
|
|||
minix/rs.h minix/safecopies.h minix/sched.h minix/sef.h minix/sound.h \
|
||||
minix/spin.h minix/sys_config.h minix/sysinfo.h minix/syslib.h \
|
||||
minix/sysutil.h minix/timers.h minix/tty.h minix/type.h minix/types.h \
|
||||
minix/u64.h minix/vfsif.h minix/vm.h minix/vtreefs.h \
|
||||
minix/u64.h minix/vfsif.h minix/vm.h minix/vtreefs.h minix/gcov.h \
|
||||
minix/compiler.h minix/compiler-ack.h minix/sha2.h minix/sha1.h minix/md5.h \
|
||||
minix/audio_fw.h
|
||||
INCS+= net/hton.h net/if.h net/ioctl.h net/netlib.h
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define NCALLS 112 /* number of system calls allowed */
|
||||
#define NCALLS 113 /* number of system calls allowed */
|
||||
|
||||
#define EXIT 1
|
||||
#define FORK 2
|
||||
|
@ -113,6 +113,8 @@
|
|||
*/
|
||||
#define SRV_KILL 111 /* to PM: special kill call for RS */
|
||||
|
||||
#define GCOV_FLUSH 112 /* flush gcov data from server to gcov files */
|
||||
|
||||
#define TASK_REPLY 121 /* to VFS: reply code from drivers, not
|
||||
* really a standalone call.
|
||||
*/
|
||||
|
|
|
@ -864,8 +864,6 @@
|
|||
* Miscellaneous field names *
|
||||
*===========================================================================*/
|
||||
|
||||
#define COMMON_RQ_BASE 0xE00
|
||||
|
||||
/* PM field names */
|
||||
/* BRK */
|
||||
#define PMBRK_ADDR m1_p1
|
||||
|
@ -891,10 +889,19 @@
|
|||
#define SEL_ERRORFDS m8_p3
|
||||
#define SEL_TIMEOUT m8_p4
|
||||
|
||||
#define COMMON_RQ_BASE 0xE00
|
||||
|
||||
/* Field names for system signals (sent by a signal manager). */
|
||||
#define SIGS_SIGNAL_RECEIVED (COMMON_RQ_BASE+0)
|
||||
# define SIGS_SIG_NUM m2_i1
|
||||
|
||||
/* Common request to all processes: gcov data. */
|
||||
#define COMMON_REQ_GCOV_DATA (COMMON_RQ_BASE+1)
|
||||
# define GCOV_GRANT m1_i2
|
||||
# define GCOV_PID m1_i3
|
||||
# define GCOV_BUFF_P m1_p1
|
||||
# define GCOV_BUFF_SZ m1_i1
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for VM server *
|
||||
*===========================================================================*/
|
||||
|
|
16
include/minix/gcov.h
Normal file
16
include/minix/gcov.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <sys/types.h>
|
||||
#include <lib.h>
|
||||
#include <stdlib.h>
|
||||
#include <minix/syslib.h>
|
||||
|
||||
/* opcodes for use in gcov buffer */
|
||||
#define GCOVOP_OPEN 23
|
||||
#define GCOVOP_WRITE 24
|
||||
#define GCOVOP_CLOSE 25
|
||||
#define GCOVOP_END 26
|
||||
|
||||
/* More information on the GCOV Minix Wiki page. */
|
||||
|
||||
int gcov_flush_svr(char *buff, int buff_sz, int server_nr);
|
||||
extern void __gcov_flush (void);
|
||||
int do_gcov_flush_impl(message *msg);
|
|
@ -199,10 +199,12 @@ _PROTOTYPE( int sef_cb_lu_response_rs_reply, (message *m_ptr) );
|
|||
/* Callback type definitions. */
|
||||
typedef void(*sef_cb_signal_handler_t)(int signo);
|
||||
typedef int(*sef_cb_signal_manager_t)(endpoint_t target, int signo);
|
||||
typedef int(*sef_cb_gcov_t)(message *msg);
|
||||
|
||||
/* Callback registration helpers. */
|
||||
_PROTOTYPE( void sef_setcb_signal_handler, (sef_cb_signal_handler_t cb));
|
||||
_PROTOTYPE( void sef_setcb_signal_manager, (sef_cb_signal_manager_t cb));
|
||||
_PROTOTYPE( void sef_setcb_gcov, (sef_cb_gcov_t cb));
|
||||
|
||||
/* Predefined callback implementations. */
|
||||
_PROTOTYPE( void sef_cb_signal_handler_null, (int signo) );
|
||||
|
|
|
@ -57,6 +57,8 @@ SRCS+= \
|
|||
fts.c \
|
||||
fgetln.c \
|
||||
fsversion.c \
|
||||
gcov.c \
|
||||
gcov_flush.c \
|
||||
getgrent.c \
|
||||
getlogin.c \
|
||||
getopt_long.c \
|
||||
|
|
55
lib/libc/other/gcov.c
Normal file
55
lib/libc/other/gcov.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <minix/gcov.h>
|
||||
|
||||
int gcov_flush_svr(char *buff, int buff_sz, int server_nr)
|
||||
{
|
||||
message msg;
|
||||
|
||||
msg.GCOV_BUFF_P = buff;
|
||||
msg.GCOV_BUFF_SZ = buff_sz;
|
||||
msg.GCOV_PID = server_nr;
|
||||
|
||||
/* Make the call to server. It will call the gcov library,
|
||||
* buffer the stdio requests, and copy the buffer to this user
|
||||
* space
|
||||
*/
|
||||
_syscall(VFS_PROC_NR, GCOV_FLUSH, &msg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* wrappers for file system calls from gcc libgcov library.
|
||||
Default calls are wrapped. In libsys, an alternative
|
||||
implementation for servers is used.
|
||||
*/
|
||||
|
||||
FILE *_gcov_fopen(char *name, char *mode){
|
||||
return fopen(name, mode);
|
||||
}
|
||||
|
||||
|
||||
size_t _gcov_fread(void *ptr, size_t itemsize, size_t nitems
|
||||
, FILE *stream){
|
||||
return fread(ptr, itemsize, nitems, stream);
|
||||
}
|
||||
|
||||
size_t _gcov_fwrite(void *ptr, size_t itemsize, size_t nitems
|
||||
, FILE *stream){
|
||||
return fwrite(ptr, itemsize, nitems, stream);
|
||||
}
|
||||
|
||||
int _gcov_fclose(FILE *stream){
|
||||
return fclose(stream);
|
||||
}
|
||||
|
||||
int _gcov_fseek(FILE *stream, long offset, int ptrname){
|
||||
return fseek(stream, offset, ptrname);
|
||||
}
|
||||
|
||||
char *_gcov_getenv(const char *name){
|
||||
return getenv(name);
|
||||
}
|
||||
|
14
lib/libc/other/gcov_flush.c
Normal file
14
lib/libc/other/gcov_flush.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <minix/gcov.h>
|
||||
|
||||
void __gcov_flush(void)
|
||||
{
|
||||
/* A version of __gcov_flush for cases in which no gcc -lgcov
|
||||
* is given; i.e. non-gcc or gcc without active gcov.
|
||||
*/
|
||||
;
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ SRCS= \
|
|||
sched_start.c \
|
||||
sched_stop.c \
|
||||
sef.c \
|
||||
sef_gcov.c \
|
||||
sef_init.c \
|
||||
sef_liveupdate.c \
|
||||
sef_ping.c \
|
||||
|
@ -120,7 +121,8 @@ SRCS= \
|
|||
profile.c \
|
||||
vprintf.c \
|
||||
timers.c \
|
||||
spin.c
|
||||
spin.c \
|
||||
gcov.c
|
||||
|
||||
CPPFLAGS.sched_start.c+= -I${MINIXSRCDIR}
|
||||
|
||||
|
|
161
lib/libsys/gcov.c
Normal file
161
lib/libsys/gcov.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* This code can be linked into minix servers that are compiled
|
||||
* with gcc gcov flags.
|
||||
* Author: Anton Kuijsten
|
||||
*/
|
||||
|
||||
#include <lib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/gcov.h>
|
||||
|
||||
static int grant, pos; /* data-buffer pointer from user space tool */
|
||||
static int gcov_fd=0; /* file descriptor for writing gcov data */
|
||||
static int gcov_enable=0; /* nothing will be done with gcov-data if zero */
|
||||
static int gcov_buff_sz; /* size of user space buffer */
|
||||
static FILE gcov_file; /* used as fopen() return value. */
|
||||
static int gcov_opened;
|
||||
|
||||
/* copies <size> bytes from <ptr> to <gcov_buff> */
|
||||
static void add_buff(void *ptr, int size)
|
||||
{
|
||||
int r;
|
||||
assert(pos <= gcov_buff_sz);
|
||||
|
||||
if(pos+size > gcov_buff_sz) {
|
||||
size = pos - gcov_buff_sz;
|
||||
}
|
||||
|
||||
r = sys_safecopyto(VFS_PROC_NR, grant, pos, (vir_bytes)ptr, size, D);
|
||||
|
||||
if(r) {
|
||||
printf("libsys: gcov: safecopy failed (%d)\n", r);
|
||||
}
|
||||
|
||||
pos += size;
|
||||
|
||||
assert(pos <= gcov_buff_sz);
|
||||
}
|
||||
|
||||
/* easy wrapper for add_buff */
|
||||
static void add_int(int value)
|
||||
{
|
||||
add_buff((void *) &value, sizeof(int));
|
||||
}
|
||||
|
||||
/* These functions are meant to replace standard file
|
||||
* system calls (fopen, etc)
|
||||
*/
|
||||
|
||||
FILE *_gcov_fopen(char *name, char *mode)
|
||||
{
|
||||
if(!gcov_enable) return;
|
||||
|
||||
assert(!gcov_opened);
|
||||
|
||||
/* write information to buffer */
|
||||
add_int(GCOVOP_OPEN);
|
||||
add_int(strlen(name)+1);
|
||||
add_buff(name, strlen(name)+1);
|
||||
|
||||
gcov_opened = 1;
|
||||
|
||||
/* return dummy FILE *. */
|
||||
return &gcov_file;
|
||||
}
|
||||
|
||||
|
||||
size_t _gcov_fread(void *ptr, size_t itemsize, size_t nitems, FILE *stream)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t _gcov_fwrite(void *ptr, size_t itemsize, size_t nitems, FILE *stream)
|
||||
{
|
||||
int size = itemsize * nitems;
|
||||
|
||||
if(!gcov_enable) return;
|
||||
|
||||
/* only have one file open at a time to ensure writes go
|
||||
* to the right place.
|
||||
*/
|
||||
assert(gcov_opened);
|
||||
assert(stream == &gcov_file);
|
||||
|
||||
/* write information to buffer */
|
||||
add_int(GCOVOP_WRITE);
|
||||
add_int(size);
|
||||
add_buff(ptr, size);
|
||||
|
||||
return nitems;
|
||||
}
|
||||
|
||||
int _gcov_fclose(FILE *stream)
|
||||
{
|
||||
if(!gcov_enable) return;
|
||||
|
||||
add_int(GCOVOP_CLOSE);
|
||||
assert(gcov_opened);
|
||||
gcov_opened = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gcov_fseek(FILE *stream, long offset, int ptrname)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *_gcov_getenv(const char *name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int gcov_flush(cp_grant_id_t grantid, int bufsize)
|
||||
{
|
||||
/* Initialize global state. */
|
||||
pos=0;
|
||||
grant = grantid;
|
||||
gcov_buff_sz = bufsize;
|
||||
assert(!gcov_enable);
|
||||
assert(!gcov_opened);
|
||||
gcov_enable = 1;
|
||||
|
||||
/* Trigger copying.
|
||||
* This function is not always available, but there is a do-nothing
|
||||
* version in libc so that executables can be linked even without
|
||||
* this code ever being activated.
|
||||
*/
|
||||
__gcov_flush();
|
||||
|
||||
/* Mark the end of the data, stop. */
|
||||
add_int(GCOVOP_END);
|
||||
assert(!gcov_opened);
|
||||
assert(gcov_enable);
|
||||
gcov_enable = 0;
|
||||
|
||||
/* Return number of bytes used in buffer. */
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* This function can be called to perform the copying.
|
||||
* It sends its own reply message and can thus be
|
||||
* registered as a SEF * callback.
|
||||
*/
|
||||
int do_gcov_flush_impl(message *msg)
|
||||
{
|
||||
message replymsg;
|
||||
memset(&replymsg, 0, sizeof(replymsg));
|
||||
|
||||
assert(msg->m_type == COMMON_REQ_GCOV_DATA);
|
||||
assert(msg->m_source == VFS_PROC_NR);
|
||||
|
||||
replymsg.m_type = gcov_flush(msg->GCOV_GRANT, msg->GCOV_BUFF_SZ);
|
||||
return send(msg->m_source, &replymsg);
|
||||
}
|
||||
|
|
@ -151,6 +151,14 @@ PUBLIC int sef_receive_status(endpoint_t src, message *m_ptr, int *status_ptr)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Intercept GCOV data requests (sent by VFS in vfs/gcov.c). */
|
||||
if(m_ptr->m_type == COMMON_REQ_GCOV_DATA &&
|
||||
m_ptr->m_source == VFS_PROC_NR) {
|
||||
if(do_sef_gcov_request(m_ptr) == OK) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get this far, this is not a valid SEF request, return and
|
||||
* let the caller deal with that.
|
||||
*/
|
||||
|
|
|
@ -124,6 +124,7 @@ _PROTOTYPE (int (*call_vec[]), (void) ) = {
|
|||
do_deldma, /* 109 = deldma */
|
||||
do_getdma, /* 110 = getdma */
|
||||
do_srv_kill, /* 111 = srv_kill */
|
||||
no_sys, /* 112 = gcov_flush */
|
||||
};
|
||||
/* This should not fail with "array size is negative": */
|
||||
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
|
||||
|
|
|
@ -4,7 +4,7 @@ SRCS= main.c open.c read.c write.c pipe.c dmap.c \
|
|||
path.c device.c mount.c link.c exec.c \
|
||||
filedes.c stadir.c protect.c time.c \
|
||||
lock.c misc.c utility.c select.c table.c \
|
||||
vnode.c vmnt.c request.c fscall.c
|
||||
vnode.c vmnt.c request.c fscall.c gcov.c
|
||||
|
||||
DPADD+= ${LIBSYS} ${LIBTIMERS}
|
||||
LDADD+= -lsys -ltimers
|
||||
|
|
73
servers/vfs/gcov.c
Normal file
73
servers/vfs/gcov.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
|
||||
#include "fs.h"
|
||||
#include "file.h"
|
||||
#include "fproc.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_gcov_flush *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_gcov_flush()
|
||||
{
|
||||
/* A userland tool has requested the gcov data from another
|
||||
* process (possibly vfs itself). Grant the target process
|
||||
* access to the supplied buffer, and perform the call that
|
||||
* makes the target copy its buffer to the caller (incl vfs
|
||||
* itself).
|
||||
*/
|
||||
int i;
|
||||
struct fproc *rfp;
|
||||
ssize_t size;
|
||||
cp_grant_id_t grantid;
|
||||
int r;
|
||||
int n;
|
||||
pid_t target;
|
||||
|
||||
size = m_in.GCOV_BUFF_SZ;
|
||||
target = m_in.GCOV_PID;
|
||||
|
||||
/* If the wrong process is sent to, the system hangs;
|
||||
* so make this root-only.
|
||||
*/
|
||||
|
||||
if (!super_user) return(EPERM);
|
||||
|
||||
/* Find target gcov process. */
|
||||
|
||||
for(n = 0; n < NR_PROCS; n++) {
|
||||
if(fproc[n].fp_endpoint != NONE &&
|
||||
fproc[n].fp_pid == target)
|
||||
break;
|
||||
}
|
||||
|
||||
if(n >= NR_PROCS) {
|
||||
printf("VFS: gcov proccess %d not found.\n", target);
|
||||
return ESRCH;
|
||||
}
|
||||
|
||||
rfp = &fproc[n];
|
||||
|
||||
/* Grant target process to requestor's buffer. */
|
||||
|
||||
if((grantid = cpf_grant_magic(rfp->fp_endpoint,
|
||||
who_e, (vir_bytes) m_in.GCOV_BUFF_P,
|
||||
size, CPF_WRITE)) < 0) {
|
||||
printf("VFS: gcov_flush: grant failed\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if(target == getpid()) {
|
||||
/* Request is for VFS itself. */
|
||||
r = gcov_flush(grantid, size);
|
||||
} else {
|
||||
/* Perform generic GCOV request. */
|
||||
m_out.GCOV_GRANT = grantid;
|
||||
m_out.GCOV_BUFF_SZ = size;
|
||||
r = _taskcall(rfp->fp_endpoint, COMMON_REQ_GCOV_DATA, &m_out);
|
||||
}
|
||||
|
||||
cpf_revoke(grantid);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -257,6 +257,9 @@ _PROTOTYPE( int check_vrefs, (void) );
|
|||
/* write.c */
|
||||
_PROTOTYPE( int do_write, (void) );
|
||||
|
||||
/* gcov.c */
|
||||
_PROTOTYPE( int do_gcov_flush, (void) );
|
||||
|
||||
/* select.c */
|
||||
_PROTOTYPE( int do_select, (void) );
|
||||
_PROTOTYPE( int select_callback, (struct filp *, int ops) );
|
||||
|
|
|
@ -128,6 +128,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
|
|||
no_sys, /* 109 = (deldma) */
|
||||
no_sys, /* 110 = (getdma) */
|
||||
no_sys, /* 111 = (srv_kill) */
|
||||
do_gcov_flush, /* 112 = gcov_flush */
|
||||
};
|
||||
/* This should not fail with "array size is negative": */
|
||||
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
|
||||
|
|
|
@ -7,7 +7,7 @@ FILES= bsd.ack.mk bsd.dep.mk bsd.files.mk \
|
|||
bsd.gcc.mk bsd.inc.mk \
|
||||
bsd.init.mk bsd.kinc.mk bsd.klinks.mk \
|
||||
bsd.lib.mk bsd.links.mk bsd.man.mk bsd.obj.mk bsd.own.mk \
|
||||
bsd.prog.mk bsd.subdir.mk bsd.sys.mk \
|
||||
bsd.prog.mk bsd.subdir.mk bsd.sys.mk bsd.gcov.mk \
|
||||
sys.mk
|
||||
|
||||
FILESDIR=/usr/share/mk
|
||||
|
|
12
share/mk/bsd.gcov.mk
Normal file
12
share/mk/bsd.gcov.mk
Normal file
|
@ -0,0 +1,12 @@
|
|||
LCOV=lcov.$(PROG)
|
||||
CLEANFILES+= *.gcno *.gcda $(LCOV)
|
||||
|
||||
.if ${MKCOVERAGE} == "yes"
|
||||
CFLAGS+=-fno-builtin -fprofile-arcs -ftest-coverage
|
||||
LDADD+= -lgcov
|
||||
COMPILER_TYPE=gnu
|
||||
CC=gcc
|
||||
.endif
|
||||
|
||||
lcov:
|
||||
lcov -c -d . >$(LCOV)
|
|
@ -749,7 +749,7 @@ ${var}?= yes
|
|||
#
|
||||
_MKVARS.no= \
|
||||
MKCRYPTO_IDEA MKCRYPTO_MDC2 MKCRYPTO_RC5 MKDEBUG MKDEBUGLIB \
|
||||
MKEXTSRC \
|
||||
MKEXTSRC MKCOVERAGE \
|
||||
MKMANDOC MKMANZ MKOBJDIRS \
|
||||
MKPCC MKPCCCMDS \
|
||||
MKSOFTFLOAT MKSTRIPIDENT \
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
.ifndef HOSTPROG
|
||||
|
||||
.include <bsd.init.mk>
|
||||
.include <bsd.gcov.mk>
|
||||
|
||||
#
|
||||
# Definitions and targets shared among all programs built by a single
|
||||
|
|
Loading…
Reference in a new issue