Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / ktap / userspace / main.c
1 /*
2  * main.c - ktap compiler and loader entry
3  *
4  * This file is part of ktap by Jovi Zhangwei.
5  *
6  * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
7  *
8  * ktap is free software; you can redistribute it and/or modify it
9  * under the terms and conditions of the GNU General Public License,
10  * version 2, as published by the Free Software Foundation.
11  *
12  * ktap is distributed in the hope it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sched.h>
25 #include <string.h>
26 #include <signal.h>
27 #include <stdarg.h>
28 #include <sys/mman.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <math.h>
35
36 #include "../include/ktap_types.h"
37 #include "../include/ktap_opcodes.h"
38 #include "ktapc.h"
39 #include "../runtime/kp_obj.h"
40 #include "../runtime/kp_str.h"
41 #include "../runtime/kp_tab.h"
42 #include "symbol.h"
43 #include "cparser.h"
44
45
46 /*******************************************************************/
47
48 void *ktapc_reallocv(void *block, size_t osize, size_t nsize)
49 {
50         return kp_reallocv(NULL, block, osize, nsize);
51 }
52
53 ktap_closure *ktapc_newclosure(int n)
54 {
55         return kp_newclosure(NULL, n);
56 }
57
58 ktap_proto *ktapc_newproto()
59 {
60         return kp_newproto(NULL);
61 }
62
63 const ktap_value *ktapc_table_get(ktap_tab *t, const ktap_value *key)
64 {
65         return kp_tab_get(t, key);
66 }
67
68 void ktapc_table_setvalue(ktap_tab *t, const ktap_value *key, ktap_value *val)
69 {
70         kp_tab_setvalue(NULL, t, key, val);
71 }
72
73 ktap_tab *ktapc_table_new()
74 {
75         return kp_tab_new(NULL);
76 }
77
78 ktap_string *ktapc_ts_newlstr(const char *str, size_t l)
79 {
80         return kp_tstring_newlstr(NULL, str, l);
81 }
82
83 ktap_string *ktapc_ts_new(const char *str)
84 {
85         return kp_tstring_new(NULL, str);
86 }
87
88 int ktapc_ts_eqstr(ktap_string *a, ktap_string *b)
89 {
90         return kp_tstring_eqstr(a, b);
91 }
92
93 static void ktapc_runerror(const char *err_msg_fmt, ...)
94 {
95         va_list ap;
96
97         fprintf(stderr, "ktapc_runerror\n");
98
99         va_start(ap, err_msg_fmt);
100         vfprintf(stderr, err_msg_fmt, ap);
101         va_end(ap);
102
103         exit(EXIT_FAILURE);
104 }
105
106 /*
107  * todo: memory leak here
108  */
109 char *ktapc_sprintf(const char *fmt, ...)
110 {
111         char *msg = malloc(128);
112
113         va_list argp;
114         va_start(argp, fmt);
115         vsprintf(msg, fmt, argp);
116         va_end(argp);
117         return msg;
118 }
119
120
121 #define MINSIZEARRAY    4
122
123 void *ktapc_growaux(void *block, int *size, size_t size_elems, int limit,
124                     const char *what)
125 {
126         void *newblock;
127         int newsize;
128
129         if (*size >= limit/2) {  /* cannot double it? */
130                 if (*size >= limit)  /* cannot grow even a little? */
131                         ktapc_runerror("too many %s (limit is %d)\n",
132                                         what, limit);
133                 newsize = limit;  /* still have at least one free place */
134         } else {
135                 newsize = (*size) * 2;
136                 if (newsize < MINSIZEARRAY)
137                         newsize = MINSIZEARRAY;  /* minimum size */
138         }
139
140         newblock = ktapc_reallocv(block, (*size) * size_elems, newsize * size_elems);
141         *size = newsize;  /* update only when everything else is OK */
142         return newblock;
143 }
144
145 /*************************************************************************/
146
147 #define print_base(i) \
148         do {    \
149                 if (i < f->sizelocvars) /* it's a localvars */ \
150                         printf("%s", getstr(f->locvars[i].varname));  \
151                 else \
152                         printf("base + %d", i); \
153         } while (0)
154
155 #define print_RK(instr, _field)  \
156         do {    \
157                 if (ISK(GETARG_##_field(instr))) \
158                         kp_showobj(NULL, k + INDEXK(GETARG_##_field(instr))); \
159                 else \
160                         print_base(GETARG_##_field(instr)); \
161         } while (0)
162
163 #define print_RKA(instr) print_RK(instr, A)
164 #define print_RKB(instr) print_RK(instr, B)
165 #define print_RKC(instr) print_RK(instr, C)
166
167 #define print_upvalue(idx) \
168         do {    \
169                 if ((idx) == 0) \
170                         printf("global"); \
171                 else \
172                         printf("upvalues[%d]", (idx)); \
173         } while (0)
174
175 static void decode_instruction(ktap_proto *f, int instr)
176 {
177         int opcode = GET_OPCODE(instr);
178         ktap_value *k;
179
180         k = f->k;
181
182         printf("%.8x\t", instr);
183         printf("%s\t", ktap_opnames[opcode]);
184
185         switch (opcode) {
186         case OP_MOVE:
187                 printf("\t");
188                 print_base(GETARG_A(instr));
189                 printf(" <- ");
190                 print_base(GETARG_B(instr));
191                 break;
192         case OP_GETTABUP:
193                 print_base(GETARG_A(instr));
194                 printf(" <- ");
195                 print_upvalue(GETARG_B(instr));
196                 printf("{"); print_RKC(instr); printf("}");
197
198                 break;
199         case OP_GETTABLE:
200                 print_base(GETARG_A(instr));
201                 printf(" <- ");
202
203                 print_base(GETARG_B(instr));
204
205                 printf("{");
206                 print_RKC(instr);
207                 printf("}");
208                 break;
209         case OP_SETTABLE:
210                 print_base(GETARG_A(instr));
211                 printf("{");
212                 print_RKB(instr);
213                 printf("}");
214                 printf(" <- ");
215                 print_RKC(instr);
216                 break;
217         case OP_LOADK:
218                 printf("\t");
219                 print_base(GETARG_A(instr));
220                 printf(" <- ");
221
222                 kp_showobj(NULL, k + GETARG_Bx(instr));
223                 break;
224         case OP_CALL:
225                 printf("\t");
226                 print_base(GETARG_A(instr));
227                 break;
228         case OP_JMP:
229                 printf("\t%d", GETARG_sBx(instr));
230                 break;
231         case OP_CLOSURE:
232                 printf("\t");
233                 print_base(GETARG_A(instr));
234                 printf(" <- closure(func starts from line %d)",
235                         f->p[GETARG_Bx(instr)]->lineinfo[0]);
236                 break;
237         case OP_SETTABUP:
238                 print_upvalue(GETARG_A(instr));
239                 printf("{");
240                 print_RKB(instr);
241                 printf("} <- ");
242
243                 print_RKC(instr);
244                 break;
245         case OP_GETUPVAL:
246                 print_base(GETARG_A(instr));
247                 printf(" <- ");
248
249                 print_upvalue(GETARG_B(instr));
250                 break;
251         case OP_NEWTABLE:
252                 print_base(GETARG_A(instr));
253                 printf(" <- {}");
254         default:
255                 break;
256         }
257
258         printf("\n");
259 }
260
261 static int function_nr = 0;
262
263 /* this is a debug function used for check bytecode chunk file */
264 static void dump_function(int level, ktap_proto *f)
265 {
266         int i;
267
268         printf("\n----------------------------------------------------\n");
269         printf("function %d [level %d]:\n", function_nr++, level);
270         printf("linedefined: %d\n", f->linedefined);
271         printf("lastlinedefined: %d\n", f->lastlinedefined);
272         printf("numparams: %d\n", f->numparams);
273         printf("is_vararg: %d\n", f->is_vararg);
274         printf("maxstacksize: %d\n", f->maxstacksize);
275         printf("source: %s\n", getstr(f->source));
276         printf("sizelineinfo: %d \t", f->sizelineinfo);
277         for (i = 0; i < f->sizelineinfo; i++)
278                 printf("%d ", f->lineinfo[i]);
279         printf("\n");
280
281         printf("sizek: %d\n", f->sizek);
282         for (i = 0; i < f->sizek; i++) {
283                 switch(f->k[i].type) {
284                 case KTAP_TNIL:
285                         printf("\tNIL\n");
286                         break;
287                 case KTAP_TBOOLEAN:
288                         printf("\tBOOLEAN: ");
289                         printf("%d\n", f->k[i].val.b);
290                         break;
291                 case KTAP_TNUMBER:
292                         printf("\tTNUMBER: ");
293                         printf("%ld\n", f->k[i].val.n);
294                         break;
295                 case KTAP_TSHRSTR:
296                 case KTAP_TLNGSTR:
297                         printf("\tTSTRING: ");
298                         printf("%s\n", svalue(&(f->k[i])));
299                         break;
300                 default:
301                         printf("\tUnknow constant type %d: ", f->k[i].type);
302                         kp_showobj(NULL, &(f->k[i]));
303                         printf("\n");
304                 }
305         }
306
307         printf("sizelocvars: %d\n", f->sizelocvars);
308         for (i = 0; i < f->sizelocvars; i++) {
309                 printf("\tlocvars: %s startpc: %d endpc: %d\n",
310                         getstr(f->locvars[i].varname), f->locvars[i].startpc,
311                         f->locvars[i].endpc);
312         }
313
314         printf("sizeupvalues: %d\n", f->sizeupvalues);
315         for (i = 0; i < f->sizeupvalues; i++) {
316                 printf("\tname: %s instack: %d idx: %d\n",
317                         getstr(f->upvalues[i].name), f->upvalues[i].instack,
318                         f->upvalues[i].idx);
319         }
320
321         printf("\n");
322         printf("sizecode: %d\n", f->sizecode);
323         for (i = 0; i < f->sizecode; i++)
324                 decode_instruction(f, f->code[i]);
325
326         printf("sizep: %d\n", f->sizep);
327         for (i = 0; i < f->sizep; i++)
328                 dump_function(level + 1, f->p[i]);
329
330 }
331
332 static void usage(const char *msg_fmt, ...)
333 {
334         va_list ap;
335
336         va_start(ap, msg_fmt);
337         vfprintf(stderr, msg_fmt, ap);
338         va_end(ap);
339
340         fprintf(stderr,
341 "Usage: ktap [options] file [script args] -- cmd [args]\n"
342 "   or: ktap [options] -e one-liner  -- cmd [args]\n"
343 "\n"
344 "Options and arguments:\n"
345 "  -o file        : send script output to file, instead of stderr\n"
346 "  -p pid         : specific tracing pid\n"
347 "  -C cpu         : cpu to monitor in system-wide\n"
348 "  -T             : show timestamp for event\n"
349 "  -V             : show version\n"
350 "  -v             : enable verbose mode\n"
351 "  -q             : suppress start tracing message\n"
352 "  -s             : simple event tracing\n"
353 "  -b             : list byte codes\n"
354 "  -le [glob]     : list pre-defined events in system\n"
355 #ifndef NO_LIBELF
356 "  -lf DSO        : list available functions from DSO\n"
357 "  -lm DSO        : list available sdt notes from DSO\n"
358 #endif
359 "  file           : program read from script file\n"
360 "  -- cmd [args]  : workload to tracing\n");
361
362         exit(EXIT_FAILURE);
363 }
364
365 ktap_global_state dummy_global_state;
366
367 static void init_dummy_global_state()
368 {
369         memset(&dummy_global_state, 0, sizeof(ktap_global_state));
370         dummy_global_state.seed = 201236;
371
372         kp_tstring_resize(NULL, 32); /* set inital string hashtable size */
373 }
374
375 #define handle_error(str) do { perror(str); exit(-1); } while(0)
376
377 static struct ktap_parm uparm;
378 static int ktap_trunk_mem_size = 1024;
379
380 static int ktapc_writer(const void* p, size_t sz, void* ud)
381 {
382         if (uparm.trunk_len + sz > ktap_trunk_mem_size) {
383                 int new_size = (uparm.trunk_len + sz) * 2;
384                 uparm.trunk = realloc(uparm.trunk, new_size);
385                 ktap_trunk_mem_size = new_size;
386         }
387
388         memcpy(uparm.trunk + uparm.trunk_len, p, sz);
389         uparm.trunk_len += sz;
390
391         return 0;
392 }
393
394
395 static int forks;
396 static char **workload_argv;
397
398 static int fork_workload(int ktap_fd)
399 {
400         int pid;
401
402         pid = fork();
403         if (pid < 0)
404                 handle_error("failed to fork");
405
406         if (pid > 0)
407                 return pid;
408
409         signal(SIGTERM, SIG_DFL);
410
411         execvp("", workload_argv);
412
413         /*
414          * waiting ktapvm prepare all tracing event
415          * make it more robust in future.
416          */
417         pause();
418
419         execvp(workload_argv[0], workload_argv);
420
421         perror(workload_argv[0]);
422         exit(-1);
423
424         return -1;
425 }
426
427 #define KTAPVM_PATH "/sys/kernel/debug/ktap/ktapvm"
428
429 static char *output_filename;
430
431 static int run_ktapvm()
432 {
433         int ktapvm_fd, ktap_fd;
434         int ret;
435
436         ktapvm_fd = open(KTAPVM_PATH, O_RDONLY);
437         if (ktapvm_fd < 0)
438                 handle_error("open " KTAPVM_PATH " failed");
439
440         ktap_fd = ioctl(ktapvm_fd, 0, NULL);
441         if (ktap_fd < 0)
442                 handle_error("ioctl ktapvm failed");
443
444         ktapio_create(output_filename);
445
446         if (forks) {
447                 uparm.trace_pid = fork_workload(ktap_fd);
448                 uparm.workload = 1;
449         }
450
451         ret = ioctl(ktap_fd, KTAP_CMD_IOC_RUN, &uparm);
452
453         close(ktap_fd);
454         close(ktapvm_fd);
455
456         return ret;
457 }
458
459 int verbose;
460 static int quiet;
461 static int dump_bytecode;
462 static char oneline_src[1024];
463 static int trace_pid = -1;
464 static int trace_cpu = -1;
465 static int print_timestamp;
466
467 #define SIMPLE_ONE_LINER_FMT    \
468         "trace %s { print(cpu(), tid(), execname(), argevent) }"
469
470 static const char *script_file;
471 static int script_args_start;
472 static int script_args_end;
473
474 #ifndef NO_LIBELF
475 struct binary_base
476 {
477         int type;
478         const char *binary;
479 };
480 static int print_symbol(const char *name, vaddr_t addr, void *arg)
481 {
482         struct binary_base *base = (struct binary_base *)arg;
483         const char *type = base->type == FIND_SYMBOL ?
484                 "probe" : "sdt";
485
486         printf("%s:%s:%s\n", type, base->binary, name);
487         return 0;
488 }
489 #endif
490
491 static void parse_option(int argc, char **argv)
492 {
493         char pid[32] = {0};
494         char cpu_str[32] = {0};
495         char *next_arg;
496         int i, j;
497
498         for (i = 1; i < argc; i++) {
499                 if (argv[i][0] != '-') {
500                         script_file = argv[i];
501                         if (!script_file)
502                                 usage("");
503
504                         script_args_start = i + 1;
505                         script_args_end = argc;
506
507                         for (j = i + 1; j < argc; j++) {
508                                 if (argv[j][0] == '-' && argv[j][1] == '-')
509                                         goto found_cmd;
510                         }
511
512                         return;
513                 }
514
515                 if (argv[i][0] == '-' && argv[i][1] == '-') {
516                         j = i;
517                         goto found_cmd;
518                 }
519
520                 next_arg = argv[i + 1];
521
522                 switch (argv[i][1]) {
523                 case 'o':
524                         output_filename = malloc(strlen(next_arg) + 1);
525                         if (!output_filename)
526                                 return;
527
528                         strncpy(output_filename, next_arg, strlen(next_arg));
529                         i++;
530                         break;
531                 case 'e':
532                         strncpy(oneline_src, next_arg, strlen(next_arg));
533                         i++;
534                         break;
535                 case 'p':
536                         strncpy(pid, next_arg, strlen(next_arg));
537                         trace_pid = atoi(pid);
538                         i++;
539                         break;
540                 case 'C':
541                         strncpy(cpu_str, next_arg, strlen(next_arg));
542                         trace_cpu = atoi(cpu_str);
543                         i++;
544                         break;
545                 case 'T':
546                         print_timestamp = 1;
547                         break;
548                 case 'v':
549                         verbose = 1;
550                         break;
551                 case 'q':
552                         quiet = 1;
553                         break;
554                 case 's':
555                         sprintf(oneline_src, SIMPLE_ONE_LINER_FMT, next_arg);
556                         i++;
557                         break;
558                 case 'b':
559                         dump_bytecode = 1;
560                         break;
561                 case 'l': /* list available events */
562                         switch (argv[i][2]) {
563                         case 'e': /* tracepoints */
564                                 list_available_events(next_arg);
565                                 exit(EXIT_SUCCESS);
566 #ifndef NO_LIBELF
567                         case 'f': /* functions in DSO */
568                         case 'm': /* static marks in DSO */ {
569                                 const char *binary = next_arg;
570                                 int type = argv[i][2] == 'f' ?
571                                                 FIND_SYMBOL : FIND_STAPSDT_NOTE;
572                                 struct binary_base base = {
573                                         .type = type,
574                                         .binary = binary,
575                                 };
576                                 int ret;
577
578                                 ret = parse_dso_symbols(binary, type,
579                                                         print_symbol,
580                                                         (void *)&base);
581                                 if (ret <= 0) {
582                                         fprintf(stderr,
583                                         "error: no symbols in binary %s\n",
584                                                 binary);
585                                         exit(EXIT_FAILURE);
586                                 }
587                                 exit(EXIT_SUCCESS);
588                         }
589 #endif
590                         default:
591                                 exit(EXIT_FAILURE);
592                         }
593                         break;
594                 case 'V':
595 #ifdef CONFIG_KTAP_FFI
596                         usage("%s (with FFI)\n\n", KTAP_VERSION);
597 #else
598                         usage("%s\n\n", KTAP_VERSION);
599 #endif
600                         break;
601                 case '?':
602                 case 'h':
603                         usage("");
604                         break;
605                 default:
606                         usage("wrong argument\n");
607                         break;
608                 }
609         }
610
611         return;
612
613  found_cmd:
614         script_args_end = j;
615         forks = 1;
616         workload_argv = &argv[j + 1];
617 }
618
619 static void compile(const char *input)
620 {
621         ktap_closure *cl;
622         char *buff;
623         struct stat sb;
624         int fdin;
625
626         if (oneline_src[0] != '\0') {
627                 init_dummy_global_state();
628                 ffi_cparser_init();
629                 cl = ktapc_parser(oneline_src, input);
630                 goto dump;
631         }
632
633         fdin = open(input, O_RDONLY);
634         if (fdin < 0) {
635                 fprintf(stderr, "open file %s failed\n", input);
636                 exit(-1);
637         }
638
639         if (fstat(fdin, &sb) == -1)
640                 handle_error("fstat failed");
641
642         buff = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
643         if (buff == MAP_FAILED)
644                 handle_error("mmap failed");
645
646         init_dummy_global_state();
647         ffi_cparser_init();
648         cl = ktapc_parser(buff, input);
649
650         munmap(buff, sb.st_size);
651         close(fdin);
652
653  dump:
654         if (dump_bytecode) {
655                 dump_function(1, cl->p);
656                 exit(0);
657         }
658
659         /* ktapc output */
660         uparm.trunk = malloc(ktap_trunk_mem_size);
661         if (!uparm.trunk)
662                 handle_error("malloc failed");
663
664         ktapc_dump(cl->p, ktapc_writer, NULL, 0);
665         ffi_cparser_free();
666 }
667
668 int main(int argc, char **argv)
669 {
670         char **ktapvm_argv;
671         int new_index, i;
672         int ret;
673
674         if (argc == 1)
675                 usage("");
676
677         parse_option(argc, argv);
678
679         if (oneline_src[0] != '\0')
680                 script_file = "one-liner";
681
682         compile(script_file);
683
684         ktapvm_argv = (char **)malloc(sizeof(char *)*(script_args_end -
685                                         script_args_start + 1));
686         if (!ktapvm_argv) {
687                 fprintf(stderr, "canno allocate ktapvm_argv\n");
688                 return -1;
689         }
690
691         ktapvm_argv[0] = malloc(strlen(script_file) + 1);
692         if (!ktapvm_argv[0]) {
693                 fprintf(stderr, "canno allocate memory\n");
694                 return -1;
695         }
696         strcpy(ktapvm_argv[0], script_file);
697         ktapvm_argv[0][strlen(script_file)] = '\0';
698
699         /* pass rest argv into ktapvm */
700         new_index = 1;
701         for (i = script_args_start; i < script_args_end; i++) {
702                 ktapvm_argv[new_index] = malloc(strlen(argv[i]) + 1);
703                 if (!ktapvm_argv[new_index]) {
704                         fprintf(stderr, "canno allocate memory\n");
705                         return -1;
706                 }
707                 strcpy(ktapvm_argv[new_index], argv[i]);
708                 ktapvm_argv[new_index][strlen(argv[i])] = '\0';
709                 new_index++;
710         }
711
712         uparm.argv = ktapvm_argv;
713         uparm.argc = new_index;
714         uparm.verbose = verbose;
715         uparm.trace_pid = trace_pid;
716         uparm.trace_cpu = trace_cpu;
717         uparm.print_timestamp = print_timestamp;
718         uparm.quiet = quiet;
719
720         /* start running into kernel ktapvm */
721         ret = run_ktapvm();
722
723         cleanup_event_resources();
724         return ret;
725 }
726
727