xref: /minix3/minix/lib/libsys/gcov.c (revision 3ac58492b3d3709bad0ae9c60a137f63a90960b7)
1433d6423SLionel Sambuc /* This code can be linked into minix servers that are compiled
2433d6423SLionel Sambuc  * with gcc gcov flags.
3433d6423SLionel Sambuc  * Author: Anton Kuijsten
4433d6423SLionel Sambuc  */
5433d6423SLionel Sambuc 
6433d6423SLionel Sambuc #include <lib.h>
7433d6423SLionel Sambuc #include <stdio.h>
8433d6423SLionel Sambuc #include <sys/types.h>
9433d6423SLionel Sambuc #include <stdlib.h>
10433d6423SLionel Sambuc #include <string.h>
11433d6423SLionel Sambuc #include <fcntl.h>
12433d6423SLionel Sambuc #include <sys/stat.h>
13433d6423SLionel Sambuc #include <unistd.h>
14433d6423SLionel Sambuc #include <assert.h>
15433d6423SLionel Sambuc #include <minix/syslib.h>
16*3ac58492SDavid van Moolenbroek #include <minix/sysutil.h>
17433d6423SLionel Sambuc #include <minix/gcov.h>
18433d6423SLionel Sambuc 
19*3ac58492SDavid van Moolenbroek static endpoint_t endpt = NONE;   /* endpoint of requesting service, or NONE */
20*3ac58492SDavid van Moolenbroek static cp_grant_id_t grant;    /* grant to write results into during request */
21*3ac58492SDavid van Moolenbroek static int pos;                  /* data-buffer pointer from user space tool */
22433d6423SLionel Sambuc static int gcov_enable=0;     /* nothing will be done with gcov-data if zero */
23433d6423SLionel Sambuc static int gcov_buff_sz;                        /* size of user space buffer */
24433d6423SLionel Sambuc static FILE gcov_file;                      /* used as fopen() return value. */
25433d6423SLionel Sambuc static int gcov_opened;
26433d6423SLionel Sambuc 
27433d6423SLionel Sambuc /* copies <size> bytes from <ptr> to <gcov_buff> */
add_buff(const void * ptr,int size)28*3ac58492SDavid van Moolenbroek static void add_buff(const void *ptr, int size)
29433d6423SLionel Sambuc {
30433d6423SLionel Sambuc 	int r;
31*3ac58492SDavid van Moolenbroek 
32*3ac58492SDavid van Moolenbroek 	assert(endpt != NONE);
33433d6423SLionel Sambuc 	assert(pos <= gcov_buff_sz);
34433d6423SLionel Sambuc 
35433d6423SLionel Sambuc 	if(pos+size > gcov_buff_sz) {
36433d6423SLionel Sambuc 		size = pos - gcov_buff_sz;
37433d6423SLionel Sambuc 	}
38433d6423SLionel Sambuc 
39*3ac58492SDavid van Moolenbroek 	r = sys_safecopyto(endpt, grant, pos, (vir_bytes)ptr, size);
40433d6423SLionel Sambuc 
41433d6423SLionel Sambuc 	if(r) {
42433d6423SLionel Sambuc 		printf("libsys: gcov: safecopy failed (%d)\n", r);
43433d6423SLionel Sambuc   	}
44433d6423SLionel Sambuc 
45433d6423SLionel Sambuc 	pos += size;
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc 	assert(pos <= gcov_buff_sz);
48433d6423SLionel Sambuc }
49433d6423SLionel Sambuc 
50433d6423SLionel Sambuc /* easy wrapper for add_buff */
add_int(int value)51433d6423SLionel Sambuc static void add_int(int value)
52433d6423SLionel Sambuc {
53433d6423SLionel Sambuc 	add_buff((void *) &value, sizeof(int));
54433d6423SLionel Sambuc }
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc /* These functions are meant to replace standard file
57433d6423SLionel Sambuc  * system calls (fopen, etc)
58433d6423SLionel Sambuc  */
59433d6423SLionel Sambuc 
_gcov_fopen(const char * name,const char * mode)60*3ac58492SDavid van Moolenbroek FILE *_gcov_fopen(const char *name, const char *mode)
61433d6423SLionel Sambuc {
62433d6423SLionel Sambuc 	if(!gcov_enable) return NULL;
63433d6423SLionel Sambuc 
64433d6423SLionel Sambuc 	assert(!gcov_opened);
65433d6423SLionel Sambuc 
66433d6423SLionel Sambuc 	/* write information to buffer */
67433d6423SLionel Sambuc 	add_int(GCOVOP_OPEN);
68433d6423SLionel Sambuc 	add_int(strlen(name)+1);
69433d6423SLionel Sambuc         add_buff(name, strlen(name)+1);
70433d6423SLionel Sambuc 
71433d6423SLionel Sambuc 	gcov_opened = 1;
72433d6423SLionel Sambuc 
73433d6423SLionel Sambuc 	/* return dummy FILE *. */
74433d6423SLionel Sambuc         return &gcov_file;
75433d6423SLionel Sambuc }
76433d6423SLionel Sambuc 
77433d6423SLionel Sambuc 
_gcov_fread(void * ptr,size_t itemsize,size_t nitems,FILE * stream)78433d6423SLionel Sambuc size_t _gcov_fread(void *ptr, size_t itemsize, size_t nitems, FILE *stream)
79433d6423SLionel Sambuc {
80433d6423SLionel Sambuc         return 0;
81433d6423SLionel Sambuc }
82433d6423SLionel Sambuc 
_gcov_fwrite(const void * ptr,size_t itemsize,size_t nitems,FILE * stream)83*3ac58492SDavid van Moolenbroek size_t _gcov_fwrite(const void *ptr, size_t itemsize, size_t nitems,
84*3ac58492SDavid van Moolenbroek 	FILE *stream)
85433d6423SLionel Sambuc {
86433d6423SLionel Sambuc 	int size = itemsize * nitems;
87433d6423SLionel Sambuc 
88433d6423SLionel Sambuc 	if(!gcov_enable) return -1;
89433d6423SLionel Sambuc 
90433d6423SLionel Sambuc 	/* only have one file open at a time to ensure writes go
91433d6423SLionel Sambuc 	 * to the right place.
92433d6423SLionel Sambuc 	 */
93433d6423SLionel Sambuc 	assert(gcov_opened);
94433d6423SLionel Sambuc 	assert(stream == &gcov_file);
95433d6423SLionel Sambuc 
96433d6423SLionel Sambuc 	/* write information to buffer */
97433d6423SLionel Sambuc 	add_int(GCOVOP_WRITE);
98433d6423SLionel Sambuc 	add_int(size);
99433d6423SLionel Sambuc 	add_buff(ptr, size);
100433d6423SLionel Sambuc 
101433d6423SLionel Sambuc         return nitems;
102433d6423SLionel Sambuc }
103433d6423SLionel Sambuc 
_gcov_fclose(FILE * stream)104433d6423SLionel Sambuc int _gcov_fclose(FILE *stream)
105433d6423SLionel Sambuc {
106433d6423SLionel Sambuc 	if(!gcov_enable) return EOF;
107433d6423SLionel Sambuc 
108433d6423SLionel Sambuc 	add_int(GCOVOP_CLOSE);
109433d6423SLionel Sambuc 	assert(gcov_opened);
110433d6423SLionel Sambuc 	gcov_opened = 0;
111433d6423SLionel Sambuc         return 0;
112433d6423SLionel Sambuc }
113433d6423SLionel Sambuc 
_gcov_fseek(FILE * stream,long offset,int ptrname)114433d6423SLionel Sambuc int _gcov_fseek(FILE *stream, long offset, int ptrname)
115433d6423SLionel Sambuc {
116433d6423SLionel Sambuc         return 0;
117433d6423SLionel Sambuc }
118433d6423SLionel Sambuc 
_gcov_getenv(const char * name)119433d6423SLionel Sambuc char *_gcov_getenv(const char *name)
120433d6423SLionel Sambuc {
121433d6423SLionel Sambuc         return NULL;
122433d6423SLionel Sambuc }
123433d6423SLionel Sambuc 
gcov_flush(endpoint_t ep,cp_grant_id_t grantid,size_t bufsize)124*3ac58492SDavid van Moolenbroek int gcov_flush(endpoint_t ep, cp_grant_id_t grantid, size_t bufsize)
125433d6423SLionel Sambuc {
126433d6423SLionel Sambuc 	/* Initialize global state. */
127433d6423SLionel Sambuc 	pos=0;
128*3ac58492SDavid van Moolenbroek 	endpt = ep;
129433d6423SLionel Sambuc 	grant = grantid;
130433d6423SLionel Sambuc 	gcov_buff_sz = bufsize;
131433d6423SLionel Sambuc 	assert(!gcov_enable);
132433d6423SLionel Sambuc 	assert(!gcov_opened);
133433d6423SLionel Sambuc 	gcov_enable = 1;
134433d6423SLionel Sambuc 
135433d6423SLionel Sambuc 	/* Trigger copying.
136433d6423SLionel Sambuc 	 * This function is not always available, but there is a do-nothing
137433d6423SLionel Sambuc 	 * version in libc so that executables can be linked even without
138433d6423SLionel Sambuc 	 * this code ever being activated.
139433d6423SLionel Sambuc 	 */
140433d6423SLionel Sambuc 	__gcov_flush();
141433d6423SLionel Sambuc 
142433d6423SLionel Sambuc 	/* Mark the end of the data, stop. */
143433d6423SLionel Sambuc 	add_int(GCOVOP_END);
144433d6423SLionel Sambuc 	assert(!gcov_opened);
145433d6423SLionel Sambuc 	assert(gcov_enable);
146433d6423SLionel Sambuc 	gcov_enable = 0;
147*3ac58492SDavid van Moolenbroek 	endpt = NONE;
148433d6423SLionel Sambuc 
149433d6423SLionel Sambuc 	/* Return number of bytes used in buffer. */
150433d6423SLionel Sambuc 	return pos;
151433d6423SLionel Sambuc }
152433d6423SLionel Sambuc 
153433d6423SLionel Sambuc /* This function can be called to perform the copying.
154433d6423SLionel Sambuc  * It sends its own reply message and can thus be
155433d6423SLionel Sambuc  * registered as a SEF * callback.
156433d6423SLionel Sambuc  */
do_gcov_flush_impl(message * msg)157433d6423SLionel Sambuc int do_gcov_flush_impl(message *msg)
158433d6423SLionel Sambuc {
159433d6423SLionel Sambuc 	message replymsg;
160433d6423SLionel Sambuc 	memset(&replymsg, 0, sizeof(replymsg));
161433d6423SLionel Sambuc 
162433d6423SLionel Sambuc 	assert(msg->m_type == COMMON_REQ_GCOV_DATA);
163433d6423SLionel Sambuc 
164*3ac58492SDavid van Moolenbroek 	replymsg.m_type = gcov_flush(msg->m_source, msg->m_vfs_lsys_gcov.grant,
165*3ac58492SDavid van Moolenbroek 		msg->m_vfs_lsys_gcov.size);
166433d6423SLionel Sambuc 	return ipc_send(msg->m_source, &replymsg);
167433d6423SLionel Sambuc }
168