A dynamic tracer for Linux

global.c 4.5KB

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