A dynamic tracer for Linux

global.c 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #define _GNU_SOURCE /* asprintf */
  2. #include <assert.h>
  3. #include <errno.h>
  4. #include <limits.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "arch.h"
  8. #include "func.h"
  9. #include "node.h"
  10. #include "ply.h"
  11. #include "sym.h"
  12. #include "type.h"
  13. /* :map */
  14. static struct type *global_map_ktype(struct node *n)
  15. {
  16. struct node *map, *key;
  17. struct type *ktype;
  18. struct tfield *kfields, *f;
  19. int i, nargs = node_nargs(n);
  20. char *kname;
  21. map = n->expr.args;
  22. if (nargs == 2)
  23. return map->next->sym->type;
  24. ktype = calloc(1, sizeof(*ktype));
  25. assert(ktype);
  26. kfields = calloc(nargs, sizeof(*kfields));
  27. assert(kfields);
  28. for (key = map->next, f = kfields, i = 0; key; key = key->next, f++, i++) {
  29. asprintf(&f->name, "k%d", i);
  30. f->type = key->sym->type;
  31. }
  32. asprintf(&ktype->sou.name, ":%s_key", map->ident.name);
  33. ktype->ttype = T_STRUCT;
  34. ktype->sou.fields = kfields;
  35. type_add(ktype);
  36. return ktype;
  37. }
  38. static int global_map_type_infer(const struct func *func, struct node *n)
  39. {
  40. struct node *map = n->expr.args;
  41. if (n->sym->type || !map->sym->type)
  42. return 0;
  43. assert(map->sym->type->ttype == T_MAP);
  44. /* given `m[key]` where m's type is known, infer that the
  45. * expression's type is equal to m's value type. */
  46. n->sym->type = map->sym->type->map.vtype;
  47. return 0;
  48. }
  49. static int global_map_static_validate(const struct func *func, struct node *n)
  50. {
  51. if (n->expr.args->ntype != N_IDENT) {
  52. _e("%#N: trying to lookup a key in %N, which is not a map.\n",
  53. n, n);
  54. return -EINVAL;
  55. }
  56. return 0;
  57. }
  58. /* :assign */
  59. static int global_assign_type_infer_map(struct node *n)
  60. {
  61. struct node *map, *key;
  62. struct type *ktype;
  63. map = n->expr.args;
  64. for (key = map->next; key; key = key->next) {
  65. if (type_sizeof(key->sym->type) < 0)
  66. return 0;
  67. }
  68. map->sym->type = type_map_of(global_map_ktype(n), n->sym->type);
  69. return 0;
  70. }
  71. static int global_assign_type_infer(const struct func *func, struct node *n)
  72. {
  73. struct node *lval, *rval;
  74. lval = n->expr.args;
  75. rval = lval->next;
  76. if (!rval->sym->type)
  77. return 0;
  78. if (!lval->sym->type) {
  79. /* given `a = b` where b's type is known but not a's,
  80. * infer that a's type must be equal to b's */
  81. lval->sym->type = rval->sym->type;
  82. if (node_is_map(lval))
  83. return global_assign_type_infer_map(lval);
  84. return 0;
  85. }
  86. if (type_compatible(lval->sym->type, rval->sym->type))
  87. return 0;
  88. _e("%#N: can't assign %N (type '%T'), to %N (type '%T').\n",
  89. n, rval, rval->sym->type, lval, lval->sym->type);
  90. return -EINVAL;
  91. }
  92. static int global_assign_static_validate(const struct func *func, struct node *n)
  93. {
  94. struct node *lval;
  95. lval = n->expr.args;
  96. if (node_is_map(lval) || (lval->ntype == N_IDENT))
  97. return 0;
  98. _e("%#N: can't assign a value to %N.\n", n, lval);
  99. return -EINVAL;
  100. }
  101. /* :binop */
  102. static int global_binop_type_infer(const struct func *func, struct node *n)
  103. {
  104. struct node *lval, *rval;
  105. lval = n->expr.args;
  106. rval = lval->next;
  107. if (n->sym->type || !lval->sym->type || !rval->sym->type)
  108. return 0;
  109. if (type_equal(lval->sym->type, rval->sym->type)) {
  110. n->sym->type = lval->sym->type;
  111. return 0;
  112. }
  113. /* TODO handle integer promotion */
  114. return 0;
  115. }
  116. /* pid */
  117. struct type t_pid = {
  118. .ttype = T_TYPEDEF,
  119. .tdef = { .name = ":pid", .type = &t_u32 },
  120. };
  121. struct type t_pid_func = {
  122. .ttype = T_FUNC,
  123. .func = { .type = &t_pid },
  124. };
  125. /* time */
  126. struct type t_time = {
  127. .ttype = T_TYPEDEF, /* TODO: should be a T_FUNC with a static
  128. * signature */
  129. .tdef = { .name = ":time", .type = &t_s64 },
  130. };
  131. struct type t_time_func = {
  132. .ttype = T_FUNC,
  133. .func = { .type = &t_time },
  134. };
  135. struct type t_block_func = {
  136. .ttype = T_FUNC,
  137. .func = { .type = &t_void, .vargs = 1 },
  138. };
  139. struct tfield f_2args[] = {
  140. { .type = &t_void },
  141. { .type = &t_void },
  142. { .type = NULL }
  143. };
  144. struct type t_2args_func = {
  145. .ttype = T_FUNC,
  146. .func = { .type = &t_void, .args = f_2args },
  147. };
  148. struct tfield f_1arg[] = {
  149. { .type = &t_void },
  150. { .type = NULL }
  151. };
  152. struct type t_1arg_func = {
  153. .ttype = T_FUNC,
  154. .func = { .type = &t_void, .args = f_1arg },
  155. };
  156. static const struct func global_funcs[] = {
  157. {
  158. .name = ":block",
  159. .type = &t_block_func,
  160. .static_ret = 1,
  161. },
  162. {
  163. .name = "+",
  164. .type = &t_2args_func,
  165. .type_infer = global_binop_type_infer,
  166. },
  167. {
  168. .name = "-",
  169. .type = &t_2args_func,
  170. .type_infer = global_binop_type_infer,
  171. },
  172. {
  173. .name = "=",
  174. .type = &t_2args_func,
  175. .type_infer = global_assign_type_infer,
  176. .static_validate = global_assign_static_validate,
  177. },
  178. {
  179. .name = "{}",
  180. /* .type = t_map_func, */
  181. .type_infer = global_map_type_infer,
  182. .static_validate = global_map_static_validate,
  183. },
  184. {
  185. .name = "pid",
  186. .type = &t_pid_func,
  187. .static_ret = 1,
  188. },
  189. {
  190. .name = "time",
  191. .type = &t_time_func,
  192. .static_ret = 1,
  193. },
  194. {
  195. .name = "quantize",
  196. .type = &t_1arg_func,
  197. },
  198. { .name = NULL }
  199. };
  200. static struct type *global_num_type(struct node *n)
  201. {
  202. if (n->num.unsignd) {
  203. if (n->num.u64 <= INT_MAX)
  204. return &t_int;
  205. else if (n->num.u64 <= UINT_MAX)
  206. return &t_uint;
  207. else if (n->num.u64 <= LONG_MAX)
  208. return &t_long;
  209. else if (n->num.u64 <= ULONG_MAX)
  210. return &t_ulong;
  211. else if (n->num.u64 <= LLONG_MAX)
  212. return &t_llong;
  213. else if (n->num.u64 <= ULLONG_MAX)
  214. return &t_ullong;
  215. } else {
  216. if (n->num.s64 >= INT_MIN && n->num.s64 <= INT_MAX)
  217. return &t_int;
  218. else if (n->num.s64 >= LONG_MIN && n->num.s64 <= LONG_MAX)
  219. return &t_long;
  220. else if (n->num.s64 >= LLONG_MIN && n->num.s64 <= LLONG_MAX)
  221. return &t_llong;
  222. }
  223. assert(0);
  224. return NULL;
  225. }
  226. static const struct func global_num_func = {
  227. .name = ":num",
  228. };
  229. struct type t_string_array = {
  230. .ttype = T_ARRAY,
  231. .array = { .type = &t_char, .len = 64 }, /* TODO: tunable */
  232. };
  233. struct type t_string = {
  234. .ttype = T_TYPEDEF,
  235. .tdef = { .name = ":string", .type = &t_string_array },
  236. };
  237. static const struct func global_string_func = {
  238. .name = ":string",
  239. .type = &t_string,
  240. .static_ret = 1,
  241. };
  242. static const struct func global_ident_func = {
  243. .name = ":ident",
  244. };
  245. static const struct func *global_sym_alloc_expr(struct node *n)
  246. {
  247. const struct func *func;
  248. int err;
  249. for (func = global_funcs; func->name; func++) {
  250. if (strcmp(func->name, n->expr.func))
  251. continue;
  252. return func;
  253. }
  254. return NULL;
  255. }
  256. int global_sym_alloc(struct prog *prog, struct node *n)
  257. {
  258. const struct func *func;
  259. struct symtab *st = prog->locals;
  260. int err;
  261. switch (n->ntype) {
  262. case N_EXPR:
  263. func = global_sym_alloc_expr(n);
  264. break;
  265. case N_IDENT:
  266. st = prog->globals;
  267. func = &global_ident_func;
  268. break;
  269. case N_NUM:
  270. func = &global_num_func;
  271. break;
  272. case N_STRING:
  273. func = &global_string_func;
  274. break;
  275. }
  276. if (!func)
  277. return -ENOENT;
  278. err = func_static_validate(func, n);
  279. if (err)
  280. return err;
  281. n->sym = sym_alloc(st, n, func);
  282. if (n->ntype == N_NUM)
  283. n->sym->type = global_num_type(n);
  284. else if (func->static_ret)
  285. n->sym->type = func_return_type(func);
  286. return 0;
  287. }
  288. int global_probe(struct prog *prog)
  289. {
  290. return 0;
  291. }
  292. struct provider global = {
  293. .name = ":",
  294. .sym_alloc = global_sym_alloc,
  295. .probe = global_probe,
  296. };
  297. __attribute__((constructor))
  298. static void global_init(void)
  299. {
  300. provider_register(&global);
  301. }