2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012 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!");
63 type_init_common(struct arg_type_info *info, enum arg_type type)
71 struct arg_type_info *info;
76 type_init_struct(struct arg_type_info *info)
78 type_init_common(info, ARGTYPE_STRUCT);
79 VECT_INIT(&info->u.entries, struct struct_field);
83 type_struct_add(struct arg_type_info *info,
84 struct arg_type_info *field_info, int own)
86 assert(info->type == ARGTYPE_STRUCT);
87 struct struct_field field = { field_info, own };
88 return VECT_PUSHBACK(&info->u.entries, &field);
91 struct arg_type_info *
92 type_struct_get(struct arg_type_info *info, size_t idx)
94 assert(info->type == ARGTYPE_STRUCT);
95 struct struct_field *field = VECT_ELEMENT(&info->u.entries,
96 struct struct_field, idx);
103 type_struct_size(struct arg_type_info *info)
105 assert(info->type == ARGTYPE_STRUCT);
106 return vect_size(&info->u.entries);
110 struct_field_dtor(struct struct_field *field, void *data)
112 if (field->own_info) {
113 type_destroy(field->info);
119 type_struct_destroy(struct arg_type_info *info)
121 VECT_DESTROY(&info->u.entries, struct struct_field,
122 struct_field_dtor, NULL);
126 layout_struct(struct Process *proc, struct arg_type_info *info,
127 size_t *sizep, size_t *alignmentp, size_t *offsetofp)
130 size_t max_alignment = 0;
132 size_t offsetof_field = (size_t)-1;
133 if (offsetofp != NULL)
134 offsetof_field = *offsetofp;
136 assert(info->type == ARGTYPE_STRUCT);
137 for (i = 0; i < vect_size(&info->u.entries); ++i) {
138 struct struct_field *field
139 = VECT_ELEMENT(&info->u.entries,
140 struct struct_field, i);
142 size_t alignment = type_alignof(proc, field->info);
143 if (alignment == (size_t)-1)
146 /* Add padding to SZ to align the next element. */
147 sz = align(sz, alignment);
148 if (i == offsetof_field) {
150 if (sizep == NULL && alignmentp == NULL)
154 size_t size = type_sizeof(proc, field->info);
155 if (size == (size_t)-1)
159 if (alignment > max_alignment)
160 max_alignment = alignment;
163 if (max_alignment > 0)
164 sz = align(sz, max_alignment);
169 if (alignmentp != NULL)
170 *alignmentp = max_alignment;
176 type_init_array(struct arg_type_info *info,
177 struct arg_type_info *element_info, int own_info,
178 struct expr_node *length_expr, int own_length)
180 type_init_common(info, ARGTYPE_ARRAY);
181 info->u.array_info.elt_type = element_info;
182 info->u.array_info.own_info = own_info;
183 info->u.array_info.length = length_expr;
184 info->u.array_info.own_length = own_length;
188 type_array_destroy(struct arg_type_info *info)
190 if (info->u.array_info.own_info) {
191 type_destroy(info->u.array_info.elt_type);
192 free(info->u.array_info.elt_type);
194 if (info->u.array_info.own_length) {
195 expr_destroy(info->u.array_info.length);
196 free(info->u.array_info.length);
201 type_init_pointer(struct arg_type_info *info,
202 struct arg_type_info *pointee_info, int own_info)
204 type_init_common(info, ARGTYPE_POINTER);
205 info->u.ptr_info.info = pointee_info;
206 info->u.ptr_info.own_info = own_info;
210 type_pointer_destroy(struct arg_type_info *info)
212 if (info->u.ptr_info.own_info) {
213 type_destroy(info->u.ptr_info.info);
214 free(info->u.ptr_info.info);
219 type_destroy(struct arg_type_info *info)
224 switch (info->type) {
226 type_struct_destroy(info);
230 type_array_destroy(info);
233 case ARGTYPE_POINTER:
234 type_pointer_destroy(info);
250 if (info->own_lens) {
251 lens_destroy(info->lens);
256 #ifdef ARCH_HAVE_SIZEOF
257 size_t arch_type_sizeof(struct Process *proc, struct arg_type_info * arg);
260 arch_type_sizeof(struct Process *proc, struct arg_type_info * arg)
262 /* Use default value. */
267 #ifdef ARCH_HAVE_ALIGNOF
268 size_t arch_type_alignof(struct Process *proc, struct arg_type_info * arg);
271 arch_type_alignof(struct Process *proc, struct arg_type_info * arg)
273 /* Use default value. */
278 /* We need to support alignments that are not power of two. E.g. long
279 * double on x86 has alignment of 12. */
281 align(size_t sz, size_t alignment)
283 assert(alignment != 0);
285 if ((sz % alignment) != 0)
286 sz = ((sz / alignment) + 1) * alignment;
292 type_sizeof(struct Process *proc, struct arg_type_info *type)
294 size_t arch_size = arch_type_sizeof(proc, type);
295 if (arch_size != (size_t)-2)
298 switch (type->type) {
305 return sizeof(short);
316 return sizeof(float);
319 return sizeof(double);
322 if (layout_struct(proc, type, &size, NULL, NULL) < 0)
326 case ARGTYPE_POINTER:
327 return sizeof(void *);
330 if (expr_is_compile_constant(type->u.array_info.length)) {
332 if (expr_eval_constant(type->u.array_info.length,
336 struct arg_type_info *elt_ti
337 = type->u.array_info.elt_type;
339 size_t elt_size = type_sizeof(proc, elt_ti);
340 if (elt_size == (size_t)-1)
343 return ((size_t)l) * elt_size;
346 /* Flexible arrays don't count into the
359 #define alignof(field,st) ((size_t) ((char*) &st.field - (char*) &st))
362 type_alignof(struct Process *proc, struct arg_type_info *type)
364 size_t arch_alignment = arch_type_alignof(proc, type);
365 if (arch_alignment != (size_t)-2)
366 return arch_alignment;
368 struct { char c; char C; } cC;
369 struct { char c; short s; } cs;
370 struct { char c; int i; } ci;
371 struct { char c; long l; } cl;
372 struct { char c; void* p; } cp;
373 struct { char c; float f; } cf;
374 struct { char c; double d; } cd;
376 static size_t char_alignment = alignof(C, cC);
377 static size_t short_alignment = alignof(s, cs);
378 static size_t int_alignment = alignof(i, ci);
379 static size_t long_alignment = alignof(l, cl);
380 static size_t ptr_alignment = alignof(p, cp);
381 static size_t float_alignment = alignof(f, cf);
382 static size_t double_alignment = alignof(d, cd);
384 switch (type->type) {
388 return long_alignment;
390 return char_alignment;
393 return short_alignment;
395 return float_alignment;
397 return double_alignment;
398 case ARGTYPE_POINTER:
399 return ptr_alignment;
402 return type_alignof(proc, type->u.array_info.elt_type);
405 if (layout_struct(proc, type, NULL, &alignment, NULL) < 0)
410 return int_alignment;
415 type_offsetof(struct Process *proc, struct arg_type_info *type, size_t emt)
417 assert(type->type == ARGTYPE_STRUCT
418 || type->type == ARGTYPE_ARRAY);
420 switch (type->type) {
424 alignment = type_alignof(proc, type->u.array_info.elt_type);
425 if (alignment == (size_t)-1)
428 size = type_sizeof(proc, type->u.array_info.elt_type);
429 if (size == (size_t)-1)
432 return emt * align(size, alignment);
435 if (layout_struct(proc, type, NULL, NULL, &emt) < 0)
444 struct arg_type_info *
445 type_element(struct arg_type_info *info, size_t emt)
447 assert(info->type == ARGTYPE_STRUCT
448 || info->type == ARGTYPE_ARRAY);
450 switch (info->type) {
452 return info->u.array_info.elt_type;
455 assert(emt < type_struct_size(info));
456 return type_struct_get(info, emt);
464 type_aggregate_size(struct arg_type_info *info)
466 assert(info->type == ARGTYPE_STRUCT
467 || info->type == ARGTYPE_ARRAY);
469 switch (info->type) {
472 if (expr_eval_constant(info->u.array_info.length, &ret) < 0)
477 return type_struct_size(info);
485 type_is_integral(enum arg_type type)
502 case ARGTYPE_POINTER:
509 type_is_signed(enum arg_type type)
511 assert(type_is_integral(type));
515 return CHAR_MIN != 0;
532 case ARGTYPE_POINTER:
538 struct arg_type_info *
539 type_get_fp_equivalent(struct arg_type_info *info)
541 /* Extract innermost structure. Give up early if any
542 * component has more than one element. */
543 while (info->type == ARGTYPE_STRUCT) {
544 if (type_struct_size(info) != 1)
546 info = type_element(info, 0);
549 switch (info->type) {
559 case ARGTYPE_POINTER: