style whitespace changes
[platform/upstream/ltrace.git] / dwarf_prototypes.c
1 /* Copyright Dima Kogan <dima@secretsauce.net>
2  *
3  * This program is free software; you can redistribute it and/or modify it under
4  * the terms of version 2 of the GNU General Public License as published by the
5  * Free Software Foundation.
6  *
7  */
8 #include <stdio.h>
9 #include <elfutils/libdwfl.h>
10 #include <dwarf.h>
11 #include <stdlib.h>
12 #include <errno.h>
13 #include <string.h>
14
15 #include "config.h"
16 #include "prototype.h"
17 #include "type.h"
18 #include "param.h"
19 #include "dict.h"
20 #include "lens.h"
21 #include "lens_enum.h"
22 #include "value.h"
23 #include "expr.h"
24 #include "library.h"
25 #include "options.h"
26 #include "filter.h"
27 #include "debug.h"
28
29 #define complain(die, format, ...)                                      \
30         debug(DEBUG_FUNCTION, "%s() die '%s' @ 0x%lx: " format,         \
31               __func__, dwarf_diename(die), dwarf_dieoffset(die),       \
32               ##__VA_ARGS__)
33
34 #define NEXT_SIBLING(die)                                       \
35         int res = dwarf_siblingof(die, die);                    \
36         if (res == 0) continue;     /* sibling exists    */     \
37         if (res < 0)  return false; /* error             */     \
38         break                       /* no sibling exists */
39
40 static struct arg_type_info *get_type(int *newly_allocated_info,
41                                       Dwarf_Die *type_die,
42                                       struct protolib *plib,
43                                       struct dict *type_dieoffset_hash);
44
45
46
47
48 // debugging functions to dump types that I already parsed
49 #ifdef DUMP_PROTOTYPES
50 static bool _dump_ltrace_tree(const struct arg_type_info *info, int indent)
51 {
52         if (indent > 7) {
53                 fprintf(stderr, "%*s%p ...\n", indent*4, "", (void*)info);
54                 return true;
55         }
56
57         if (info == NULL) {
58                 fprintf(stderr, "%*s%p NULL\n", indent*4, "", (void*)info);
59                 return true;
60         }
61
62         switch (info->type) {
63         case ARGTYPE_VOID:
64                 fprintf(stderr, "%*s%p void\n", indent*4, "", (void*)info);
65                 break;
66
67         case ARGTYPE_INT:
68         case ARGTYPE_UINT:
69         case ARGTYPE_LONG:
70         case ARGTYPE_ULONG:
71         case ARGTYPE_CHAR:
72         case ARGTYPE_SHORT:
73         case ARGTYPE_USHORT:
74         case ARGTYPE_FLOAT:
75         case ARGTYPE_DOUBLE:
76                 fprintf(stderr, "%*s%p base\n", indent*4, "", (void*)info);
77                 break;
78
79         case ARGTYPE_ARRAY:
80                 fprintf(stderr, "%*s%p array. elements not printed\n", indent*4,
81                         "", (void*)info);
82                 break;
83
84         case ARGTYPE_POINTER:
85                 fprintf(stderr, "%*s%p pointer to...\n", indent*4,
86                         "", (void*)info);
87                 _dump_ltrace_tree(info->u.ptr_info.info, indent+1);
88                 break;
89
90         case ARGTYPE_STRUCT:
91                 fprintf(stderr, "%*s%p struct...\n", indent*4,
92                         "", (void*)info);
93                 struct struct_field
94                 {
95                         struct arg_type_info *info;
96                         int own_info;
97                 } *elements = (struct struct_field*)info->u.entries.data;
98                 unsigned int i;
99                 for(i=0; i<info->u.entries.size; i++)
100                         _dump_ltrace_tree(elements[i].info, indent+1);
101                 break;
102
103         default:
104                 fprintf(stderr, "%*s%p unknown type\n", indent*4,
105                         "", (void*)info);
106                 return false;;
107         }
108
109         return true;
110 }
111
112 static bool dump_ltrace_tree(const struct arg_type_info *info)
113 {
114         return _dump_ltrace_tree(info, 0);
115 }
116 #endif
117
118
119 // pulls a numerical value out of a particular attribute in a die. Returns true
120 // if successful. The result is returned in *result. Note that this is cast to
121 // (uint64_t), regardless of the actual type of the input
122 static bool get_die_numeric(uint64_t *result,
123                             Dwarf_Die *die, unsigned int attr_name)
124 {
125         Dwarf_Attribute attr ;
126
127         union {
128                 Dwarf_Word udata;
129                 Dwarf_Sword sdata;
130                 Dwarf_Addr addr;
131                 bool flag;
132         } u;
133
134         if (dwarf_attr(die, attr_name, &attr) == NULL)
135                 return false;
136
137         unsigned int form = dwarf_whatform(&attr);
138
139 #define PROCESS_NUMERIC(type)                           \
140         if (dwarf_form ## type(&attr, &u.type) != 0)    \
141                 return false;                           \
142         *result = (uint64_t)u.type;                     \
143         return true
144
145
146         switch (form) {
147         case DW_FORM_addr:
148                 PROCESS_NUMERIC(addr);
149
150         case DW_FORM_data1:
151         case DW_FORM_data2:
152         case DW_FORM_data4:
153         case DW_FORM_data8:
154         case DW_FORM_udata:
155                 PROCESS_NUMERIC(udata);
156
157         case DW_FORM_sdata:
158                 PROCESS_NUMERIC(sdata);
159
160         case DW_FORM_flag:
161                 PROCESS_NUMERIC(flag);
162
163         default:
164                 complain(die, "Unknown numeric form %d for attr_name: %d",
165                          form, attr_name);
166                 return false;
167         }
168 #undef PROCESS_NUMERIC
169 }
170
171 static bool get_integer_base_type(enum arg_type *type, int byte_size,
172                                   bool is_signed)
173 {
174         switch (byte_size) {
175         case sizeof(char):
176                 *type = ARGTYPE_CHAR;
177                 return true;
178
179         case sizeof(short):
180                 *type = is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT;
181                 return true;
182
183         case sizeof(int):
184                 *type = is_signed ? ARGTYPE_INT : ARGTYPE_UINT;
185                 return true;
186
187         case sizeof(long):
188                 *type = is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG;
189                 return true;
190
191         default:
192                 return false;
193         }
194 }
195
196 // returns an ltrace ARGTYPE_XXX base type from the given die. If we dont
197 // support a particular type (or an error occurred), I regturn ARGTYPE_VOID
198 static enum arg_type get_base_type(Dwarf_Die *die)
199 {
200         int64_t encoding;
201         if (!get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding))
202                 return ARGTYPE_VOID;
203
204         if (encoding == DW_ATE_void)
205                 return ARGTYPE_VOID;
206
207         if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char)
208                 return ARGTYPE_CHAR;
209
210         uint64_t byte_size;
211         if (!get_die_numeric(&byte_size, die, DW_AT_byte_size))
212                 return ARGTYPE_VOID;
213
214         if (encoding == DW_ATE_signed   ||
215             encoding == DW_ATE_unsigned ||
216             encoding == DW_ATE_boolean) {
217
218                 bool is_signed = (encoding == DW_ATE_signed);
219
220                 enum arg_type type;
221                 if (!get_integer_base_type(&type, (int)byte_size, is_signed)) {
222                         complain(die, "Unknown integer base type. "
223                                  "Using 'void'");
224                         return ARGTYPE_VOID;
225                 }
226                 return type;
227         }
228
229         if (encoding == DW_ATE_float) {
230                 switch (byte_size) {
231                 case sizeof(float):
232                         return ARGTYPE_FLOAT;
233
234                 case sizeof(double):
235                         return ARGTYPE_DOUBLE;
236
237                 default:
238                         // things like long doubles. ltrace has no support yet,
239                         // so I just say "void"
240                         return ARGTYPE_VOID;
241                 }
242         }
243
244 #if 0
245         if (encoding == DW_ATE_complex_float) {
246                 switch (byte_size) {
247                 case 2*sizeof(float):
248                         return ARGTYPE_FLOAT;
249
250                 case 2*sizeof(double):
251                         return ARGTYPE_DOUBLE;
252
253                 default:
254                         // things like long doubles. ltrace has no support yet,
255                         // so I just say "void"
256                         return ARGTYPE_VOID;
257                 }
258         }
259 #endif
260
261         // Unknown encoding. I just say void
262         complain(die, "Unknown base type. Returning 'void'");
263         return ARGTYPE_VOID;
264 }
265
266 static bool get_type_die(Dwarf_Die *type_die, Dwarf_Die *die)
267 {
268         Dwarf_Attribute attr;
269         return
270                 dwarf_attr(die, DW_AT_type, &attr) != NULL &&
271                 dwarf_formref_die(&attr, type_die) != NULL;
272 }
273
274
275
276 // type_dieoffset_hash dictionary callbacks
277 static size_t dwarf_die_hash(const void *x)
278 {
279         return *(const Dwarf_Off*)x;
280 }
281 static int dwarf_die_eq(const void *a, const void *b)
282 {
283         return *(const Dwarf_Off*)a == *(const Dwarf_Off*)b;
284 }
285
286
287 // returns a newly-allocated art_type_info*, or NULL on error
288 static struct arg_type_info *get_enum(Dwarf_Die *parent,
289                                       struct dict *type_dieoffset_hash)
290 {
291
292 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
293                 if (dupkey != NULL)                                     \
294                         free((void*)dupkey);                            \
295                 if (value != NULL) {                                    \
296                         value_destroy(value);                           \
297                         free(value);                                    \
298                 }                                                       \
299                 if (lens != NULL) {                                     \
300                         lens_destroy(&lens->super);                     \
301                         free(lens);                                     \
302                 }                                                       \
303                 if (result != NULL) {                                   \
304                         type_destroy(result);                           \
305                         free(result);                                   \
306                 }                                                       \
307                 dict_erase (type_dieoffset_hash, &die_offset, NULL,     \
308                             NULL, NULL);                                \
309                 dict_insert(type_dieoffset_hash, &die_offset,           \
310                             &(struct arg_type_info*){                   \
311                                     type_get_simple(ARGTYPE_VOID)});    \
312                 return ret;                                             \
313         } while (0)
314
315         struct arg_type_info *result = NULL;
316         struct enum_lens *lens = NULL;
317         const char *dupkey = NULL;
318         struct value *value = NULL;
319
320         Dwarf_Off die_offset = dwarf_dieoffset(parent);
321
322         result = calloc(1, sizeof(struct arg_type_info));
323         if (result == NULL) {
324                 complain(parent, "alloc error");
325                 CLEANUP_AND_RETURN_ERROR(NULL);
326         }
327
328         dict_insert(type_dieoffset_hash, &die_offset, &result);
329
330         uint64_t byte_size;
331         if (!get_die_numeric(&byte_size, parent, DW_AT_byte_size)) {
332                 // No byte size given, assume 'int'
333                 result->type = ARGTYPE_INT;
334         } else {
335                 if (!get_integer_base_type(&result->type,
336                                            (int)byte_size, true)) {
337                         complain(parent, "Unknown integer base type. "
338                                  "Using 'int'");
339                         result->type = ARGTYPE_INT;
340                 }
341         }
342
343         lens = calloc(1, sizeof(struct enum_lens));
344         if (lens == NULL) {
345                 complain(parent, "alloc error");
346                 CLEANUP_AND_RETURN_ERROR(NULL);
347         }
348         lens_init_enum(lens);
349         result->lens = &lens->super;
350         result->own_lens = 1;
351
352         Dwarf_Die die;
353         if (dwarf_child(parent, &die) != 0) {
354                 // empty enum. we're done
355                 CLEANUP_AND_RETURN_ERROR(NULL);
356         }
357
358
359         while (1) {
360                 complain(&die, "enum element: 0x%02x/'%s'", dwarf_tag(&die),
361                          dwarf_diename(&die));
362
363                 dupkey = NULL;
364                 value = NULL;
365
366                 if (dwarf_tag(&die) != DW_TAG_enumerator) {
367                         complain(&die, "Enums can have ONLY DW_TAG_enumerator "
368                                  "elements");
369                         CLEANUP_AND_RETURN_ERROR(NULL);
370                 }
371
372                 if (!dwarf_hasattr(&die, DW_AT_const_value)) {
373                         complain(&die, "Enums MUST have DW_AT_const_value "
374                                  "values");
375                         CLEANUP_AND_RETURN_ERROR(NULL);
376                 }
377
378                 const char *key = dwarf_diename(&die);
379                 if (key == NULL) {
380                         complain(&die, "Enums must have a DW_AT_name key");
381                         CLEANUP_AND_RETURN_ERROR(NULL);
382                 }
383                 dupkey = strdup(key);
384                 if (dupkey == NULL) {
385                         complain(&die, "Couldn't duplicate enum key");
386                         CLEANUP_AND_RETURN_ERROR(NULL);
387                 }
388
389                 value = calloc(1, sizeof(struct value));
390                 if (value == NULL) {
391                         complain(&die, "Couldn't alloc enum value");
392                         CLEANUP_AND_RETURN_ERROR(NULL);
393                 }
394
395                 value_init_detached(value, NULL, type_get_simple(result->type),
396                                     0);
397                 uint64_t enum_value;
398                 if (!get_die_numeric(&enum_value, &die, DW_AT_const_value)) {
399                         complain(&die, "Couldn't get enum value");
400                         CLEANUP_AND_RETURN_ERROR(NULL);
401                 }
402
403                 value_set_word(value, (long)enum_value);
404
405                 if (lens_enum_add(lens, dupkey, 1, value, 1)) {
406                         complain(&die, "Couldn't add enum element");
407                         CLEANUP_AND_RETURN_ERROR(NULL);
408                 }
409
410                 NEXT_SIBLING(&die);
411         }
412
413         return result;
414
415 #undef CLEANUP_AND_RETURN_ERROR
416 }
417
418 // returns a newly-allocated art_type_info*, or NULL on error
419 static struct arg_type_info *get_array(Dwarf_Die *parent,
420                                        struct protolib *plib,
421                                        struct dict *type_dieoffset_hash)
422 {
423
424 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
425                 if (length != NULL) {                                   \
426                         expr_destroy(length);                           \
427                         free(length);                                   \
428                 }                                                       \
429                 if (array_type != NULL && newly_allocated_array_type) { \
430                         type_destroy(array_type);                       \
431                         free(array_type);                               \
432                 }                                                       \
433                 if (result != NULL) {                                   \
434                         type_destroy(result);                           \
435                         free(result);                                   \
436                 }                                                       \
437                 dict_erase (type_dieoffset_hash, &die_offset,           \
438                             NULL, NULL, NULL);                          \
439                 dict_insert(type_dieoffset_hash, &die_offset,           \
440                             &(struct arg_type_info*){                   \
441                                     type_get_simple(ARGTYPE_VOID)});    \
442                 return ret;                                             \
443         } while (0)
444
445
446         struct arg_type_info *result = NULL;
447         struct expr_node *length = NULL;
448         struct arg_type_info *array_type = NULL;
449         int newly_allocated_array_type = 0;
450
451         Dwarf_Off die_offset = dwarf_dieoffset(parent);
452
453         result = calloc(1, sizeof(struct arg_type_info));
454         if (result == NULL) {
455                 complain(parent, "alloc error");
456                 CLEANUP_AND_RETURN_ERROR(NULL);
457         }
458
459         Dwarf_Die type_die;
460         if (!get_type_die(&type_die, parent)) {
461                 complain(parent, "Array has unknown type");
462                 CLEANUP_AND_RETURN_ERROR(NULL);
463         }
464
465         dict_insert(type_dieoffset_hash, &die_offset, &result);
466         array_type = get_type(&newly_allocated_array_type,
467                               &type_die, plib, type_dieoffset_hash);
468         if (array_type == NULL) {
469                 complain(parent, "Couldn't figure out array's type");
470                 CLEANUP_AND_RETURN_ERROR(NULL);
471         }
472
473         Dwarf_Die subrange;
474         if (dwarf_child(parent, &subrange) != 0) {
475                 complain(parent,
476                          "Array must have a DW_TAG_subrange_type child, "
477                          "but has none");
478                 CLEANUP_AND_RETURN_ERROR(NULL);
479         }
480
481         Dwarf_Die next_subrange;
482         if (dwarf_siblingof(&subrange, &next_subrange) <= 0) {
483                 complain(parent,
484                          "Array must have exactly one DW_TAG_subrange_type "
485                          "child");
486                 CLEANUP_AND_RETURN_ERROR(NULL);
487         }
488
489         if (dwarf_hasattr(&subrange, DW_AT_lower_bound)) {
490                 uint64_t lower_bound;
491                 if (!get_die_numeric(&lower_bound, &subrange,
492                                      DW_AT_lower_bound)) {
493                         complain(parent, "Couldn't read lower bound");
494                         CLEANUP_AND_RETURN_ERROR(NULL);
495                 }
496
497                 if (lower_bound != 0) {
498                         complain(parent,
499                                  "Array subrange has a nonzero lower bound. "
500                                  "Don't know what to do");
501                         CLEANUP_AND_RETURN_ERROR(NULL);
502                 }
503         }
504
505         uint64_t N;
506         if (!dwarf_hasattr(&subrange, DW_AT_upper_bound)) {
507                 // no upper bound is defined. This is probably a variable-width
508                 // array, and I don't know how long it is. Let's say 0 to be
509                 // safe
510                 N = 0;
511         }
512         else
513         {
514                 if (!get_die_numeric(&N, &subrange, DW_AT_upper_bound)) {
515                         complain(parent, "Couldn't read upper bound");
516                         CLEANUP_AND_RETURN_ERROR(NULL);
517                 }
518                 N++;
519         }
520
521         // I'm not checking the subrange type. It should be some sort of
522         // integer, and I don't know what it would mean for it to be something
523         // else
524         length = calloc(1, sizeof(struct expr_node));
525         if (length == NULL) {
526                 complain(&subrange, "Couldn't alloc length expr");
527                 CLEANUP_AND_RETURN_ERROR(NULL);
528         }
529         expr_init_const_word(length, N, type_get_simple(ARGTYPE_INT), 0);
530
531         type_init_array(result, array_type, newly_allocated_array_type,
532                         length, 1);
533         return result;
534
535 #undef CLEANUP_AND_RETURN_ERROR
536 }
537
538 // returns a newly-allocated art_type_info*, or NULL on error
539 static struct arg_type_info *get_structure(Dwarf_Die *parent,
540                                            struct protolib *plib,
541                                            struct dict *type_dieoffset_hash)
542 {
543
544 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
545                 if (member_type != NULL && newly_allocated_member_type) { \
546                         type_destroy(member_type);                      \
547                         free(member_type);                              \
548                 }                                                       \
549                 if (result != NULL) {                                   \
550                         type_destroy(result);                           \
551                         free(result);                                   \
552                 }                                                       \
553                 dict_erase (type_dieoffset_hash, &die_offset,           \
554                             NULL, NULL, NULL);                          \
555                 dict_insert(type_dieoffset_hash, &die_offset,           \
556                             &(struct arg_type_info*){                   \
557                                     type_get_simple(ARGTYPE_VOID)});    \
558                 return ret;                                             \
559         } while (0)
560
561
562         struct arg_type_info *result = NULL;
563         struct arg_type_info *member_type = NULL;
564         int newly_allocated_member_type = 0;
565
566         Dwarf_Off die_offset = dwarf_dieoffset(parent);
567
568         result = calloc(1, sizeof(struct arg_type_info));
569         if (result == NULL) {
570                 complain(parent, "alloc error");
571                 CLEANUP_AND_RETURN_ERROR(NULL);
572         }
573         type_init_struct(result);
574         dict_insert(type_dieoffset_hash, &die_offset, &result);
575
576         Dwarf_Die die;
577         if (dwarf_child(parent, &die) != 0) {
578                 // no elements; we're done
579                 return result;
580         }
581
582         while (1) {
583                 member_type = NULL;
584                 newly_allocated_member_type = 0;
585
586                 complain(&die, "member: 0x%02x", dwarf_tag(&die));
587
588                 if (dwarf_tag(&die) != DW_TAG_member) {
589                         complain(&die, "Structure can have ONLY DW_TAG_member");
590                         CLEANUP_AND_RETURN_ERROR(NULL);
591                 }
592
593                 Dwarf_Die type_die;
594                 if (!get_type_die(&type_die, &die)) {
595                         complain(&die, "Couldn't get type of element");
596                         CLEANUP_AND_RETURN_ERROR(NULL);
597                 }
598
599                 member_type = get_type(&newly_allocated_member_type,
600                                        &type_die, plib, type_dieoffset_hash);
601                 if (member_type == NULL) {
602                         complain(&die, "Couldn't parse type from DWARF data");
603                         CLEANUP_AND_RETURN_ERROR(NULL);
604                 }
605                 type_struct_add(result, member_type,
606                                 newly_allocated_member_type);
607
608                 NEXT_SIBLING(&die);
609         }
610
611         return result;
612 #undef CLEANUP_AND_RETURN_ERROR
613 }
614
615 // Reads the type in the die and returns the corresponding arg_type_info*. If
616 // this was newly allocated on the heap, *newly_allocated_info = true. If an
617 // error occurred, returns NULL
618 static struct arg_type_info *get_type(int *newly_allocated_result,
619                                       Dwarf_Die *type_die,
620                                       struct protolib *plib,
621                                       struct dict *type_dieoffset_hash)
622 {
623
624 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
625                 if (pointee != NULL && newly_allocated_pointee) {       \
626                         type_destroy(pointee);                          \
627                         free(pointee);                                  \
628                 }                                                       \
629                 if (result != NULL && *newly_allocated_result) {        \
630                         type_destroy(result);                           \
631                         free(result);                                   \
632                 }                                                       \
633                 dict_erase (type_dieoffset_hash, &die_offset,           \
634                             NULL, NULL, NULL);                          \
635                 dict_insert(type_dieoffset_hash, &die_offset,           \
636                             &(struct arg_type_info*){                   \
637                                     type_get_simple(ARGTYPE_VOID)});    \
638                 return ret;                                             \
639         } while (0)
640
641         struct arg_type_info *result = NULL;
642         struct arg_type_info *pointee = NULL;
643         int newly_allocated_pointee = 0;
644
645         Dwarf_Off die_offset = dwarf_dieoffset(type_die);
646
647
648         // by default, we say we allocated nothing. I set this to true later,
649         // when I allocate memory
650         *newly_allocated_result = 0;
651
652         struct arg_type_info **found_type = dict_find(type_dieoffset_hash,
653                                                       &die_offset);
654         if (found_type != NULL) {
655                 complain(type_die, "Read pre-computed type");
656                 return *found_type;
657         }
658
659         const char *type_name = dwarf_diename(type_die);
660         if (type_name != NULL) {
661
662                 struct named_type *already_defined_type =
663                         protolib_lookup_type(plib, type_name, true);
664
665                 if (already_defined_type != NULL) {
666                         complain(type_die,
667                                  "Type '%s' defined in a .conf file. "
668                                  "Using that instead of DWARF",
669                                  type_name);
670                         return already_defined_type->info;
671                 }
672         }
673
674         Dwarf_Die next_die;
675
676         switch (dwarf_tag(type_die)) {
677         case DW_TAG_base_type:
678                 complain(type_die, "Storing base type");
679                 result = type_get_simple(get_base_type(type_die));
680                 dict_insert(type_dieoffset_hash, &die_offset, &result);
681                 return result;
682
683         case DW_TAG_subroutine_type:
684         case DW_TAG_inlined_subroutine:
685                 // function pointers are stored as void*. If ltrace tries to
686                 // dereference these, it'll get a segfault
687                 complain(type_die, "Storing subroutine type");
688                 result = type_get_simple(ARGTYPE_VOID);
689                 dict_insert(type_dieoffset_hash, &die_offset, &result);
690                 return result;
691
692         case DW_TAG_pointer_type:
693                 if (!get_type_die(&next_die, type_die)) {
694                         // the pointed-to type isn't defined, so I report a
695                         // void*
696                         complain(type_die, "Storing void-pointer type");
697                         result = type_get_voidptr();
698                         dict_insert(type_dieoffset_hash, &die_offset, &result);
699                         return result;
700                 }
701
702                 complain(type_die, "Storing pointer type");
703
704                 *newly_allocated_result = 1;
705                 result = calloc(1, sizeof(struct arg_type_info));
706                 if (result == NULL) {
707                         complain(type_die, "alloc error");
708                         CLEANUP_AND_RETURN_ERROR(NULL);
709                 }
710                 dict_insert(type_dieoffset_hash, &die_offset, &result);
711                 pointee = get_type(&newly_allocated_pointee,
712                                    &next_die, plib, type_dieoffset_hash);
713                 if (pointee == NULL)
714                         CLEANUP_AND_RETURN_ERROR(NULL);
715
716                 type_init_pointer(result, pointee, newly_allocated_pointee);
717                 return result;
718
719         case DW_TAG_structure_type:
720                 complain(type_die, "Storing struct type");
721                 *newly_allocated_result = 1;
722
723                 result = get_structure(type_die, plib, type_dieoffset_hash);
724                 if (result == NULL)
725                         CLEANUP_AND_RETURN_ERROR(NULL);
726                 return result;
727
728
729         case DW_TAG_typedef:
730         case DW_TAG_const_type:
731         case DW_TAG_volatile_type:
732                 // Various tags are simply pass-through, so I just keep going
733                 if (get_type_die(&next_die, type_die)) {
734                         complain(type_die, "Storing const/typedef type");
735
736                         result = get_type(newly_allocated_result, &next_die,
737                                           plib, type_dieoffset_hash);
738                         if (result == NULL)
739                                 CLEANUP_AND_RETURN_ERROR(NULL);
740                 } else {
741                         // no type. Use 'void'. Normally I'd think this is
742                         // bogus, but stdio typedefs something to void
743                         result = type_get_simple(ARGTYPE_VOID);
744                         complain(type_die, "Storing void type");
745                 }
746                 dict_insert(type_dieoffset_hash, &die_offset, &result);
747                 return result;
748
749         case DW_TAG_enumeration_type:
750                 // We have an enumeration. This has a base type, but has a
751                 // particular lens to handle the enum
752                 *newly_allocated_result = 1;
753
754                 complain(type_die, "Storing enum int");
755                 result = get_enum(type_die, type_dieoffset_hash);
756                 if (result == NULL)
757                         CLEANUP_AND_RETURN_ERROR(NULL);
758                 return result;
759
760         case DW_TAG_array_type:
761                 *newly_allocated_result = 1;
762
763                 complain(type_die, "Storing array");
764                 result = get_array(type_die, plib, type_dieoffset_hash);
765                 if (result == NULL)
766                         CLEANUP_AND_RETURN_ERROR(NULL);
767                 return result;
768
769         case DW_TAG_union_type:
770                 result = type_get_simple(ARGTYPE_VOID);
771                 complain(type_die, "Storing union-as-void type");
772                 dict_insert(type_dieoffset_hash, &die_offset, &result);
773                 return result;
774
775         default:
776                 complain(type_die, "Unknown type tag 0x%x. Returning void",
777                          dwarf_tag(type_die));
778                 result = type_get_simple(ARGTYPE_VOID);
779                 dict_insert(type_dieoffset_hash, &die_offset, &result);
780                 return result;
781         }
782
783 #undef CLEANUP_AND_RETURN_ERROR
784 }
785
786 // fills in *proto with a prototype. Returns true on success
787 static bool get_prototype(struct prototype *result,
788                           Dwarf_Die *subroutine, struct protolib *plib,
789                           struct dict *type_dieoffset_hash)
790 {
791
792 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
793                 if (argument_type != NULL && newly_allocated_argument_type) { \
794                         type_destroy(argument_type);                    \
795                         free(argument_type);                            \
796                 }                                                       \
797                 prototype_destroy(result);                              \
798                 return ret;                                             \
799         } while (0)
800
801
802         struct arg_type_info *argument_type = NULL;
803         int newly_allocated_argument_type = 0;
804
805         prototype_init(result);
806
807         // First, look at the return type. This is stored in a DW_AT_type tag in
808         // the subroutine DIE. If there is no such tag, this function returns
809         // void
810         Dwarf_Die return_type_die;
811         if (!get_type_die(&return_type_die, subroutine)) {
812                 result->return_info = type_get_simple(ARGTYPE_VOID);
813                 result->own_return_info = 0;
814         } else {
815                 int newly_allocated_return_type;
816                 result->return_info = get_type(&newly_allocated_return_type,
817                                                &return_type_die, plib,
818                                                type_dieoffset_hash);
819                 if (result->return_info == NULL) {
820                         complain(subroutine, "Couldn't get return type");
821                         CLEANUP_AND_RETURN_ERROR(false);
822                 }
823                 result->own_return_info = newly_allocated_return_type;
824         }
825
826
827         // Now look at the arguments
828         Dwarf_Die arg_die;
829         if (dwarf_child(subroutine, &arg_die) != 0) {
830                 // no args. We're done
831                 return true;
832         }
833
834         while (1) {
835                 if (dwarf_tag(&arg_die) == DW_TAG_formal_parameter) {
836
837                         complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die));
838
839                         argument_type = NULL;
840                         newly_allocated_argument_type = false;
841
842                         Dwarf_Die type_die;
843                         if (!get_type_die(&type_die, &arg_die)) {
844                                 complain(&arg_die, "Couldn't get the argument "
845                                          "type die");
846                                 CLEANUP_AND_RETURN_ERROR(false);
847                         }
848
849
850                         argument_type = get_type(&newly_allocated_argument_type,
851                                                  &type_die, plib,
852                                                  type_dieoffset_hash);
853                         if (argument_type==NULL) {
854                                 complain(&arg_die, "Couldn't parse arg "
855                                          "type from DWARF data");
856                                 CLEANUP_AND_RETURN_ERROR(false);
857                         }
858
859                         struct param param;
860                         param_init_type(&param, argument_type,
861                                         newly_allocated_argument_type);
862                         if (prototype_push_param(result, &param) <0) {
863                                 complain(&arg_die, "couldn't add argument to "
864                                          "the prototype");
865                                 CLEANUP_AND_RETURN_ERROR(false);
866                         }
867
868 #ifdef DUMP_PROTOTYPES
869                         fprintf(stderr, "Adding argument:\n");
870                         dump_ltrace_tree(argument_type);
871 #endif
872                 }
873
874                 NEXT_SIBLING(&arg_die);
875         }
876
877         return true;
878 #undef CLEANUP_AND_RETURN_ERROR
879 }
880
881 static bool import_subprogram(struct protolib *plib, struct library *lib,
882                               struct dict *type_dieoffset_hash,
883                               Dwarf_Die *die)
884 {
885         // I use the linkage function name if there is one, otherwise the
886         // plain name
887         const char *function_name = NULL;
888         Dwarf_Attribute attr;
889         if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL)
890                 function_name = dwarf_formstring(&attr);
891         if (function_name == NULL)
892                 function_name = dwarf_diename(die);
893         if (function_name == NULL) {
894                 complain(die, "Function has no name. Not importing");
895                 return true;
896         }
897
898         if (!filter_matches_symbol(options.plt_filter,    function_name, lib) &&
899             !filter_matches_symbol(options.static_filter, function_name, lib) &&
900             !filter_matches_symbol(options.export_filter, function_name, lib)) {
901                 complain(die, "Prototype not requested by any filter");
902                 return true;
903         }
904
905         complain(die, "subroutine_type: 0x%02x; function '%s'",
906                  dwarf_tag(die), function_name);
907
908         struct prototype *proto_already_there =
909                 protolib_lookup_prototype(plib, function_name, false);
910
911         if (proto_already_there != NULL) {
912                 complain(die, "Prototype already exists. Skipping");
913                 return true;
914         }
915
916         struct prototype proto;
917         if (!get_prototype(&proto, die, plib, type_dieoffset_hash)) {
918                 complain(die, "couldn't get prototype");
919                 return false;
920         }
921
922         const char *function_name_dup = strdup(function_name);
923         if (function_name_dup == NULL) {
924                 complain(die, "couldn't strdup");
925                 prototype_destroy(&proto);
926                 return false;
927         }
928         protolib_add_prototype(plib, function_name_dup, 1, &proto);
929         return true;
930 }
931
932 static bool process_die_compileunit(struct protolib *plib, struct library *lib,
933                                     struct dict *type_dieoffset_hash,
934                                     Dwarf_Die *parent)
935 {
936         complain(parent, "Processing compile unit");
937         Dwarf_Die die;
938         if (dwarf_child(parent, &die) != 0) {
939                 // no child nodes, so nothing to do
940                 return true;
941         }
942
943         while (1) {
944                 if (dwarf_tag(&die) == DW_TAG_subprogram)
945                         if (!import_subprogram(plib, lib, type_dieoffset_hash,
946                                                &die))
947                                 complain(&die, "Error importing subprogram. "
948                                          "Skipping");
949
950                 NEXT_SIBLING(&die);
951         }
952
953         return true;
954 }
955
956 static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
957 {
958         // A map from DIE addresses (Dwarf_Off) to type structures (struct
959         // arg_type_info*). This is created and filled in at the start of each
960         // import, and deleted when the import is complete
961         struct dict type_dieoffset_hash;
962
963         dict_init(&type_dieoffset_hash, sizeof(Dwarf_Off),
964                   sizeof(struct arg_type_info*),
965                   dwarf_die_hash, dwarf_die_eq, NULL);
966
967         Dwarf_Addr bias;
968         Dwarf_Die *die = NULL;
969         while ((die = dwfl_nextcu(dwfl, die, &bias)) != NULL) {
970                 if (dwarf_tag(die) == DW_TAG_compile_unit)
971                         process_die_compileunit(plib, lib,
972                                                 &type_dieoffset_hash, die);
973                 else
974                         complain(die, "A DW_TAG_compile_unit die expected. "
975                                  "Skipping this one");
976         }
977
978         dict_destroy(&type_dieoffset_hash, NULL, NULL, NULL);
979 }
980
981 bool import_DWARF_prototypes(struct library *lib)
982 {
983         struct protolib *plib = lib->protolib;
984         Dwfl *dwfl = lib->dwfl;
985
986         debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
987               lib->soname);
988         if (plib == NULL) {
989
990                 const char *soname_dup = strdup(lib->soname);
991                 if (soname_dup == NULL) {
992                         fprintf(stderr, "couldn't strdup");
993                         return false;
994                 }
995
996                 plib = protolib_cache_default(&g_protocache, soname_dup, 1);
997                 if (plib == NULL) {
998                         fprintf(stderr, "Error loading protolib %s: %s.\n",
999                                 lib->soname, strerror(errno));
1000                 }
1001         }
1002
1003         import(plib, lib, dwfl);
1004         lib->protolib = plib;
1005
1006         return true;
1007 }