]> Zhao Yanbai Git Server - minix.git/commitdiff
gcov support, based on work contributed by Anton Kuijsten.
authorBen Gras <ben@minix3.org>
Wed, 25 Aug 2010 13:06:43 +0000 (13:06 +0000)
committerBen Gras <ben@minix3.org>
Wed, 25 Aug 2010 13:06:43 +0000 (13:06 +0000)
23 files changed:
commands/Makefile
commands/gcov-pull/Makefile [new file with mode: 0644]
commands/gcov-pull/gcov-pull.c [new file with mode: 0644]
include/Makefile
include/minix/callnr.h
include/minix/com.h
include/minix/gcov.h [new file with mode: 0644]
include/minix/sef.h
lib/libc/other/Makefile.inc
lib/libc/other/gcov.c [new file with mode: 0644]
lib/libc/other/gcov_flush.c [new file with mode: 0644]
lib/libsys/Makefile
lib/libsys/gcov.c [new file with mode: 0644]
lib/libsys/sef.c
servers/pm/table.c
servers/vfs/Makefile
servers/vfs/gcov.c [new file with mode: 0644]
servers/vfs/proto.h
servers/vfs/table.c
share/mk/Makefile
share/mk/bsd.gcov.mk [new file with mode: 0644]
share/mk/bsd.own.mk
share/mk/bsd.prog.mk

index 4030cd65233e616f798411a9263af9c068d4f74b..0a82de12f9c86532dd80cd1bf8c7ea91f7493b99 100644 (file)
@@ -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 \
diff --git a/commands/gcov-pull/Makefile b/commands/gcov-pull/Makefile
new file mode 100644 (file)
index 0000000..8a121bd
--- /dev/null
@@ -0,0 +1,4 @@
+PROG=gcov-pull
+MAN=
+
+.include <bsd.prog.mk>
diff --git a/commands/gcov-pull/gcov-pull.c b/commands/gcov-pull/gcov-pull.c
new file mode 100644 (file)
index 0000000..8739451
--- /dev/null
@@ -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;
+}
index a75437ea8b9d137b1921eb99cc8ef61e739d7828..6763fe8991fb061113e20516252bbc583fa928f0 100644 (file)
@@ -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
index 3b52911ad8970401799d431ad18e2b3358413d16..58c37c7dd6a8ccefc53565ebc09ef22d893d8006 100644 (file)
@@ -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 
                                 */
 #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.
                                 */
index 454da85e753d4fe3a9d1cff5fb62f6786695c18a..04f289e448b4ca6dfd83b0e3404439af7a381b99 100644 (file)
  *                Miscellaneous field names                                 *
  *===========================================================================*/
 
-#define COMMON_RQ_BASE         0xE00
-
 /* PM field names */
 /* BRK */
 #define PMBRK_ADDR                             m1_p1
 #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                                    *
  *===========================================================================*/
diff --git a/include/minix/gcov.h b/include/minix/gcov.h
new file mode 100644 (file)
index 0000000..51b11c6
--- /dev/null
@@ -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);
index 3cb4041a24960cd5ed7626750b1b3900738f27ee..9bb2414b172d744e78a1e801e8318226cb63f46e 100644 (file)
@@ -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) );
index 8f18fb62a924d7f9a995ec773006311d2b347ed7..d8d9026922fd7cfd1e554c9f0dde2aa7b99265e9 100644 (file)
@@ -57,6 +57,8 @@ SRCS+=  \
        fts.c \
        fgetln.c \
        fsversion.c \
+       gcov.c \
+       gcov_flush.c \
        getgrent.c \
        getlogin.c \
        getopt_long.c \
diff --git a/lib/libc/other/gcov.c b/lib/libc/other/gcov.c
new file mode 100644 (file)
index 0000000..b49657c
--- /dev/null
@@ -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);
+}
+
diff --git a/lib/libc/other/gcov_flush.c b/lib/libc/other/gcov_flush.c
new file mode 100644 (file)
index 0000000..60e678c
--- /dev/null
@@ -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.
+         */
+        ;
+}
+
index 7469515e4450cfadac4054d2ea15aca62f7ab3c4..e33d2594294258d8499459c57817af66c65f9a66 100644 (file)
@@ -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}
 
diff --git a/lib/libsys/gcov.c b/lib/libsys/gcov.c
new file mode 100644 (file)
index 0000000..2d020b3
--- /dev/null
@@ -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);
+}
+
index 428b076fd3f63e7d3da9218441746bf5107ad7b4..5be45ae6f819569428866d29cb9b98b662562508 100644 (file)
@@ -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.
        */
index 0e3e0eafd1a0edc9066b6f267d3c037730126117..8fdc6683d92faa9793e3774f914bb9bc7be75820 100644 (file)
@@ -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];
index ae18060162be42169fc6109426df959851f09c2d..db545d7b8be60fc5ef1308e3a21094d0cc0035c0 100644 (file)
@@ -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
diff --git a/servers/vfs/gcov.c b/servers/vfs/gcov.c
new file mode 100644 (file)
index 0000000..1bbe0b4
--- /dev/null
@@ -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;
+}
+
index 0a107e4c98bae1f653f4975480e8676523c628a2..10fd861940d083ba571135925215230e5ce4d512 100644 (file)
@@ -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)              );
index 6d7f4f28a637bb5a9f4a5142e6e9234106e6ff99..2c7c3e413c6d4b78206ea27a20bffca56e07cb58 100644 (file)
@@ -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];
index ecd7d67c28c791cee3ac1dc6ec719aa357deab91..36de72ec8c358ca18b1d9a7e5c897213e602277f 100644 (file)
@@ -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
diff --git a/share/mk/bsd.gcov.mk b/share/mk/bsd.gcov.mk
new file mode 100644 (file)
index 0000000..f466bec
--- /dev/null
@@ -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)
index 83390da3a0b6a73b200ba4dc532d4809ad261e09..ff512aedf3299b121be90e022e7a887462064428 100644 (file)
@@ -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 \
index 04f8eecca0271be96e372ff380ed3d526bea9bf1..d3eb82457cb667b7c4c58e01807264529c539c1d 100644 (file)
@@ -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