[REFACTOR] rename sspt_procs* --> sspt_proc*
[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                                         const char err_str[] =
163                                                 "(failed strcpy_from_user)";
164                                         EPRINTF("failed to copy string from user %p, bytes %d",
165                                                 user_s, nLengthOfString);
166                                         nLengthOfString = sizeof(err_str);
167                                         memcpy(pResult, err_str, nLengthOfString);
168                                 }
169                         }
170                         else
171 #endif
172                         {
173                                 nLengthOfString = strlen (s) + 1;
174                                 if(nFree < nLengthOfString)
175                                         return NULL; // no space for arg
176                                 memcpy (pResult, s, nLengthOfString);
177                         }
178                         nSizeOfString = ALIGN_VALUE (nLengthOfString);
179                         if(nFree < nSizeOfString)
180                                 return NULL; // no space for arg
181                         pResult += nSizeOfString;
182                         nFree -= nSizeOfString;
183                 }
184                 break;
185                 case AT_ARRAY:
186                         {
187                                 int nLength = va_arg (args, int);
188                                 void *p = NULL;
189                                 int nSize = 0;
190                                 nSize = ALIGN_VALUE (nLength);
191                                 if(nFree < nSize)
192                                         return NULL; // no space for arg
193                                 memcpy (pResult, &nLength, sizeof (int));
194                                 pResult += sizeof (int);
195                                 p = va_arg (args, void *);
196 #ifdef __KERNEL__
197                                 if((void *)p < (void *)TASK_SIZE) {
198                                         const void __user *P = (void __user *) va_arg(args, void*);
199                                         if(copy_from_user(pResult, P, nLength)!= 0)
200                                                 EPRINTF ("failed to copy array from user %p, bytes %d", P, nLength);
201                                 }
202                                 else
203 #endif
204                                         memcpy (pResult, p, nLength);
205                                 pResult += nSize;
206                                 nFree -= nSize;
207                         }
208                         break;
209                 default:
210                         break;
211                 };
212         }
213         return pResult;
214 }
215
216 static UNUSED TYPEOF_EVENT_LENGTH VPackEvent(char *buf, unsigned long buf_len, int mask, TYPEOF_PROBE_ID probe_id,
217                                 TYPEOF_EVENT_TYPE record_type, TYPEOF_TIME *tv, TYPEOF_PROCESS_ID pid,
218                                 TYPEOF_THREAD_ID tid, TYPEOF_CPU_NUMBER cpu, const char *fmt, va_list args)
219 {
220         char *cur = buf;
221         SWAP_TYPE_EVENT_HEADER *pEventHeader = (SWAP_TYPE_EVENT_HEADER *)buf;
222
223         if(buf_len < sizeof(SWAP_TYPE_EVENT_HEADER))
224                 return 0; // no space for header
225
226         pEventHeader->m_nLength = 0;
227         cur += sizeof(TYPEOF_EVENT_LENGTH);
228         pEventHeader->m_nType = record_type;
229         cur += sizeof(TYPEOF_EVENT_TYPE);
230         pEventHeader->m_nProbeID = probe_id;
231         cur += sizeof(TYPEOF_PROBE_ID);
232         //pEventHeader->m_time.tv_sec = tv->tv_sec;
233         //pEventHeader->m_time.tv_usec = tv->tv_usec;
234         if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_TIME)){
235                 memcpy(cur, tv, sizeof(TYPEOF_TIME));
236                 cur += sizeof(TYPEOF_TIME);
237         }
238         //pEventHeader->m_nProcessID = pid;
239         if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_PID)){
240                 (*(TYPEOF_PROCESS_ID *)cur) = pid;
241                 cur += sizeof(TYPEOF_PROCESS_ID);
242         }
243         //pEventHeader->m_nThreadID = tid;
244         if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_TID)){
245                 (*(TYPEOF_THREAD_ID *)cur) = tid;
246                 cur += sizeof(TYPEOF_THREAD_ID);
247         }
248         //pEventHeader->m_nCPU = cpu;
249         if((probe_id == EVENT_FMT_PROBE_ID) || !(mask & IOCTL_EMASK_CPU)){
250                 (*(TYPEOF_CPU_NUMBER *)cur) = cpu;
251                 cur += sizeof(TYPEOF_CPU_NUMBER);
252         }
253         // dyn lib event should have all args, it is for internal use and not visible to user
254         if((probe_id == EVENT_FMT_PROBE_ID) || (probe_id == DYN_LIB_PROBE_ID) || !(mask & IOCTL_EMASK_ARGS)){
255                 (*(TYPEOF_NUMBER_OF_ARGS *)cur) = strlen(fmt);
256                 cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
257                 cur = PackArguments(cur, buf_len-(cur-buf), fmt, args);
258                 if(!cur) return 0; // no space for args
259         }
260         else {
261                 // user space and dynamic kernel probes should have at least one argument
262                 // to identify them
263                 if((probe_id == US_PROBE_ID) || (probe_id == VTP_PROBE_ID) || (probe_id == KS_PROBE_ID)){
264                         char fmt2[2];
265                         (*(TYPEOF_NUMBER_OF_ARGS *)cur) = 1;
266                         cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
267                         // pack args using format string for the 1st arg only
268                         fmt2[0] = fmt[0]; fmt2[1] = '\0';
269                         cur = PackArguments(cur, buf_len-(cur-buf), fmt2, args);
270                         if(!cur) return 0; // no space for args
271                 }
272                 else {
273                         (*(TYPEOF_NUMBER_OF_ARGS *)cur) = 0;
274                         cur += sizeof(TYPEOF_NUMBER_OF_ARGS);
275                 }
276         }
277
278         pEventHeader->m_nLength = cur - buf + sizeof(TYPEOF_EVENT_LENGTH);
279         if(buf_len < pEventHeader->m_nLength)
280                 return 0;// no space for back length
281         //memcpy(cur, &pEventHeader->m_nLength, sizeof(TYPEOF_EVENT_LENGTH));
282         *((TYPEOF_EVENT_LENGTH *)cur) = pEventHeader->m_nLength;
283
284         return pEventHeader->m_nLength;
285 }
286
287 /*static TYPEOF_EVENT_LENGTH PackEvent(char *buf, unsigned long buf_len, TYPEOF_PROBE_ID probe_id,
288                                 TYPEOF_EVENT_TYPE record_type, TYPEOF_TIME *tv, TYPEOF_PROCESS_ID pid,
289                                 TYPEOF_THREAD_ID tid, TYPEOF_CPU_NUMBER cpu, const char *fmt, ...)
290 {
291         va_list args;
292         TYPEOF_EVENT_LENGTH len;
293
294         va_start (args, fmt);
295         len = VPackEvent(buf, buf_len, probe_id, record_type, tv, pid, tid, cpu, fmt, args);
296         va_end (args);
297
298         return len;
299 }*/
300
301 #endif /*EVENTS_H_*/