A dynamic tracer for Linux

type.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. #include <assert.h>
  2. #include <errno.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "type.h"
  7. void type_dump_func(struct type *t, FILE *fp)
  8. {
  9. struct tfield *arg;
  10. type_dump(t->func.type, fp);
  11. fputs(" (*)(", fp);
  12. if (!t->func.args) {
  13. fputs("void)", fp);
  14. return;
  15. }
  16. for (arg = t->func.args; arg->type != T_VOID; arg++) {
  17. if (arg != t->func.args)
  18. fputs(", ", fp);
  19. type_dump(arg->type, fp);
  20. }
  21. fputc(')', fp);
  22. }
  23. void type_dump(struct type *t, FILE *fp)
  24. {
  25. if (!t) {
  26. fputs("<NONE>", fp);
  27. return;
  28. }
  29. switch (t->ttype){
  30. case T_VOID:
  31. fputs("void", fp);
  32. break;
  33. case T_TYPEDEF:
  34. fputs(t->tdef.name, fp);
  35. break;
  36. case T_SCALAR:
  37. fputs(t->scalar.name, fp);
  38. break;
  39. case T_POINTER:
  40. type_dump(t->ptr.type, fp);
  41. fputs(" *", fp);
  42. break;
  43. case T_ARRAY:
  44. type_dump(t->array.type, fp);
  45. fprintf(fp, "[%zu]", t->array.len);
  46. break;
  47. case T_STRUCT:
  48. fputs("struct ", fp);
  49. fputs(t->sou.name, fp);
  50. break;
  51. case T_UNION:
  52. fputs("union ", fp);
  53. fputs(t->sou.name, fp);
  54. break;
  55. case T_FUNC:
  56. type_dump_func(t, fp);
  57. break;
  58. case T_MAP:
  59. fputs("map [", fp);
  60. type_dump(t->map.ktype, fp);
  61. fputs("] ", fp);
  62. type_dump(t->map.vtype, fp);
  63. break;
  64. }
  65. }
  66. void type_dump_cdecl_sou(struct type *t, FILE *fp)
  67. {
  68. struct tfield *f;
  69. type_dump(t, fp);
  70. fputs(" {\n", fp);
  71. for (f = t->sou.fields; f->type; f++) {
  72. fputc('\t', fp);
  73. type_dump(f->type, fp);
  74. fprintf(fp, " %s;\n", f->name);
  75. }
  76. fputs("}", fp);
  77. }
  78. void type_dump_cdecl(struct type *t, FILE *fp)
  79. {
  80. switch (t->ttype) {
  81. case T_TYPEDEF:
  82. fputs("typedef ", fp);
  83. type_dump(t->tdef.type, fp);
  84. fprintf(fp, " %s", t->tdef.name);
  85. break;
  86. case T_STRUCT:
  87. case T_UNION:
  88. type_dump_cdecl_sou(t, fp);
  89. break;
  90. case T_VOID:
  91. case T_SCALAR:
  92. case T_POINTER:
  93. case T_ARRAY:
  94. case T_MAP:
  95. case T_FUNC:
  96. type_dump(t, fp);
  97. break;
  98. }
  99. }
  100. /* void types_dump_cdecl(FILE *fp) */
  101. /* { */
  102. /* size_t i; */
  103. /* for (i = 0; i < types.len; i++) { */
  104. /* struct type *t = types.type[i]; */
  105. /* type_dump_cdecl(t, stdout); */
  106. /* printf(" <sz:0x%zx>\n", t->size); */
  107. /* } */
  108. /* } */
  109. /* struct type *type_map_of(struct type *ktype, struct type *vtype) */
  110. /* { */
  111. /* struct type *t; */
  112. /* size_t i; */
  113. /* for (i = 0; i < types.len; i++) { */
  114. /* t = types.type[i]; */
  115. /* if ((t->ttype == T_MAP) */
  116. /* && (t->map.ktype == ktype) */
  117. /* && (t->map.vtype == vtype)) */
  118. /* return t; */
  119. /* } */
  120. /* t = calloc(1, sizeof(*t)); */
  121. /* t->ttype = T_MAP; */
  122. /* t->map.vtype = vtype; */
  123. /* t->map.ktype = ktype; */
  124. /* type_add(t); */
  125. /* return t; */
  126. /* } */
  127. /* struct type *type_ptr_of(struct type *type) */
  128. /* { */
  129. /* struct type *t; */
  130. /* size_t i; */
  131. /* for (i = 0; i < types.len; i++) { */
  132. /* t = types.type[i]; */
  133. /* if ((t->ttype == T_POINTER) */
  134. /* && (t->pointer.type == type)) */
  135. /* return t; */
  136. /* } */
  137. /* t = calloc(1, sizeof(*t)); */
  138. /* t->ttype = T_POINTER; */
  139. /* t->pointer.type = type; */
  140. /* type_add(t); */
  141. /* return t; */
  142. /* } */
  143. struct type *type_normalize(struct type *t)
  144. {
  145. while (t->ttype == T_TYPEDEF)
  146. t = t->tdef.type;
  147. return t;
  148. }
  149. int type_equal(struct type *a, struct type *b)
  150. {
  151. /* TODO */
  152. return a == b;
  153. }
  154. int type_compatible(struct type *a, struct type *b)
  155. {
  156. a = type_normalize(a);
  157. b = type_normalize(b);
  158. if (a->ttype != b->ttype)
  159. return 0;
  160. switch (a->ttype){
  161. case T_VOID:
  162. case T_SCALAR:
  163. case T_POINTER:
  164. return 1;
  165. case T_ARRAY:
  166. if (a->array.len != b->array.len)
  167. return 0;
  168. return type_compatible(a->array.type, b->array.type);
  169. case T_STRUCT:
  170. case T_UNION:
  171. return !strcmp(a->sou.name, b->sou.name);
  172. case T_FUNC:
  173. return type_compatible(a->func.type, b->func.type);
  174. case T_MAP:
  175. return type_compatible(a->map.vtype, b->map.vtype);
  176. case T_TYPEDEF:
  177. assert(0);
  178. }
  179. assert(0);
  180. return 0;
  181. }
  182. /* void type_size_set_sou(struct type *t) */
  183. /* { */
  184. /* struct tfield *f; */
  185. /* size_t size = 0; */
  186. /* if (!t->sou.fields) */
  187. /* return; */
  188. /* for (f = t->sou.fields; f->name; f++) { */
  189. /* /\* size of all members is now known yet, abort *\/ */
  190. /* if (!f->type->size) */
  191. /* return; */
  192. /* if (!t->sou.packed) */
  193. /* size += size % f->type->size; */
  194. /* size += f->type->size; */
  195. /* f->offset = size; */
  196. /* } */
  197. /* if (!t->sou.packed && size) { */
  198. /* /\* align complete struct to requirements of first */
  199. /* * member, if struct keep going downwards *\/ */
  200. /* f = t->sou.fields; */
  201. /* while (f->type->ttype == T_STRUCT) */
  202. /* f = f->type->sou.fields; */
  203. /* size += size % f->type->size; */
  204. /* } */
  205. /* t->size = size; */
  206. /* } */
  207. /* void type_size_set(struct type *t) */
  208. /* { */
  209. /* switch (t->ttype) { */
  210. /* case T_TYPEDEF: */
  211. /* t->size = t->tdef.type->size; */
  212. /* break; */
  213. /* case T_STRUCT: */
  214. /* case T_UNION: */
  215. /* type_size_set_sou(t); */
  216. /* break; */
  217. /* case T_FUNC: */
  218. /* t->size = t->func.type->size; */
  219. /* assert(t->func.generate_ir); */
  220. /* break; */
  221. /* case T_SCALAR: */
  222. /* break; */
  223. /* case T_POINTER: */
  224. /* t->size = sizeof(void *); */
  225. /* break; */
  226. /* case T_ARRAY: */
  227. /* t->size = t->array.len * t->array.type->size; */
  228. /* break; */
  229. /* case T_MAP: */
  230. /* /\* map fds are s64:s *\/ */
  231. /* t->size = 8; */
  232. /* break; */
  233. /* } */
  234. /* } */
  235. static ssize_t type_alignof_union(struct type *t)
  236. {
  237. ssize_t amax = -EINVAL;
  238. struct tfield *f;
  239. for (f = t->sou.fields; f->type != T_VOID; f++) {
  240. ssize_t a;
  241. a = type_alignof(f->type);
  242. if (a < 0)
  243. return a;
  244. if (a > amax)
  245. amax = a;
  246. }
  247. return amax;
  248. }
  249. ssize_t type_alignof(struct type *t)
  250. {
  251. switch (t->ttype){
  252. case T_VOID:
  253. case T_SCALAR:
  254. case T_POINTER:
  255. case T_FUNC:
  256. case T_MAP:
  257. return type_sizeof(t);
  258. case T_TYPEDEF:
  259. return type_alignof(t->tdef.type);
  260. case T_ARRAY:
  261. return type_alignof(t->array.type);
  262. case T_STRUCT:
  263. if (!t->sou.fields)
  264. return type_alignof(&t_void);
  265. return type_alignof(t->sou.fields->type);
  266. case T_UNION:
  267. if (!t->sou.fields)
  268. return type_alignof(&t_void);
  269. return type_alignof_union(t);
  270. }
  271. return -EINVAL;
  272. }
  273. static ssize_t type_sizeof_struct(struct type *t)
  274. {
  275. struct tfield *f;
  276. size_t size = 0;
  277. ssize_t fsize;
  278. if (!t->sou.fields)
  279. return 0;
  280. for (f = t->sou.fields; f->name; f++) {
  281. /* size of all members is now known yet, abort */
  282. fsize = type_sizeof(f->type);
  283. if (fsize < 0)
  284. return fsize;
  285. size += fsize;
  286. if (!t->sou.packed)
  287. size += size % type_alignof(f->type);
  288. }
  289. if (!t->sou.packed && size)
  290. size += size % type_alignof(t);
  291. return size;
  292. }
  293. static ssize_t type_sizeof_union(struct type *t)
  294. {
  295. struct tfield *f;
  296. ssize_t size = 0;
  297. if (!t->sou.fields)
  298. return 0;
  299. for (f = t->sou.fields; f->name; f++) {
  300. ssize_t z, a;
  301. z = type_sizeof(f->type);
  302. a = t->sou.packed ? type_alignof(f->type) : 0;
  303. if ((z < 0) || (a < 0))
  304. return -EINVAL;
  305. z += z % a;
  306. if (z > size)
  307. size = z;
  308. }
  309. return size;
  310. }
  311. ssize_t type_sizeof(struct type *t)
  312. {
  313. switch (t->ttype){
  314. case T_VOID:
  315. return sizeof(void);
  316. case T_SCALAR:
  317. return t->scalar.size;
  318. case T_TYPEDEF:
  319. return type_sizeof(t->tdef.type);
  320. case T_POINTER:
  321. case T_FUNC:
  322. return sizeof(void *);
  323. case T_ARRAY:
  324. return t->array.len * type_sizeof(t->array.type);
  325. case T_STRUCT:
  326. return type_sizeof_struct(t);
  327. case T_UNION:
  328. return type_sizeof_union(t);
  329. case T_MAP:
  330. return sizeof(int);
  331. }
  332. return -EINVAL;
  333. }
  334. /* int type_walk_fields(struct tfield *f, twalk_fn pre, twalk_fn post, void *ctx) */
  335. /* { */
  336. /* if (!f) */
  337. /* return 0; */
  338. /* while (f->type != T_VOID) { */
  339. /* if (pre && (err = pre(f->type, ctx))) */
  340. /* return err; */
  341. /* err = type_walk(f->type, pre, post, ctx); */
  342. /* if (err) */
  343. /* return err; */
  344. /* if (post && (err = post(f->type, ctx))) */
  345. /* return err; */
  346. /* } */
  347. /* } */
  348. /* int type_walk(struct type *t, twalk_fn pre, twalk_fn post, void *ctx) */
  349. /* { */
  350. /* int err; */
  351. /* if (pre && (err = pre(t, ctx))) */
  352. /* return err; */
  353. /* switch (t->ttype){ */
  354. /* case T_VOID: */
  355. /* case T_SCALAR: */
  356. /* break; */
  357. /* case T_TYPEDEF: */
  358. /* err = type_walk(t->tdef.type, pre, post, ctx); */
  359. /* break; */
  360. /* case T_POINTER: */
  361. /* err = type_walk(t->ptr.type, pre, post, ctx); */
  362. /* break; */
  363. /* case T_ARRAY: */
  364. /* err = type_walk(t->array.type, pre, post, ctx); */
  365. /* break; */
  366. /* case T_STRUCT: */
  367. /* case T_UNION: */
  368. /* err = type_walk_fields(t->sou.fields, pre, post, ctx); */
  369. /* break; */
  370. /* case T_FUNC: */
  371. /* err = type_walk_fields(t->func.args, pre, post, ctx); */
  372. /* break; */
  373. /* case T_MAP: */
  374. /* err = type_walk(t->map.ktype, pre, post, ctx); */
  375. /* if (err) */
  376. /* break; */
  377. /* err = type_walk(t->map.vtype, pre, post, ctx); */
  378. /* break; */
  379. /* } */
  380. /* if (err) */
  381. /* return err; */
  382. /* if (post && (err = post(t, ctx))) */
  383. /* return err; */
  384. /* } */
  385. int all_types_cmp(const void *_a, const void *_b)
  386. {
  387. const struct type *a = *((struct type **)_a);
  388. const struct type *b = *((struct type **)_b);
  389. return a - b;
  390. }
  391. struct type_list {
  392. struct type **types;
  393. size_t len;
  394. } all_types;
  395. int type_add(struct type *t)
  396. {
  397. if (bsearch(t, all_types.types, all_types.len,
  398. sizeof(*all_types.types), all_types_cmp))
  399. return 0;
  400. /* type_size_set(t); */
  401. all_types.types = realloc(all_types.types,
  402. ++all_types.len * sizeof(*all_types.types));
  403. all_types.types[all_types.len - 1] = t;
  404. qsort(all_types.types, all_types.len, sizeof(*all_types.types), all_types_cmp);
  405. return 0;
  406. }
  407. int type_add_list(struct type **ts)
  408. {
  409. int err;
  410. for (; *ts; ts++) {
  411. err = type_add(*ts);
  412. if (err)
  413. return err;
  414. }
  415. return 0;
  416. }
  417. #define is_signed(_t) (((_t)(-1)) < 0)
  418. #define builtin_scalar(_t) { \
  419. .ttype = T_SCALAR, \
  420. .scalar = { \
  421. .name = #_t, \
  422. .size = sizeof(_t), \
  423. .is_signed = is_signed(_t), \
  424. }, \
  425. }
  426. struct type t_void = { .ttype = T_VOID };
  427. #pragma GCC diagnostic ignored "-Wtype-limits"
  428. /* is_signed will generate a warning for unsigned types since the
  429. * expression can never be true. this is exactly what we're interested
  430. * in here though. it gets us out of having to specify scalar
  431. * signedness per architecture. */
  432. struct type t_char = builtin_scalar(char);
  433. struct type t_schar = builtin_scalar(signed char);
  434. struct type t_uchar = builtin_scalar(unsigned char);
  435. struct type t_short = builtin_scalar(short);
  436. struct type t_sshort = builtin_scalar(signed short);
  437. struct type t_ushort = builtin_scalar(unsigned short);
  438. struct type t_int = builtin_scalar(int);
  439. struct type t_sint = builtin_scalar(signed int);
  440. struct type t_uint = builtin_scalar(unsigned int);
  441. struct type t_long = builtin_scalar(long);
  442. struct type t_slong = builtin_scalar(signed long);
  443. struct type t_ulong = builtin_scalar(unsigned long);
  444. struct type t_llong = builtin_scalar(long long);
  445. struct type t_sllong = builtin_scalar(signed long long);
  446. struct type t_ullong = builtin_scalar(unsigned long long);
  447. #pragma GCC diagnostic pop
  448. struct type *builtin_types[] = {
  449. &t_void,
  450. &t_char, &t_schar, &t_uchar,
  451. &t_short, &t_sshort, &t_ushort,
  452. &t_int, &t_sint, &t_uint,
  453. &t_long, &t_slong, &t_ulong,
  454. &t_llong, &t_sllong, &t_ullong,
  455. NULL
  456. };
  457. __attribute__((constructor))
  458. static void type_init(void)
  459. {
  460. type_add_list(builtin_types);
  461. }