added forgotten error checking to some ltrace calls
[platform/upstream/ltrace.git] / type.c
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
4  * Copyright (C) 2007,2008 Juan Cespedes
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19  * 02110-1301 USA
20  */
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <limits.h>
25
26 #include "type.h"
27 #include "sysdep.h"
28 #include "expr.h"
29 #include "lens.h"
30
31 struct arg_type_info *
32 type_get_simple(enum arg_type type)
33 {
34 #define HANDLE(T) {                                     \
35                 static struct arg_type_info t = { T };  \
36         case T:                                         \
37                 return &t;                              \
38         }
39
40         switch (type) {
41         HANDLE(ARGTYPE_VOID)
42         HANDLE(ARGTYPE_INT)
43         HANDLE(ARGTYPE_UINT)
44         HANDLE(ARGTYPE_LONG)
45         HANDLE(ARGTYPE_ULONG)
46         HANDLE(ARGTYPE_CHAR)
47         HANDLE(ARGTYPE_SHORT)
48         HANDLE(ARGTYPE_USHORT)
49         HANDLE(ARGTYPE_FLOAT)
50         HANDLE(ARGTYPE_DOUBLE)
51
52 #undef HANDLE
53
54         case ARGTYPE_ARRAY:
55         case ARGTYPE_STRUCT:
56         case ARGTYPE_POINTER:
57                 assert(!"Not a simple type!");
58         };
59         abort();
60 }
61
62 struct arg_type_info *
63 type_get_voidptr(void)
64 {
65         struct arg_type_info *void_info = type_get_simple(ARGTYPE_VOID);
66         static struct arg_type_info *ret;
67         if (ret == NULL) {
68                 static struct arg_type_info ptr_info;
69                 type_init_pointer(&ptr_info, void_info, 0);
70                 ret = &ptr_info;
71         }
72         return ret;
73 }
74
75 static void
76 type_init_common(struct arg_type_info *info, enum arg_type type)
77 {
78         info->type = type;
79         info->lens = NULL;
80         info->own_lens = 0;
81 }
82
83 struct struct_field {
84         struct arg_type_info *info;
85         int own_info;
86 };
87
88 void
89 type_init_struct(struct arg_type_info *info)
90 {
91         type_init_common(info, ARGTYPE_STRUCT);
92         VECT_INIT(&info->u.entries, struct struct_field);
93 }
94
95 int
96 type_struct_add(struct arg_type_info *info,
97                 struct arg_type_info *field_info, int own)
98 {
99         assert(info->type == ARGTYPE_STRUCT);
100         struct struct_field field = { field_info, own };
101         return VECT_PUSHBACK(&info->u.entries, &field);
102 }
103
104 struct arg_type_info *
105 type_struct_get(struct arg_type_info *info, size_t idx)
106 {
107         assert(info->type == ARGTYPE_STRUCT);
108         return VECT_ELEMENT(&info->u.entries, struct struct_field, idx)->info;
109 }
110
111 size_t
112 type_struct_size(struct arg_type_info *info)
113 {
114         assert(info->type == ARGTYPE_STRUCT);
115         return vect_size(&info->u.entries);
116 }
117
118 static void
119 struct_field_dtor(struct struct_field *field, void *data)
120 {
121         if (field->own_info) {
122                 type_destroy(field->info);
123                 free(field->info);
124         }
125 }
126
127 static void
128 type_struct_destroy(struct arg_type_info *info)
129 {
130         VECT_DESTROY(&info->u.entries, struct struct_field,
131                      struct_field_dtor, NULL);
132 }
133
134 static int
135 layout_struct(struct process *proc, struct arg_type_info *info,
136               size_t *sizep, size_t *alignmentp, size_t *offsetofp)
137 {
138         size_t sz = 0;
139         size_t max_alignment = 0;
140         size_t i;
141         size_t offsetof_field = (size_t)-1;
142         if (offsetofp != NULL)
143                 offsetof_field = *offsetofp;
144
145         assert(info->type == ARGTYPE_STRUCT);
146         for (i = 0; i < vect_size(&info->u.entries); ++i) {
147                 struct struct_field *field
148                         = VECT_ELEMENT(&info->u.entries,
149                                        struct struct_field, i);
150
151                 size_t alignment = type_alignof(proc, field->info);
152                 if (alignment == (size_t)-1)
153                         return -1;
154
155                 /* Add padding to SZ to align the next element.  */
156                 sz = align(sz, alignment);
157                 if (i == offsetof_field) {
158                         *offsetofp = sz;
159                         if (sizep == NULL && alignmentp == NULL)
160                                 return 0;
161                 }
162
163                 size_t size = type_sizeof(proc, field->info);
164                 if (size == (size_t)-1)
165                         return -1;
166                 sz += size;
167
168                 if (alignment > max_alignment)
169                         max_alignment = alignment;
170         }
171
172         if (max_alignment > 0)
173                 sz = align(sz, max_alignment);
174
175         if (sizep != NULL)
176                 *sizep = sz;
177
178         if (alignmentp != NULL)
179                 *alignmentp = max_alignment;
180
181         return 0;
182 }
183
184 void
185 type_init_array(struct arg_type_info *info,
186                 struct arg_type_info *element_info, int own_info,
187                 struct expr_node *length_expr, int own_length)
188 {
189         type_init_common(info, ARGTYPE_ARRAY);
190         info->u.array_info.elt_type = element_info;
191         info->u.array_info.own_info = own_info;
192         info->u.array_info.length = length_expr;
193         info->u.array_info.own_length = own_length;
194 }
195
196 static void
197 type_array_destroy(struct arg_type_info *info)
198 {
199         if (info->u.array_info.own_info) {
200                 type_destroy(info->u.array_info.elt_type);
201                 free(info->u.array_info.elt_type);
202         }
203         if (info->u.array_info.own_length) {
204                 expr_destroy(info->u.array_info.length);
205                 free(info->u.array_info.length);
206         }
207 }
208
209 void
210 type_init_pointer(struct arg_type_info *info,
211                   struct arg_type_info *pointee_info, int own_info)
212 {
213         type_init_common(info, ARGTYPE_POINTER);
214         info->u.ptr_info.info = pointee_info;
215         info->u.ptr_info.own_info = own_info;
216 }
217
218 static void
219 type_pointer_destroy(struct arg_type_info *info)
220 {
221         if (info->u.ptr_info.own_info) {
222                 type_destroy(info->u.ptr_info.info);
223                 free(info->u.ptr_info.info);
224         }
225 }
226
227 void
228 type_destroy(struct arg_type_info *info)
229 {
230         if (info == NULL)
231                 return;
232
233         switch (info->type) {
234         case ARGTYPE_STRUCT:
235                 type_struct_destroy(info);
236                 break;
237
238         case ARGTYPE_ARRAY:
239                 type_array_destroy(info);
240                 break;
241
242         case ARGTYPE_POINTER:
243                 type_pointer_destroy(info);
244                 break;
245
246         case ARGTYPE_VOID:
247         case ARGTYPE_INT:
248         case ARGTYPE_UINT:
249         case ARGTYPE_LONG:
250         case ARGTYPE_ULONG:
251         case ARGTYPE_CHAR:
252         case ARGTYPE_SHORT:
253         case ARGTYPE_USHORT:
254         case ARGTYPE_FLOAT:
255         case ARGTYPE_DOUBLE:
256                 break;
257         }
258
259         if (info->own_lens) {
260                 lens_destroy(info->lens);
261                 free(info->lens);
262         }
263 }
264
265 static int
266 type_alloc_and_clone(struct arg_type_info **retpp,
267                      struct arg_type_info *info, int own)
268 {
269         *retpp = info;
270         if (own) {
271                 *retpp = malloc(sizeof **retpp);
272                 if (*retpp == NULL || type_clone(*retpp, info) < 0) {
273                         free(*retpp);
274                         return -1;
275                 }
276         }
277         return 0;
278 }
279
280 static enum callback_status
281 clone_struct_add_field(const struct struct_field *field, void *data)
282 {
283         struct arg_type_info *retp = data;
284         struct arg_type_info *info;
285         if (type_alloc_and_clone(&info, field->info, field->own_info) < 0) {
286         fail:
287                 if (info != field->info)
288                         free(info);
289                 return CBS_STOP;
290         }
291
292         if (type_struct_add(retp, info, field->own_info) < 0) {
293                 if (field->own_info)
294                         type_destroy(info);
295                 goto fail;
296         }
297
298         return CBS_CONT;
299 }
300
301 int
302 type_clone(struct arg_type_info *retp, const struct arg_type_info *info)
303 {
304         switch (info->type) {
305         case ARGTYPE_STRUCT:
306                 type_init_struct(retp);
307                 if (VECT_EACH_CST(&info->u.entries, struct struct_field, NULL,
308                                   clone_struct_add_field, retp) != NULL) {
309                         type_destroy(retp);
310                         return -1;
311                 }
312                 break;
313
314         case ARGTYPE_ARRAY:;
315                 struct arg_type_info *elt_type;
316                 if (type_alloc_and_clone(&elt_type, info->u.array_info.elt_type,
317                                          info->u.array_info.own_info) < 0)
318                         return -1;
319
320                 assert(!info->u.array_info.own_length); // XXXXXXX
321                 type_init_array(retp, elt_type, info->u.array_info.own_info,
322                                 info->u.array_info.length,
323                                 info->u.array_info.own_length);
324                 break;
325
326         case ARGTYPE_POINTER:;
327                 struct arg_type_info *ninfo;
328                 if (type_alloc_and_clone(&ninfo, info->u.ptr_info.info,
329                                          info->u.ptr_info.own_info) < 0)
330                         return -1;
331                 type_init_pointer(retp, ninfo, info->u.ptr_info.own_info);
332                 break;
333
334         case ARGTYPE_VOID:
335         case ARGTYPE_INT:
336         case ARGTYPE_UINT:
337         case ARGTYPE_LONG:
338         case ARGTYPE_ULONG:
339         case ARGTYPE_CHAR:
340         case ARGTYPE_SHORT:
341         case ARGTYPE_USHORT:
342         case ARGTYPE_FLOAT:
343         case ARGTYPE_DOUBLE:
344                 *retp = *info;
345                 break;
346         }
347
348         assert(!info->own_lens);
349         retp->lens = info->lens;
350         retp->own_lens = info->own_lens;
351         return 0;
352 }
353
354 #ifdef ARCH_HAVE_SIZEOF
355 size_t arch_type_sizeof(struct process *proc, struct arg_type_info *arg);
356 #else
357 size_t
358 arch_type_sizeof(struct process *proc, struct arg_type_info *arg)
359 {
360         /* Use default value.  */
361         return (size_t)-2;
362 }
363 #endif
364
365 #ifdef ARCH_HAVE_ALIGNOF
366 size_t arch_type_alignof(struct process *proc, struct arg_type_info *arg);
367 #else
368 size_t
369 arch_type_alignof(struct process *proc, struct arg_type_info *arg)
370 {
371         /* Use default value.  */
372         return (size_t)-2;
373 }
374 #endif
375
376 /* We need to support alignments that are not power of two.  E.g. long
377  * double on x86 has alignment of 12.  */
378 size_t
379 align(size_t sz, size_t alignment)
380 {
381         assert(alignment != 0);
382
383         if ((sz % alignment) != 0)
384                 sz = ((sz / alignment) + 1) * alignment;
385
386         return sz;
387 }
388
389 size_t
390 type_sizeof(struct process *proc, struct arg_type_info *type)
391 {
392         size_t arch_size = arch_type_sizeof(proc, type);
393         if (arch_size != (size_t)-2)
394                 return arch_size;
395
396         switch (type->type) {
397                 size_t size;
398         case ARGTYPE_CHAR:
399                 return sizeof(char);
400
401         case ARGTYPE_SHORT:
402         case ARGTYPE_USHORT:
403                 return sizeof(short);
404
405         case ARGTYPE_INT:
406         case ARGTYPE_UINT:
407                 return sizeof(int);
408
409         case ARGTYPE_LONG:
410         case ARGTYPE_ULONG:
411                 return sizeof(long);
412
413         case ARGTYPE_FLOAT:
414                 return sizeof(float);
415
416         case ARGTYPE_DOUBLE:
417                 return sizeof(double);
418
419         case ARGTYPE_STRUCT:
420                 if (layout_struct(proc, type, &size, NULL, NULL) < 0)
421                         return (size_t)-1;
422                 return size;
423
424         case ARGTYPE_POINTER:
425                 return sizeof(void *);
426
427         case ARGTYPE_ARRAY:
428                 if (expr_is_compile_constant(type->u.array_info.length)) {
429                         long l;
430                         if (expr_eval_constant(type->u.array_info.length,
431                                                &l) < 0)
432                                 return -1;
433
434                         struct arg_type_info *elt_ti
435                                 = type->u.array_info.elt_type;
436
437                         size_t elt_size = type_sizeof(proc, elt_ti);
438                         if (elt_size == (size_t)-1)
439                                 return (size_t)-1;
440
441                         return ((size_t)l) * elt_size;
442
443                 } else {
444                         /* Flexible arrays don't count into the
445                          * sizeof.  */
446                         return 0;
447                 }
448
449         case ARGTYPE_VOID:
450                 return 0;
451         }
452
453         abort();
454 }
455
456 #undef alignof
457 #define alignof(field,st) ((size_t) ((char*) &st.field - (char*) &st))
458
459 size_t
460 type_alignof(struct process *proc, struct arg_type_info *type)
461 {
462         size_t arch_alignment = arch_type_alignof(proc, type);
463         if (arch_alignment != (size_t)-2)
464                 return arch_alignment;
465
466         struct { char c; char C; } cC;
467         struct { char c; short s; } cs;
468         struct { char c; int i; } ci;
469         struct { char c; long l; } cl;
470         struct { char c; void* p; } cp;
471         struct { char c; float f; } cf;
472         struct { char c; double d; } cd;
473
474         static size_t char_alignment = alignof(C, cC);
475         static size_t short_alignment = alignof(s, cs);
476         static size_t int_alignment = alignof(i, ci);
477         static size_t long_alignment = alignof(l, cl);
478         static size_t ptr_alignment = alignof(p, cp);
479         static size_t float_alignment = alignof(f, cf);
480         static size_t double_alignment = alignof(d, cd);
481
482         switch (type->type) {
483                 size_t alignment;
484         case ARGTYPE_LONG:
485         case ARGTYPE_ULONG:
486                 return long_alignment;
487         case ARGTYPE_CHAR:
488                 return char_alignment;
489         case ARGTYPE_SHORT:
490         case ARGTYPE_USHORT:
491                 return short_alignment;
492         case ARGTYPE_FLOAT:
493                 return float_alignment;
494         case ARGTYPE_DOUBLE:
495                 return double_alignment;
496         case ARGTYPE_POINTER:
497                 return ptr_alignment;
498
499         case ARGTYPE_ARRAY:
500                 return type_alignof(proc, type->u.array_info.elt_type);
501
502         case ARGTYPE_STRUCT:
503                 if (layout_struct(proc, type, NULL, &alignment, NULL) < 0)
504                         return (size_t)-1;
505                 return alignment;
506
507         default:
508                 return int_alignment;
509         }
510 }
511
512 size_t
513 type_offsetof(struct process *proc, struct arg_type_info *type, size_t emt)
514 {
515         assert(type->type == ARGTYPE_STRUCT
516                || type->type == ARGTYPE_ARRAY);
517
518         switch (type->type) {
519                 size_t alignment;
520                 size_t size;
521         case ARGTYPE_ARRAY:
522                 alignment = type_alignof(proc, type->u.array_info.elt_type);
523                 if (alignment == (size_t)-1)
524                         return (size_t)-1;
525
526                 size = type_sizeof(proc, type->u.array_info.elt_type);
527                 if (size == (size_t)-1)
528                         return (size_t)-1;
529
530                 return emt * align(size, alignment);
531
532         case ARGTYPE_STRUCT:
533                 if (layout_struct(proc, type, NULL, NULL, &emt) < 0)
534                         return (size_t)-1;
535                 return emt;
536
537         default:
538                 abort();
539         }
540 }
541
542 struct arg_type_info *
543 type_element(struct arg_type_info *info, size_t emt)
544 {
545         assert(info->type == ARGTYPE_STRUCT
546                || info->type == ARGTYPE_ARRAY);
547
548         switch (info->type) {
549         case ARGTYPE_ARRAY:
550                 return info->u.array_info.elt_type;
551
552         case ARGTYPE_STRUCT:
553                 assert(emt < type_struct_size(info));
554                 return type_struct_get(info, emt);
555
556         default:
557                 abort();
558         }
559 }
560
561 size_t
562 type_aggregate_size(struct arg_type_info *info)
563 {
564         assert(info->type == ARGTYPE_STRUCT
565                || info->type == ARGTYPE_ARRAY);
566
567         switch (info->type) {
568                 long ret;
569         case ARGTYPE_ARRAY:
570                 if (expr_eval_constant(info->u.array_info.length, &ret) < 0)
571                         return (size_t)-1;
572                 return (size_t)ret;
573
574         case ARGTYPE_STRUCT:
575                 return type_struct_size(info);
576
577         default:
578                 abort();
579         }
580 }
581
582 int
583 type_is_integral(enum arg_type type)
584 {
585         switch (type) {
586         case ARGTYPE_INT:
587         case ARGTYPE_UINT:
588         case ARGTYPE_LONG:
589         case ARGTYPE_ULONG:
590         case ARGTYPE_CHAR:
591         case ARGTYPE_SHORT:
592         case ARGTYPE_USHORT:
593                 return 1;
594
595         case ARGTYPE_VOID:
596         case ARGTYPE_FLOAT:
597         case ARGTYPE_DOUBLE:
598         case ARGTYPE_ARRAY:
599         case ARGTYPE_STRUCT:
600         case ARGTYPE_POINTER:
601                 return 0;
602         }
603         abort();
604 }
605
606 int
607 type_is_signed(enum arg_type type)
608 {
609         assert(type_is_integral(type));
610
611         switch (type) {
612         case ARGTYPE_CHAR:
613                 return CHAR_MIN != 0;
614
615         case ARGTYPE_SHORT:
616         case ARGTYPE_INT:
617         case ARGTYPE_LONG:
618                 return 1;
619
620         case ARGTYPE_UINT:
621         case ARGTYPE_ULONG:
622         case ARGTYPE_USHORT:
623                 return 0;
624
625         case ARGTYPE_VOID:
626         case ARGTYPE_FLOAT:
627         case ARGTYPE_DOUBLE:
628         case ARGTYPE_ARRAY:
629         case ARGTYPE_STRUCT:
630         case ARGTYPE_POINTER:
631                 abort();
632         }
633         abort();
634 }
635
636 struct arg_type_info *
637 type_get_fp_equivalent(struct arg_type_info *info)
638 {
639         /* Extract innermost structure.  Give up early if any
640          * component has more than one element.  */
641         while (info->type == ARGTYPE_STRUCT) {
642                 if (type_struct_size(info) != 1)
643                         return NULL;
644                 info = type_element(info, 0);
645         }
646
647         switch (info->type) {
648         case ARGTYPE_CHAR:
649         case ARGTYPE_SHORT:
650         case ARGTYPE_INT:
651         case ARGTYPE_LONG:
652         case ARGTYPE_UINT:
653         case ARGTYPE_ULONG:
654         case ARGTYPE_USHORT:
655         case ARGTYPE_VOID:
656         case ARGTYPE_ARRAY:
657         case ARGTYPE_POINTER:
658                 return NULL;
659
660         case ARGTYPE_FLOAT:
661         case ARGTYPE_DOUBLE:
662                 return info;
663
664         case ARGTYPE_STRUCT:
665                 abort();
666         }
667         abort();
668 }
669
670 struct arg_type_info *
671 type_get_hfa_type(struct arg_type_info *info, size_t *countp)
672 {
673         assert(info != NULL);
674         if (info->type != ARGTYPE_STRUCT
675             && info->type != ARGTYPE_ARRAY)
676                 return NULL;
677
678         size_t n = type_aggregate_size(info);
679         if (n == (size_t)-1)
680                 return NULL;
681
682         struct arg_type_info *ret = NULL;
683         *countp = 0;
684
685         while (n-- > 0) {
686                 struct arg_type_info *emt = type_element(info, n);
687
688                 size_t emt_count = 1;
689                 if (emt->type == ARGTYPE_STRUCT || emt->type == ARGTYPE_ARRAY)
690                         emt = type_get_hfa_type(emt, &emt_count);
691                 if (emt == NULL)
692                         return NULL;
693                 if (ret == NULL) {
694                         if (emt->type != ARGTYPE_FLOAT
695                             && emt->type != ARGTYPE_DOUBLE)
696                                 return NULL;
697                         ret = emt;
698                 }
699                 if (emt->type != ret->type)
700                         return NULL;
701                 *countp += emt_count;
702         }
703         return ret;
704 }