A dynamic tracer for Linux

global.c 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include <assert.h>
  2. #include <errno.h>
  3. #include <string.h>
  4. #include "arch.h"
  5. #include "func.h"
  6. #include "node.h"
  7. #include "ply.h"
  8. #include "sym.h"
  9. #include "type.h"
  10. static struct type *global_map_ktype(struct node *n)
  11. {
  12. struct node *map, *key;
  13. struct type *ktype;
  14. int nargs = node_nargs(n);
  15. map = n->expr.args;
  16. if (node_nargs(n) == 2)
  17. return map->next->sym->type;
  18. assert(0);
  19. return NULL;
  20. }
  21. static int global_assign_type_infer_map(struct node *n)
  22. {
  23. struct node *map, *key;
  24. struct type *ktype;
  25. map = n->expr.args;
  26. for (key = map->next; key; key = key->next) {
  27. node_print(key, stdout);printf("WKZ\n");
  28. if (type_sizeof(key->sym->type) < 0)
  29. return 0;
  30. node_print(key, stdout);printf("WKZ\n");
  31. }
  32. map->sym->type = type_map_of(global_map_ktype(n), n->sym->type);
  33. return 0;
  34. }
  35. static int global_assign_type_infer(struct prog *prog, struct node *n)
  36. {
  37. struct node *lval, *rval;
  38. lval = n->expr.args;
  39. rval = lval->next;
  40. if (!rval->sym->type)
  41. return 0;
  42. if (!lval->sym->type) {
  43. lval->sym->type = rval->sym->type;
  44. if (node_is_map(lval))
  45. return global_assign_type_infer_map(lval);
  46. return 0;
  47. }
  48. if (type_compatible(lval->sym->type, rval->sym->type))
  49. return 0;
  50. if (lval->ntype == N_IDENT) {
  51. node_error(n, stderr, "conflicting types for '%s'",
  52. lval->ident.name);
  53. } else {
  54. node_error(n, stderr, "conflicting types for '%s'",
  55. lval->expr.args->ident.name);
  56. }
  57. return -EINVAL;
  58. }
  59. static int global_assign_static_verify(struct node *n)
  60. {
  61. struct node *lval;
  62. int nargs = node_nargs(n);
  63. if (nargs != 2) {
  64. node_error(n, stderr, "assignment operator expects 2 arguments,"
  65. " %d given", nargs);
  66. return -EINVAL;
  67. }
  68. lval = n->expr.args;
  69. if (node_is_map(lval) || (lval->ntype == N_IDENT))
  70. return 0;
  71. node_error(n, stderr, "assignment destination must be a variable or map");
  72. return -EINVAL;
  73. }
  74. struct type t_pid = {
  75. .ttype = T_TYPEDEF,
  76. .tdef = { .name = ":pid", .type = &t_u32 },
  77. };
  78. struct type t_time = {
  79. .ttype = T_TYPEDEF,
  80. .tdef = { .name = ":time", .type = &t_s64 },
  81. };
  82. static const struct func global_funcs[] = {
  83. { .name = ":block", .type = &t_void, },
  84. { .name = "+", },
  85. { .name = "-", },
  86. {
  87. .name = ":assign",
  88. .static_verify = global_assign_static_verify,
  89. .type_infer = global_assign_type_infer,
  90. },
  91. {
  92. .name = ":map",
  93. /* .static_verify = global_map_static_verify, */
  94. /* .type_infer = global_map_type_infer, */
  95. },
  96. { .name = "pid", .type = &t_pid, },
  97. { .name = "time", .type = &t_time, },
  98. { .name = "quantize", },
  99. { .name = NULL }
  100. };
  101. static const struct func global_num_func = {
  102. .name = ":num",
  103. .type = &t_int,
  104. };
  105. struct type t_string_array = {
  106. .ttype = T_ARRAY,
  107. .array = { .type = &t_char, .len = 64 }, /* TODO: tunable */
  108. };
  109. struct type t_string = {
  110. .ttype = T_TYPEDEF,
  111. .tdef = { .name = ":string", .type = &t_string_array },
  112. };
  113. static const struct func global_string_func = {
  114. .name = ":string",
  115. .type = &t_string,
  116. };
  117. static const struct func global_ident_func = {
  118. .name = ":ident",
  119. };
  120. static const struct func *global_sym_alloc_expr(struct node *n)
  121. {
  122. const struct func *func;
  123. int err;
  124. for (func = global_funcs; func->name; func++) {
  125. if (strcmp(func->name, n->expr.func))
  126. continue;
  127. return func;
  128. }
  129. return NULL;
  130. }
  131. int global_sym_alloc(struct prog *prog, struct node *n)
  132. {
  133. const struct func *func;
  134. struct symtab *st = prog->locals;
  135. int err;
  136. switch (n->ntype) {
  137. case N_EXPR:
  138. func = global_sym_alloc_expr(n);
  139. break;
  140. case N_IDENT:
  141. st = prog->globals;
  142. func = &global_ident_func;
  143. break;
  144. case N_NUM:
  145. func = &global_num_func;
  146. break;
  147. case N_STRING:
  148. func = &global_string_func;
  149. break;
  150. }
  151. if (!func)
  152. return -ENOENT;
  153. if (func->static_verify) {
  154. err = func->static_verify(n);
  155. if (err)
  156. return err;
  157. }
  158. n->sym = sym_alloc(st, n, func);
  159. if (func->type)
  160. /* return type is static, fill it now */
  161. n->sym->type = func->type;
  162. return 0;
  163. }
  164. int global_probe(struct prog *prog)
  165. {
  166. return 0;
  167. }
  168. struct provider global = {
  169. .name = ":",
  170. .sym_alloc = global_sym_alloc,
  171. .probe = global_probe,
  172. };
  173. __attribute__((constructor))
  174. static void global_init(void)
  175. {
  176. provider_register(&global);
  177. }