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
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.
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.
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
31 struct arg_type_info *
32 type_get_simple(enum arg_type type)
35 static struct arg_type_info t = { T }; \
48 HANDLE(ARGTYPE_USHORT)
50 HANDLE(ARGTYPE_DOUBLE)
57 assert(!"Not a simple type!");
62 struct arg_type_info *
63 type_get_voidptr(void)
65 struct arg_type_info *void_info = type_get_simple(ARGTYPE_VOID);
66 static struct arg_type_info *ret;
68 static struct arg_type_info ptr_info;
69 type_init_pointer(&ptr_info, void_info, 0);
76 type_init_common(struct arg_type_info *info, enum arg_type type)
84 struct arg_type_info *info;
89 type_init_struct(struct arg_type_info *info)
91 type_init_common(info, ARGTYPE_STRUCT);
92 VECT_INIT(&info->u.entries, struct struct_field);
96 type_struct_add(struct arg_type_info *info,
97 struct arg_type_info *field_info, int own)
99 assert(info->type == ARGTYPE_STRUCT);
100 struct struct_field field = { field_info, own };
101 return VECT_PUSHBACK(&info->u.entries, &field);
104 struct arg_type_info *
105 type_struct_get(struct arg_type_info *info, size_t idx)
107 assert(info->type == ARGTYPE_STRUCT);
108 return VECT_ELEMENT(&info->u.entries, struct struct_field, idx)->info;
112 type_struct_size(struct arg_type_info *info)
114 assert(info->type == ARGTYPE_STRUCT);
115 return vect_size(&info->u.entries);
119 struct_field_dtor(struct struct_field *field, void *data)
121 if (field->own_info) {
122 type_destroy(field->info);
128 type_struct_destroy(struct arg_type_info *info)
130 VECT_DESTROY(&info->u.entries, struct struct_field,
131 struct_field_dtor, NULL);
135 layout_struct(struct process *proc, struct arg_type_info *info,
136 size_t *sizep, size_t *alignmentp, size_t *offsetofp)
139 size_t max_alignment = 0;
141 size_t offsetof_field = (size_t)-1;
142 if (offsetofp != NULL)
143 offsetof_field = *offsetofp;
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);
151 size_t alignment = type_alignof(proc, field->info);
152 if (alignment == (size_t)-1)
155 /* Add padding to SZ to align the next element. */
156 sz = align(sz, alignment);
157 if (i == offsetof_field) {
159 if (sizep == NULL && alignmentp == NULL)
163 size_t size = type_sizeof(proc, field->info);
164 if (size == (size_t)-1)
168 if (alignment > max_alignment)
169 max_alignment = alignment;
172 if (max_alignment > 0)
173 sz = align(sz, max_alignment);
178 if (alignmentp != NULL)
179 *alignmentp = max_alignment;
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)
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;
197 type_array_destroy(struct arg_type_info *info)
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);
203 if (info->u.array_info.own_length) {
204 expr_destroy(info->u.array_info.length);
205 free(info->u.array_info.length);
210 type_init_pointer(struct arg_type_info *info,
211 struct arg_type_info *pointee_info, int own_info)
213 type_init_common(info, ARGTYPE_POINTER);
214 info->u.ptr_info.info = pointee_info;
215 info->u.ptr_info.own_info = own_info;
219 type_pointer_destroy(struct arg_type_info *info)
221 if (info->u.ptr_info.own_info) {
222 type_destroy(info->u.ptr_info.info);
223 free(info->u.ptr_info.info);
228 type_destroy(struct arg_type_info *info)
233 switch (info->type) {
235 type_struct_destroy(info);
239 type_array_destroy(info);
242 case ARGTYPE_POINTER:
243 type_pointer_destroy(info);
259 if (info->own_lens) {
260 lens_destroy(info->lens);
266 type_alloc_and_clone(struct arg_type_info **retpp,
267 struct arg_type_info *info, int own)
271 *retpp = malloc(sizeof **retpp);
272 if (*retpp == NULL || type_clone(*retpp, info) < 0) {
280 static enum callback_status
281 clone_struct_add_field(const struct struct_field *field, void *data)
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) {
287 if (info != field->info)
292 if (type_struct_add(retp, info, field->own_info) < 0) {
302 type_clone(struct arg_type_info *retp, const struct arg_type_info *info)
304 switch (info->type) {
306 type_init_struct(retp);
307 if (VECT_EACH_CST(&info->u.entries, struct struct_field, NULL,
308 clone_struct_add_field, retp) != NULL) {
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)
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);
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)
331 type_init_pointer(retp, ninfo, info->u.ptr_info.own_info);
348 assert(!info->own_lens);
349 retp->lens = info->lens;
350 retp->own_lens = info->own_lens;
354 #ifdef ARCH_HAVE_SIZEOF
355 size_t arch_type_sizeof(struct process *proc, struct arg_type_info *arg);
358 arch_type_sizeof(struct process *proc, struct arg_type_info *arg)
360 /* Use default value. */
365 #ifdef ARCH_HAVE_ALIGNOF
366 size_t arch_type_alignof(struct process *proc, struct arg_type_info *arg);
369 arch_type_alignof(struct process *proc, struct arg_type_info *arg)
371 /* Use default value. */
376 /* We need to support alignments that are not power of two. E.g. long
377 * double on x86 has alignment of 12. */
379 align(size_t sz, size_t alignment)
381 assert(alignment != 0);
383 if ((sz % alignment) != 0)
384 sz = ((sz / alignment) + 1) * alignment;
390 type_sizeof(struct process *proc, struct arg_type_info *type)
392 size_t arch_size = arch_type_sizeof(proc, type);
393 if (arch_size != (size_t)-2)
396 switch (type->type) {
403 return sizeof(short);
414 return sizeof(float);
417 return sizeof(double);
420 if (layout_struct(proc, type, &size, NULL, NULL) < 0)
424 case ARGTYPE_POINTER:
425 return sizeof(void *);
428 if (expr_is_compile_constant(type->u.array_info.length)) {
430 if (expr_eval_constant(type->u.array_info.length,
434 struct arg_type_info *elt_ti
435 = type->u.array_info.elt_type;
437 size_t elt_size = type_sizeof(proc, elt_ti);
438 if (elt_size == (size_t)-1)
441 return ((size_t)l) * elt_size;
444 /* Flexible arrays don't count into the
457 #define alignof(field,st) ((size_t) ((char*) &st.field - (char*) &st))
460 type_alignof(struct process *proc, struct arg_type_info *type)
462 size_t arch_alignment = arch_type_alignof(proc, type);
463 if (arch_alignment != (size_t)-2)
464 return arch_alignment;
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;
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);
482 switch (type->type) {
486 return long_alignment;
488 return char_alignment;
491 return short_alignment;
493 return float_alignment;
495 return double_alignment;
496 case ARGTYPE_POINTER:
497 return ptr_alignment;
500 return type_alignof(proc, type->u.array_info.elt_type);
503 if (layout_struct(proc, type, NULL, &alignment, NULL) < 0)
508 return int_alignment;
513 type_offsetof(struct process *proc, struct arg_type_info *type, size_t emt)
515 assert(type->type == ARGTYPE_STRUCT
516 || type->type == ARGTYPE_ARRAY);
518 switch (type->type) {
522 alignment = type_alignof(proc, type->u.array_info.elt_type);
523 if (alignment == (size_t)-1)
526 size = type_sizeof(proc, type->u.array_info.elt_type);
527 if (size == (size_t)-1)
530 return emt * align(size, alignment);
533 if (layout_struct(proc, type, NULL, NULL, &emt) < 0)
542 struct arg_type_info *
543 type_element(struct arg_type_info *info, size_t emt)
545 assert(info->type == ARGTYPE_STRUCT
546 || info->type == ARGTYPE_ARRAY);
548 switch (info->type) {
550 return info->u.array_info.elt_type;
553 assert(emt < type_struct_size(info));
554 return type_struct_get(info, emt);
562 type_aggregate_size(struct arg_type_info *info)
564 assert(info->type == ARGTYPE_STRUCT
565 || info->type == ARGTYPE_ARRAY);
567 switch (info->type) {
570 if (expr_eval_constant(info->u.array_info.length, &ret) < 0)
575 return type_struct_size(info);
583 type_is_integral(enum arg_type type)
600 case ARGTYPE_POINTER:
607 type_is_signed(enum arg_type type)
609 assert(type_is_integral(type));
613 return CHAR_MIN != 0;
630 case ARGTYPE_POINTER:
636 struct arg_type_info *
637 type_get_fp_equivalent(struct arg_type_info *info)
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)
644 info = type_element(info, 0);
647 switch (info->type) {
657 case ARGTYPE_POINTER:
670 struct arg_type_info *
671 type_get_hfa_type(struct arg_type_info *info, size_t *countp)
673 assert(info != NULL);
674 if (info->type != ARGTYPE_STRUCT
675 && info->type != ARGTYPE_ARRAY)
678 size_t n = type_aggregate_size(info);
682 struct arg_type_info *ret = NULL;
686 struct arg_type_info *emt = type_element(info, n);
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);
694 if (emt->type != ARGTYPE_FLOAT
695 && emt->type != ARGTYPE_DOUBLE)
699 if (emt->type != ret->type)
701 *countp += emt_count;