[REFACTOR] move and rename install_file_probes()
[kernel/swap-modules.git] / driver / events.h
1 #ifndef EVENTS_H_
2 #define EVENTS_H_
3
4 #define UNUSED __attribute__((unused))
5
6 #ifdef __KERNEL__
7 #include <asm/uaccess.h>        // copy_from_user
8 #include "debug.h"              // //DPRINTF
9 #else
10 #include <string.h>
11 #include <stdarg.h>
12 #endif
13 #include "picl.h"
14 #include "ec_ioctl.h"
15 #include "ec_probe.h"
16
17 static TYPE_ARGUMENT GetArgumentType (char ch)
18 {
19         switch (ch)
20         {
21         case 'c':
22                 return AT_CHAR;
23                 break;
24         case 'h':
25                 return AT_SHORT;
26                 break;
27         case 'd':
28                 return AT_INT;
29                 break;
30         case 'x':
31                 return AT_LONG;
32                 break;
33         case 'p':
34                 return AT_PTR;
35                 break;
36         case 'f':
37                 return AT_FLOAT;
38                 break;
39         case 'w':
40                 return AT_DOUBLE;
41                 break;
42         case 's':
43                 return AT_STRING;
44                 break;
45         case 'a':
46                 return AT_ARRAY;
47                 break;
48         };
49         return AT_UNKNOWN;
50 }
51
52 static char *PackArguments (char *pBuffer, unsigned long nLen, const char *szFormat, va_list args)
53 {
54         TYPE_ARGUMENT nArgType = AT_UNKNOWN;
55         const char *pChar = NULL;
56         char chCode = '\0';
57         char *pResult = pBuffer;
58         unsigned long nLengthOfDescriptor = 0, nFree = nLen;
59         unsigned long nSizeOfDescriptor = 0;
60
61         // Descriptor
62         nLengthOfDescriptor = strlen (szFormat) + 1;
63         nSizeOfDescriptor = ALIGN_VALUE(nLengthOfDescriptor);
64         if(nFree < nSizeOfDescriptor)
65                 return NULL; // no space for descriptor
66         memcpy (pResult, szFormat, nLengthOfDescriptor);
67         pResult += nSizeOfDescriptor;
68         nFree -= nSizeOfDescriptor;
69
70         for (pChar = szFormat; (chCode = *pChar) != '\0'; pChar++)
71         {
72                 nArgType = GetArgumentType(chCode);
73                 switch (nArgType)
74                 {
75                 case AT_CHAR:
76                         {
77                                 int ch = va_arg (args, int);
78                                 if(nFree < sizeof(ch))
79                                         return NULL; // no space for arg
80                                 memcpy(pResult, &ch, sizeof (ch));
81                                 pResult += sizeof (ch);
82                                 nFree -= sizeof (ch);
83                         }
84                         break;
85                 case AT_SHORT:
86                         {
87                                 int nShort = va_arg (args, int);
88                                 if(nFree < sizeof(nShort))
89                                         return NULL; // no space for arg
90                                 memcpy(pResult, &nShort, sizeof (nShort));
91                                 pResult += sizeof (nShort);
92                                 nFree -= sizeof (nShort);
93                         }
94                         break;
95                 case AT_INT:
96                         {
97                                 int nInt = va_arg (args, int);
98                                 if(nFree < sizeof(nInt))
99                                         return NULL; // no space for arg
100                                 memcpy(pResult, &nInt, sizeof (nInt));
101                                 pResult += sizeof (nInt);
102                                 nFree -= sizeof (nInt);
103                         }
104                         break;
105                 case AT_LONG:
106                         {
107                                 long nLong = va_arg (args, long);
108                                 if(nFree < sizeof(nLong))
109                                         return NULL; // no space for arg
110                                 memcpy (pResult, &nLong, sizeof (nLong));
111                                 pResult += sizeof (nLong);
112                                 nFree -= sizeof (nLong);
113                         }
114                         break;
115                 case AT_PTR:
116                         {
117                                 void *p = va_arg (args, void *);
118                                 if(nFree < sizeof(p))
119                                         return NULL; // no space for arg
120                                 memcpy (pResult, &p, sizeof (p));
121                                 pResult += sizeof (p);
122                                 nFree -= sizeof (p);
123                         }
124                         break;
125                 case AT_FLOAT:
126                         {
127                                 double fValue = va_arg (args, double);
128                                 if(nFree < sizeof(fValue))
129                                         return NULL; // no space for arg
130                                 memcpy (pResult, &fValue, sizeof (fValue));
131                                 pResult += sizeof (fValue);
132                                 nFree -= sizeof (fValue);
133                         }
134                         break;
135                 case AT_DOUBLE:
136                         {
137                                 double fDouble = va_arg (args, double);
138                                 if(nFree < sizeof(fDouble))
139                                         return NULL; // no space for arg
140                                 memcpy (pResult, &fDouble, sizeof (fDouble));
141                                 pResult += sizeof (fDouble);
142                                 nFree -= sizeof (fDouble);
143                         }
144                         break;
145                 case AT_STRING:
146                 {
147                         const char *s = va_arg (args, const char *);
148                         int nLengthOfString = 0, nSizeOfString;
149                         if(!s) {
150                                 /* If string poiner is NULL then */
151                                 s = "(null)";
152                         }
153 #ifdef __KERNEL__
154                         if((void *)s < (void *)TASK_SIZE) {
155                                 const char __user *user_s = (const char __user *)s;
156                                 nLengthOfString = strlen_user(user_s);
157                                 if(nFree < nLengthOfString)
158                                         return NULL; // no space for arg
159                                 if(strncpy_from_user(pResult,
160                                                      user_s,
161                                                      nLengthOfString) != (nLengthOfString-1)) {
162                                         EPRINTF("failed to copy string from user %p, bytes %d",
163                                                 user_s, nLengthOfString);
164                                 }
165                         }
166                         else
167 #endif
168                         {
169                                 nLengthOfString = strlen (s) + 1;
170                                 if(nFree < nLengthOfString)
171                                         return NULL; // no space for arg
172                                 memcpy (pResult, s, nLengthOfString);
173                         }
174                         nSizeOfString = ALIGN_VALUE (nLengthOfString);
175                         if(nFree < nSizeOfString)
176                                 return NULL; // no space for arg
177                         pResult += nSizeOfString;
178                         nFree -= nSizeOfString;
179                 }
180                 break;
181                 case AT_ARRAY:
182                         {
183                                 int nLength = va_arg (args, int);
184                                 void *p = NULL;
185                                 int nSize = 0;
186                                 nSize = ALIGN_VALUE (nLength);
187                                 if(nFree < nSize)
188                                         return NULL; // no space for arg
189                                 memcpy (pResult, &nLength, sizeof (int));
190                                 pResult += sizeof (int);
191                                 p = va_arg (args, void *);
192 #ifdef __KERNEL__
193                                 if((void *)p < (void *)TASK_SIZE) {
194                                         const void __user *P = (void __user *) va_arg(args, void*);
195                                         if(copy_from_user(pResult, P, nLength)!= 0)
196                                                 EPRINTF ("failed to copy array from user %p, bytes %d", P, nLength);
197                                 }
198                                 else
199 #endif
200                                         memcpy (pResult, p, nLength);
201                                 pResult += nSize;
202                                 nFree -= nSize;
203                         }
204                         break;
205                 default:
206                         break;
207                 };
208         }
209         return pResult;
210 }
211
212 static UNUSED TYPEOF_EVENT_LENGTH VPackEvent(char *buf, unsigned long buf_len, int mask, TYPEOF_PROBE_ID probe_id,
213                                 TYPEOF_EVENT_TYPE record_type, TYPEOF_TIME *tv, TYPEOF_PROCESS_ID pid,
214                                 TYPEOF_THREAD_ID tid, TYPEOF_CPU_NUMBER cpu, const char *fmt, va_list args)
215 {
216         char *cur = buf;
217         SWAP_TYPE_EVENT_HEADER *pEventHeader = (SWAP_TYPE_EVENT_HEADER *)buf;
218
219         if(buf_len < sizeof(SWAP_TYPE_EVENT_HEADER))
220                 return 0; // no space for header
221
222         pEventHeader->m_nLength = 0;
223         cur += sizeof(TYPEOF_EVENT_LENGTH);
224         pEventHeader->m_nType = record_type;
225         cur += sizeof(TYPEOF_EVENT_TYPE);
226         pEventHeader->m_nProbeID = probe_id;
227         cur += sizeof(TYPEOF_PROBE_ID);
228         //pEventHeader->m_time.tv_sec = tv->tv_sec;
229         //pEventHeader->m_time.tv_usec = tv->tv_usec;
230         if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_TIME)){
231                 memcpy(cur, tv, sizeof(TYPEOF_TIME));
232                 cur += sizeof(TYPEOF_TIME);
233         }
234         //pEventHeader->m_nProcessID = pid;
235         if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_PID)){
236                 (*(TYPEOF_PROCESS_ID *)cur) = pid;
237                 cur += sizeof(TYPEOF_PROCESS_ID);
238         }
239         //pEventHeader->m_nThreadID = tid;
240         if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_TID)){
241                 (*(TYPEOF_THREAD_ID *)cur) = tid;
242                 cur += sizeof(TYPEOF_THREAD_ID);
243         }
244         //pEventHeader->m_nCPU = cpu;
245         if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_CPU)){
246                 (*(TYPEOF_CPU_NUMBER *)cur) = cpu;
247                 cur += sizeof(TYPEOF_CPU_NUMBER);
248         }
249         // dyn lib event should have all args, it is for internal use and not visible to user
250         if((probe_id == EVENT_FMT_PROBE_ID) || (probe_id == DYN_LIB_PROBE_ID) || !(mask & IOCTL_EMASK_ARGS)){
251                 (*(TYPEOF_NUMBER_OF_ARGS *)cur) = strlen(fmt);
252                 cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
253                 cur = PackArguments(cur, buf_len-(cur-buf), fmt, args);
254                 if(!cur) return 0; // no space for args
255         }
256         else {
257                 // user space and dynamic kernel probes should have at least one argument
258                 // to identify them
259                 if((probe_id == US_PROBE_ID) || (probe_id == VTP_PROBE_ID) || (probe_id == KS_PROBE_ID)){
260                         char fmt2[2];
261                         (*(TYPEOF_NUMBER_OF_ARGS *)cur) = 1;
262                         cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
263                         // pack args using format string for the 1st arg only
264                         fmt2[0] = fmt[0]; fmt2[1] = '\0';
265                         cur = PackArguments(cur, buf_len-(cur-buf), fmt2, args);
266                         if(!cur) return 0; // no space for args
267                 }
268                 else {
269                         (*(TYPEOF_NUMBER_OF_ARGS *)cur) = 0;
270                         cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
271                 }
272         }
273
274         pEventHeader->m_nLength = cur - buf + sizeof(TYPEOF_EVENT_LENGTH);
275         if(buf_len < pEventHeader->m_nLength)
276                 return 0;// no space for back length
277         //memcpy(cur, &pEventHeader->m_nLength, sizeof(TYPEOF_EVENT_LENGTH));
278         *((TYPEOF_EVENT_LENGTH *)cur) = pEventHeader->m_nLength;
279
280         return pEventHeader->m_nLength;
281 }
282
283 /*static TYPEOF_EVENT_LENGTH PackEvent(char *buf, unsigned long buf_len, TYPEOF_PROBE_ID probe_id,
284                                 TYPEOF_EVENT_TYPE record_type, TYPEOF_TIME *tv, TYPEOF_PROCESS_ID pid,
285                                 TYPEOF_THREAD_ID tid, TYPEOF_CPU_NUMBER cpu, const char *fmt, ...)
286 {
287         va_list args;
288         TYPEOF_EVENT_LENGTH len;
289
290         va_start (args, fmt);
291         len = VPackEvent(buf, buf_len, probe_id, record_type, tv, pid, tid, cpu, fmt, args);
292         va_end (args);
293
294         return len;
295 }*/
296
297 #endif /*EVENTS_H_*/