A dynamic tracer for Linux

global.c 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #define _GNU_SOURCE /* asprintf */
  2. #include <assert.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "arch.h"
  7. #include "func.h"
  8. #include "node.h"
  9. #include "ply.h"
  10. #include "sym.h"
  11. #include "type.h"
  12. /* :map */
  13. static struct type *global_map_ktype(struct node *n)
  14. {
  15. struct node *map, *key;
  16. struct type *ktype;
  17. struct tfield *kfields, *f;
  18. int i, nargs = node_nargs(n);
  19. char *kname;
  20. map = n->expr.args;
  21. if (nargs == 2)
  22. return map->next->sym->type;
  23. ktype = calloc(1, sizeof(*ktype));
  24. assert(ktype);
  25. kfields = calloc(nargs, sizeof(*kfields));
  26. assert(kfields);
  27. for (key = map->next, f = kfields, i = 0; key; key = key->next, f++, i++) {
  28. asprintf(&f->name, "k%d", i);
  29. f->type = key->sym->type;
  30. }
  31. asprintf(&ktype->sou.name, ":%s_key", map->ident.name);
  32. ktype->ttype = T_STRUCT;
  33. ktype->sou.fields = kfields;
  34. type_add(ktype);
  35. return ktype;
  36. }
  37. static int global_map_type_infer(const struct func *func, struct node *n)
  38. {
  39. struct node *map = n->expr.args;
  40. if (n->sym->type || !map->sym->type)
  41. return 0;
  42. assert(map->sym->type->ttype == T_MAP);
  43. /* given `m[key]` where m's type is known, infer that the
  44. * expression's type is equal to m's value type. */
  45. n->sym->type = map->sym->type->map.vtype;
  46. return 0;
  47. }
  48. static int global_map_static_validate(const struct func *func, struct node *n)
  49. {
  50. if (n->expr.args->ntype != N_IDENT) {
  51. _e("%#N: %N is not subscriptable.\n", n, n);
  52. return -EINVAL;
  53. }
  54. return 0;
  55. }
  56. /* :assign */
  57. static int global_assign_type_infer_map(struct node *n)
  58. {
  59. struct node *map, *key;
  60. struct type *ktype;
  61. map = n->expr.args;
  62. for (key = map->next; key; key = key->next) {
  63. if (type_sizeof(key->sym->type) < 0)
  64. return 0;
  65. }
  66. map->sym->type = type_map_of(global_map_ktype(n), n->sym->type);
  67. return 0;
  68. }
  69. static int global_assign_type_infer(const struct func *func, struct node *n)
  70. {
  71. struct node *lval, *rval;
  72. lval = n->expr.args;
  73. rval = lval->next;
  74. if (!rval->sym->type)
  75. return 0;
  76. if (!lval->sym->type) {
  77. /* given `a = b` where b's type is known but not a's,
  78. * infer that a's type must be equal to b's */
  79. lval->sym->type = rval->sym->type;
  80. if (node_is_map(lval))
  81. return global_assign_type_infer_map(lval);
  82. return 0;
  83. }
  84. if (type_compatible(lval->sym->type, rval->sym->type))
  85. return 0;
  86. _e("%#N: can't assign %N (type '%T'), to %N (type '%T').\n",
  87. n, rval, rval->sym->type, lval, lval->sym->type);
  88. return -EINVAL;
  89. }
  90. static int global_assign_static_validate(const struct func *func, struct node *n)
  91. {
  92. struct node *lval;
  93. int nargs = node_nargs(n);
  94. if (nargs != 2) {
  95. _e("%#N: expected 2 arguments, %d given.\n", n, nargs);
  96. return -EINVAL;
  97. }
  98. lval = n->expr.args;
  99. if (node_is_map(lval) || (lval->ntype == N_IDENT))
  100. return 0;
  101. _e("%#N: %N is not assignable.\n", n, lval);
  102. return -EINVAL;
  103. }
  104. /* pid */
  105. struct type t_pid = {
  106. .ttype = T_TYPEDEF,
  107. .tdef = { .name = ":pid", .type = &t_u32 },
  108. };
  109. struct type t_pid_func = {
  110. .ttype = T_FUNC,
  111. .func = { .type = &t_pid },
  112. };
  113. /* time */
  114. struct type t_time = {
  115. .ttype = T_TYPEDEF, /* TODO: should be a T_FUNC with a static
  116. * signature */
  117. .tdef = { .name = ":time", .type = &t_s64 },
  118. };
  119. struct type t_time_func = {
  120. .ttype = T_FUNC,
  121. .func = { .type = &t_time },
  122. };
  123. struct type t_block_func = {
  124. .ttype = T_FUNC,
  125. .func = { .type = &t_void, .vargs = 1 },
  126. };
  127. struct tfield f_assign[] = {
  128. { .type = &t_void },
  129. { .type = &t_void },
  130. { .type = NULL }
  131. };
  132. struct type t_assign_func = {
  133. .ttype = T_FUNC,
  134. .func = { .type = &t_void, .args = f_assign },
  135. };
  136. static const struct func global_funcs[] = {
  137. { .name = ":block", .type = &t_block_func, },
  138. { .name = "+", },
  139. { .name = "-", },
  140. {
  141. .name = ":assign",
  142. .type = &t_assign_func,
  143. .type_infer = global_assign_type_infer,
  144. .static_validate = global_assign_static_validate,
  145. },
  146. {
  147. .name = ":map",
  148. /* .type = t_map_func, */
  149. .type_infer = global_map_type_infer,
  150. .static_validate = global_map_static_validate,
  151. },
  152. { .name = "pid", .type = &t_pid_func, },
  153. { .name = "time", .type = &t_time_func, },
  154. { .name = "quantize", },
  155. { .name = NULL }
  156. };
  157. static const struct func global_num_func = {
  158. .name = ":num",
  159. .type = &t_int,
  160. };
  161. struct type t_string_array = {
  162. .ttype = T_ARRAY,
  163. .array = { .type = &t_char, .len = 64 }, /* TODO: tunable */
  164. };
  165. struct type t_string = {
  166. .ttype = T_TYPEDEF,
  167. .tdef = { .name = ":string", .type = &t_string_array },
  168. };
  169. static const struct func global_string_func = {
  170. .name = ":string",
  171. .type = &t_string,
  172. };
  173. static const struct func global_ident_func = {
  174. .name = ":ident",
  175. };
  176. static const struct func *global_sym_alloc_expr(struct node *n)
  177. {
  178. const struct func *func;
  179. int err;
  180. for (func = global_funcs; func->name; func++) {
  181. if (strcmp(func->name, n->expr.func))
  182. continue;
  183. return func;
  184. }
  185. return NULL;
  186. }
  187. int global_sym_alloc(struct prog *prog, struct node *n)
  188. {
  189. const struct func *func;
  190. struct symtab *st = prog->locals;
  191. int err;
  192. switch (n->ntype) {
  193. case N_EXPR:
  194. func = global_sym_alloc_expr(n);
  195. break;
  196. case N_IDENT:
  197. st = prog->globals;
  198. func = &global_ident_func;
  199. break;
  200. case N_NUM:
  201. func = &global_num_func;
  202. break;
  203. case N_STRING:
  204. func = &global_string_func;
  205. break;
  206. }
  207. if (!func)
  208. return -ENOENT;
  209. err = func_static_validate(func, n);
  210. if (err)
  211. return err;
  212. n->sym = sym_alloc(st, n, func);
  213. n->sym->type = func_return_type(func);
  214. return 0;
  215. }
  216. int global_probe(struct prog *prog)
  217. {
  218. return 0;
  219. }
  220. struct provider global = {
  221. .name = ":",
  222. .sym_alloc = global_sym_alloc,
  223. .probe = global_probe,
  224. };
  225. __attribute__((constructor))
  226. static void global_init(void)
  227. {
  228. provider_register(&global);
  229. }