I now always build the export list
[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         // not using a switch() here because sizeof(int) == sizeof(long) on some
175         // architectures, and removing that case for those arches is a pain
176         if (byte_size == sizeof(char)) {
177                 *type = ARGTYPE_CHAR;
178                 return true;
179         }
180
181         if (byte_size == sizeof(short)) {
182                 *type = is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT;
183                 return true;
184         }
185
186         if (byte_size == sizeof(int)) {
187                 *type = is_signed ? ARGTYPE_INT : ARGTYPE_UINT;
188                 return true;
189         }
190
191         if (byte_size == sizeof(long)) {
192                 *type = is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG;
193                 return true;
194         }
195
196         return false;
197 }
198
199 // returns an ltrace ARGTYPE_XXX base type from the given die. If we dont
200 // support a particular type (or an error occurred), I regturn ARGTYPE_VOID
201 static enum arg_type get_base_type(Dwarf_Die *die)
202 {
203         uint64_t encoding;
204         if (!get_die_numeric(&encoding, die, DW_AT_encoding))
205                 return ARGTYPE_VOID;
206
207         if (encoding == DW_ATE_void)
208                 return ARGTYPE_VOID;
209
210         if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char)
211                 return ARGTYPE_CHAR;
212
213         uint64_t byte_size;
214         if (!get_die_numeric(&byte_size, die, DW_AT_byte_size))
215                 return ARGTYPE_VOID;
216
217         if (encoding == DW_ATE_signed   ||
218             encoding == DW_ATE_unsigned ||
219             encoding == DW_ATE_boolean) {
220
221                 bool is_signed = (encoding == DW_ATE_signed);
222
223                 enum arg_type type;
224                 if (!get_integer_base_type(&type, (int)byte_size, is_signed)) {
225                         complain(die, "Unknown integer base type. "
226                                  "Using 'void'");
227                         return ARGTYPE_VOID;
228                 }
229                 return type;
230         }
231
232         if (encoding == DW_ATE_float) {
233                 switch (byte_size) {
234                 case sizeof(float):
235                         return ARGTYPE_FLOAT;
236
237                 case sizeof(double):
238                         return ARGTYPE_DOUBLE;
239
240                 default:
241                         // things like long doubles. ltrace has no support yet,
242                         // so I just say "void"
243                         return ARGTYPE_VOID;
244                 }
245         }
246
247 #if 0
248         if (encoding == DW_ATE_complex_float) {
249                 switch (byte_size) {
250                 case 2*sizeof(float):
251                         return ARGTYPE_FLOAT;
252
253                 case 2*sizeof(double):
254                         return ARGTYPE_DOUBLE;
255
256                 default:
257                         // things like long doubles. ltrace has no support yet,
258                         // so I just say "void"
259                         return ARGTYPE_VOID;
260                 }
261         }
262 #endif
263
264         // Unknown encoding. I just say void
265         complain(die, "Unknown base type. Returning 'void'");
266         return ARGTYPE_VOID;
267 }
268
269 static bool get_type_die(Dwarf_Die *type_die, Dwarf_Die *die)
270 {
271         Dwarf_Attribute attr;
272         return
273                 dwarf_attr(die, DW_AT_type, &attr) != NULL &&
274                 dwarf_formref_die(&attr, type_die) != NULL;
275 }
276
277
278
279 // type_dieoffset_hash dictionary callbacks
280 static size_t dwarf_die_hash(const void *x)
281 {
282         return *(const Dwarf_Off*)x;
283 }
284 static int dwarf_die_eq(const void *a, const void *b)
285 {
286         return *(const Dwarf_Off*)a == *(const Dwarf_Off*)b;
287 }
288
289
290 // returns a newly-allocated art_type_info*, or NULL on error
291 static struct arg_type_info *get_enum(Dwarf_Die *parent,
292                                       struct dict *type_dieoffset_hash)
293 {
294
295 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
296                 if (dupkey != NULL)                                     \
297                         free((void*)dupkey);                            \
298                 if (value != NULL) {                                    \
299                         value_destroy(value);                           \
300                         free(value);                                    \
301                 }                                                       \
302                 if (lens != NULL) {                                     \
303                         lens_destroy(&lens->super);                     \
304                         free(lens);                                     \
305                 }                                                       \
306                 if (result != NULL) {                                   \
307                         type_destroy(result);                           \
308                         free(result);                                   \
309                 }                                                       \
310                 dict_erase (type_dieoffset_hash, &die_offset, NULL,     \
311                             NULL, NULL);                                \
312                 dict_insert(type_dieoffset_hash, &die_offset,           \
313                             &(struct arg_type_info*){                   \
314                                     type_get_simple(ARGTYPE_VOID)});    \
315                 return ret;                                             \
316         } while (0)
317
318         struct arg_type_info *result = NULL;
319         struct enum_lens *lens = NULL;
320         const char *dupkey = NULL;
321         struct value *value = NULL;
322
323         Dwarf_Off die_offset = dwarf_dieoffset(parent);
324
325         result = calloc(1, sizeof(struct arg_type_info));
326         if (result == NULL) {
327                 complain(parent, "alloc error");
328                 CLEANUP_AND_RETURN_ERROR(NULL);
329         }
330
331         if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
332                 complain(parent, "Couldn't insert into cache dict");
333                 CLEANUP_AND_RETURN_ERROR(NULL);
334         }
335
336         uint64_t byte_size;
337         if (!get_die_numeric(&byte_size, parent, DW_AT_byte_size)) {
338                 // No byte size given, assume 'int'
339                 result->type = ARGTYPE_INT;
340         } else {
341                 if (!get_integer_base_type(&result->type,
342                                            (int)byte_size, true)) {
343                         complain(parent, "Unknown integer base type. "
344                                  "Using 'int'");
345                         result->type = ARGTYPE_INT;
346                 }
347         }
348
349         lens = calloc(1, sizeof(struct enum_lens));
350         if (lens == NULL) {
351                 complain(parent, "alloc error");
352                 CLEANUP_AND_RETURN_ERROR(NULL);
353         }
354         lens_init_enum(lens);
355         result->lens = &lens->super;
356         result->own_lens = 1;
357
358         Dwarf_Die die;
359         if (dwarf_child(parent, &die) != 0) {
360                 // empty enum. we're done
361                 CLEANUP_AND_RETURN_ERROR(NULL);
362         }
363
364
365         while (1) {
366                 complain(&die, "enum element: 0x%02x/'%s'", dwarf_tag(&die),
367                          dwarf_diename(&die));
368
369                 dupkey = NULL;
370                 value = NULL;
371
372                 if (dwarf_tag(&die) != DW_TAG_enumerator) {
373                         complain(&die, "Enums can have ONLY DW_TAG_enumerator "
374                                  "elements");
375                         CLEANUP_AND_RETURN_ERROR(NULL);
376                 }
377
378                 if (!dwarf_hasattr(&die, DW_AT_const_value)) {
379                         complain(&die, "Enums MUST have DW_AT_const_value "
380                                  "values");
381                         CLEANUP_AND_RETURN_ERROR(NULL);
382                 }
383
384                 const char *key = dwarf_diename(&die);
385                 if (key == NULL) {
386                         complain(&die, "Enums must have a DW_AT_name key");
387                         CLEANUP_AND_RETURN_ERROR(NULL);
388                 }
389                 dupkey = strdup(key);
390                 if (dupkey == NULL) {
391                         complain(&die, "Couldn't duplicate enum key");
392                         CLEANUP_AND_RETURN_ERROR(NULL);
393                 }
394
395                 value = calloc(1, sizeof(struct value));
396                 if (value == NULL) {
397                         complain(&die, "Couldn't alloc enum value");
398                         CLEANUP_AND_RETURN_ERROR(NULL);
399                 }
400
401                 value_init_detached(value, NULL, type_get_simple(result->type),
402                                     0);
403                 uint64_t enum_value;
404                 if (!get_die_numeric(&enum_value, &die, DW_AT_const_value)) {
405                         complain(&die, "Couldn't get enum value");
406                         CLEANUP_AND_RETURN_ERROR(NULL);
407                 }
408
409                 value_set_word(value, (long)enum_value);
410
411                 if (lens_enum_add(lens, dupkey, 1, value, 1)) {
412                         complain(&die, "Couldn't add enum element");
413                         CLEANUP_AND_RETURN_ERROR(NULL);
414                 }
415
416                 NEXT_SIBLING(&die);
417         }
418
419         return result;
420
421 #undef CLEANUP_AND_RETURN_ERROR
422 }
423
424 // returns a newly-allocated art_type_info*, or NULL on error
425 static struct arg_type_info *get_array(Dwarf_Die *parent,
426                                        struct protolib *plib,
427                                        struct dict *type_dieoffset_hash)
428 {
429
430 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
431                 if (length != NULL) {                                   \
432                         expr_destroy(length);                           \
433                         free(length);                                   \
434                 }                                                       \
435                 if (array_type != NULL && newly_allocated_array_type) { \
436                         type_destroy(array_type);                       \
437                         free(array_type);                               \
438                 }                                                       \
439                 if (result != NULL) {                                   \
440                         type_destroy(result);                           \
441                         free(result);                                   \
442                 }                                                       \
443                 dict_erase (type_dieoffset_hash, &die_offset,           \
444                             NULL, NULL, NULL);                          \
445                 dict_insert(type_dieoffset_hash, &die_offset,           \
446                             &(struct arg_type_info*){                   \
447                                     type_get_simple(ARGTYPE_VOID)});    \
448                 return ret;                                             \
449         } while (0)
450
451
452         struct arg_type_info *result = NULL;
453         struct expr_node *length = NULL;
454         struct arg_type_info *array_type = NULL;
455         int newly_allocated_array_type = 0;
456
457         Dwarf_Off die_offset = dwarf_dieoffset(parent);
458
459         result = calloc(1, sizeof(struct arg_type_info));
460         if (result == NULL) {
461                 complain(parent, "alloc error");
462                 CLEANUP_AND_RETURN_ERROR(NULL);
463         }
464
465         Dwarf_Die type_die;
466         if (!get_type_die(&type_die, parent)) {
467                 complain(parent, "Array has unknown type");
468                 CLEANUP_AND_RETURN_ERROR(NULL);
469         }
470
471         if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
472                 complain(parent, "Couldn't insert into cache dict");
473                 CLEANUP_AND_RETURN_ERROR(NULL);
474         }
475         array_type = get_type(&newly_allocated_array_type,
476                               &type_die, plib, type_dieoffset_hash);
477         if (array_type == NULL) {
478                 complain(parent, "Couldn't figure out array's type");
479                 CLEANUP_AND_RETURN_ERROR(NULL);
480         }
481
482         Dwarf_Die subrange;
483         if (dwarf_child(parent, &subrange) != 0) {
484                 complain(parent,
485                          "Array must have a DW_TAG_subrange_type child, "
486                          "but has none");
487                 CLEANUP_AND_RETURN_ERROR(NULL);
488         }
489
490         Dwarf_Die next_subrange;
491         if (dwarf_siblingof(&subrange, &next_subrange) <= 0) {
492                 complain(parent,
493                          "Array must have exactly one DW_TAG_subrange_type "
494                          "child");
495                 CLEANUP_AND_RETURN_ERROR(NULL);
496         }
497
498         if (dwarf_hasattr(&subrange, DW_AT_lower_bound)) {
499                 uint64_t lower_bound;
500                 if (!get_die_numeric(&lower_bound, &subrange,
501                                      DW_AT_lower_bound)) {
502                         complain(parent, "Couldn't read lower bound");
503                         CLEANUP_AND_RETURN_ERROR(NULL);
504                 }
505
506                 if (lower_bound != 0) {
507                         complain(parent,
508                                  "Array subrange has a nonzero lower bound. "
509                                  "Don't know what to do");
510                         CLEANUP_AND_RETURN_ERROR(NULL);
511                 }
512         }
513
514         uint64_t N;
515         if (!dwarf_hasattr(&subrange, DW_AT_upper_bound)) {
516                 // no upper bound is defined. This is probably a variable-width
517                 // array, and I don't know how long it is. Let's say 0 to be
518                 // safe
519                 N = 0;
520         }
521         else
522         {
523                 if (!get_die_numeric(&N, &subrange, DW_AT_upper_bound)) {
524                         complain(parent, "Couldn't read upper bound");
525                         CLEANUP_AND_RETURN_ERROR(NULL);
526                 }
527                 N++;
528         }
529
530         // I'm not checking the subrange type. It should be some sort of
531         // integer, and I don't know what it would mean for it to be something
532         // else
533         length = calloc(1, sizeof(struct expr_node));
534         if (length == NULL) {
535                 complain(&subrange, "Couldn't alloc length expr");
536                 CLEANUP_AND_RETURN_ERROR(NULL);
537         }
538         expr_init_const_word(length, N, type_get_simple(ARGTYPE_INT), 0);
539
540         type_init_array(result, array_type, newly_allocated_array_type,
541                         length, 1);
542         return result;
543
544 #undef CLEANUP_AND_RETURN_ERROR
545 }
546
547 // returns a newly-allocated art_type_info*, or NULL on error
548 static struct arg_type_info *get_structure(Dwarf_Die *parent,
549                                            struct protolib *plib,
550                                            struct dict *type_dieoffset_hash)
551 {
552
553 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
554                 if (member_type != NULL && newly_allocated_member_type) { \
555                         type_destroy(member_type);                      \
556                         free(member_type);                              \
557                 }                                                       \
558                 if (result != NULL) {                                   \
559                         type_destroy(result);                           \
560                         free(result);                                   \
561                 }                                                       \
562                 dict_erase (type_dieoffset_hash, &die_offset,           \
563                             NULL, NULL, NULL);                          \
564                 dict_insert(type_dieoffset_hash, &die_offset,           \
565                             &(struct arg_type_info*){                   \
566                                     type_get_simple(ARGTYPE_VOID)});    \
567                 return ret;                                             \
568         } while (0)
569
570
571         struct arg_type_info *result = NULL;
572         struct arg_type_info *member_type = NULL;
573         int newly_allocated_member_type = 0;
574
575         Dwarf_Off die_offset = dwarf_dieoffset(parent);
576
577         result = calloc(1, sizeof(struct arg_type_info));
578         if (result == NULL) {
579                 complain(parent, "alloc error");
580                 CLEANUP_AND_RETURN_ERROR(NULL);
581         }
582         type_init_struct(result);
583         if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
584                 complain(parent, "Couldn't insert into cache dict");
585                 CLEANUP_AND_RETURN_ERROR(NULL);
586         }
587
588         Dwarf_Die die;
589         if (dwarf_child(parent, &die) != 0) {
590                 // no elements; we're done
591                 return result;
592         }
593
594         while (1) {
595                 member_type = NULL;
596                 newly_allocated_member_type = 0;
597
598                 complain(&die, "member: 0x%02x", dwarf_tag(&die));
599
600                 if (dwarf_tag(&die) != DW_TAG_member) {
601                         complain(&die, "Structure can have ONLY DW_TAG_member");
602                         CLEANUP_AND_RETURN_ERROR(NULL);
603                 }
604
605                 Dwarf_Die type_die;
606                 if (!get_type_die(&type_die, &die)) {
607                         complain(&die, "Couldn't get type of element");
608                         CLEANUP_AND_RETURN_ERROR(NULL);
609                 }
610
611                 member_type = get_type(&newly_allocated_member_type,
612                                        &type_die, plib, type_dieoffset_hash);
613                 if (member_type == NULL) {
614                         complain(&die, "Couldn't parse type from DWARF data");
615                         CLEANUP_AND_RETURN_ERROR(NULL);
616                 }
617                 if (type_struct_add(result, member_type,
618                                     newly_allocated_member_type) != 0) {
619                         complain(&die, "Couldn't add type to struct");
620                         CLEANUP_AND_RETURN_ERROR(NULL);
621                 }
622
623                 NEXT_SIBLING(&die);
624         }
625
626         return result;
627 #undef CLEANUP_AND_RETURN_ERROR
628 }
629
630 // Reads the type in the die and returns the corresponding arg_type_info*. If
631 // this was newly allocated on the heap, *newly_allocated_info = true. If an
632 // error occurred, returns NULL
633 static struct arg_type_info *get_type(int *newly_allocated_result,
634                                       Dwarf_Die *type_die,
635                                       struct protolib *plib,
636                                       struct dict *type_dieoffset_hash)
637 {
638
639 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
640                 if (pointee != NULL && newly_allocated_pointee) {       \
641                         type_destroy(pointee);                          \
642                         free(pointee);                                  \
643                 }                                                       \
644                 if (result != NULL && *newly_allocated_result) {        \
645                         type_destroy(result);                           \
646                         free(result);                                   \
647                 }                                                       \
648                 dict_erase (type_dieoffset_hash, &die_offset,           \
649                             NULL, NULL, NULL);                          \
650                 dict_insert(type_dieoffset_hash, &die_offset,           \
651                             &(struct arg_type_info*){                   \
652                                     type_get_simple(ARGTYPE_VOID)});    \
653                 return ret;                                             \
654         } while (0)
655
656 #define DICT_INSERT_AND_CHECK(type_dieoffset_hash, die_offset, result)  \
657         do {                                                            \
658                 if (dict_insert(type_dieoffset_hash,                    \
659                                 die_offset, result) != 0) {             \
660                         complain(type_die,                              \
661                                  "Couldn't insert into cache dict");    \
662                         CLEANUP_AND_RETURN_ERROR(NULL);                 \
663                 }                                                       \
664         } while(0)
665
666         struct arg_type_info *result = NULL;
667         struct arg_type_info *pointee = NULL;
668         int newly_allocated_pointee = 0;
669
670         Dwarf_Off die_offset = dwarf_dieoffset(type_die);
671
672
673         // by default, we say we allocated nothing. I set this to true later,
674         // when I allocate memory
675         *newly_allocated_result = 0;
676
677         struct arg_type_info **found_type = dict_find(type_dieoffset_hash,
678                                                       &die_offset);
679         if (found_type != NULL) {
680                 complain(type_die, "Read pre-computed type");
681                 return *found_type;
682         }
683
684         const char *type_name = dwarf_diename(type_die);
685         if (type_name != NULL) {
686
687                 struct named_type *already_defined_type =
688                         protolib_lookup_type(plib, type_name, true);
689
690                 if (already_defined_type != NULL) {
691                         complain(type_die,
692                                  "Type '%s' defined in a .conf file. "
693                                  "Using that instead of DWARF",
694                                  type_name);
695                         return already_defined_type->info;
696                 }
697         }
698
699         Dwarf_Die next_die;
700
701         switch (dwarf_tag(type_die)) {
702         case DW_TAG_base_type:
703                 complain(type_die, "Storing base type");
704                 result = type_get_simple(get_base_type(type_die));
705                 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
706                 return result;
707
708         case DW_TAG_subroutine_type:
709         case DW_TAG_inlined_subroutine:
710                 // function pointers are stored as void*. If ltrace tries to
711                 // dereference these, it'll get a segfault
712                 complain(type_die, "Storing subroutine type");
713                 result = type_get_simple(ARGTYPE_VOID);
714                 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
715                 return result;
716
717         case DW_TAG_pointer_type:
718                 if (!get_type_die(&next_die, type_die)) {
719                         // the pointed-to type isn't defined, so I report a
720                         // void*
721                         complain(type_die, "Storing void-pointer type");
722                         result = type_get_voidptr();
723                         DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
724                         return result;
725                 }
726
727                 complain(type_die, "Storing pointer type");
728
729                 *newly_allocated_result = 1;
730                 result = calloc(1, sizeof(struct arg_type_info));
731                 if (result == NULL) {
732                         complain(type_die, "alloc error");
733                         CLEANUP_AND_RETURN_ERROR(NULL);
734                 }
735                 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
736                 pointee = get_type(&newly_allocated_pointee,
737                                    &next_die, plib, type_dieoffset_hash);
738                 if (pointee == NULL)
739                         CLEANUP_AND_RETURN_ERROR(NULL);
740
741                 type_init_pointer(result, pointee, newly_allocated_pointee);
742                 return result;
743
744         case DW_TAG_structure_type:
745                 complain(type_die, "Storing struct type");
746                 *newly_allocated_result = 1;
747
748                 result = get_structure(type_die, plib, type_dieoffset_hash);
749                 if (result == NULL)
750                         CLEANUP_AND_RETURN_ERROR(NULL);
751                 return result;
752
753
754         case DW_TAG_typedef:
755         case DW_TAG_const_type:
756         case DW_TAG_volatile_type:
757                 // Various tags are simply pass-through, so I just keep going
758                 if (get_type_die(&next_die, type_die)) {
759                         complain(type_die, "Storing const/typedef type");
760
761                         result = get_type(newly_allocated_result, &next_die,
762                                           plib, type_dieoffset_hash);
763                         if (result == NULL)
764                                 CLEANUP_AND_RETURN_ERROR(NULL);
765                 } else {
766                         // no type. Use 'void'. Normally I'd think this is
767                         // bogus, but stdio typedefs something to void
768                         result = type_get_simple(ARGTYPE_VOID);
769                         complain(type_die, "Storing void type");
770                 }
771                 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
772                 return result;
773
774         case DW_TAG_enumeration_type:
775                 // We have an enumeration. This has a base type, but has a
776                 // particular lens to handle the enum
777                 *newly_allocated_result = 1;
778
779                 complain(type_die, "Storing enum int");
780                 result = get_enum(type_die, type_dieoffset_hash);
781                 if (result == NULL)
782                         CLEANUP_AND_RETURN_ERROR(NULL);
783                 return result;
784
785         case DW_TAG_array_type:
786                 *newly_allocated_result = 1;
787
788                 complain(type_die, "Storing array");
789                 result = get_array(type_die, plib, type_dieoffset_hash);
790                 if (result == NULL)
791                         CLEANUP_AND_RETURN_ERROR(NULL);
792                 return result;
793
794         case DW_TAG_union_type:
795                 result = type_get_simple(ARGTYPE_VOID);
796                 complain(type_die, "Storing union-as-void type");
797                 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
798                 return result;
799
800         default:
801                 complain(type_die, "Unknown type tag 0x%x. Returning void",
802                          dwarf_tag(type_die));
803                 result = type_get_simple(ARGTYPE_VOID);
804                 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
805                 return result;
806         }
807
808 #undef DICT_INSERT_AND_CHECK
809 #undef CLEANUP_AND_RETURN_ERROR
810 }
811
812 // fills in *proto with a prototype. Returns true on success
813 static bool get_prototype(struct prototype *result,
814                           Dwarf_Die *subroutine, struct protolib *plib,
815                           struct dict *type_dieoffset_hash)
816 {
817
818 #define CLEANUP_AND_RETURN_ERROR(ret) do {                              \
819                 if (argument_type != NULL && newly_allocated_argument_type) { \
820                         type_destroy(argument_type);                    \
821                         free(argument_type);                            \
822                 }                                                       \
823                 prototype_destroy(result);                              \
824                 return ret;                                             \
825         } while (0)
826
827
828         struct arg_type_info *argument_type = NULL;
829         int newly_allocated_argument_type = 0;
830
831         prototype_init(result);
832
833         // First, look at the return type. This is stored in a DW_AT_type tag in
834         // the subroutine DIE. If there is no such tag, this function returns
835         // void
836         Dwarf_Die return_type_die;
837         if (!get_type_die(&return_type_die, subroutine)) {
838                 result->return_info = type_get_simple(ARGTYPE_VOID);
839                 result->own_return_info = 0;
840         } else {
841                 int newly_allocated_return_type;
842                 result->return_info = get_type(&newly_allocated_return_type,
843                                                &return_type_die, plib,
844                                                type_dieoffset_hash);
845                 if (result->return_info == NULL) {
846                         complain(subroutine, "Couldn't get return type");
847                         CLEANUP_AND_RETURN_ERROR(false);
848                 }
849                 result->own_return_info = newly_allocated_return_type;
850         }
851
852
853         // Now look at the arguments
854         Dwarf_Die arg_die;
855         if (dwarf_child(subroutine, &arg_die) != 0) {
856                 // no args. We're done
857                 return true;
858         }
859
860         while (1) {
861                 if (dwarf_tag(&arg_die) == DW_TAG_formal_parameter) {
862
863                         complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die));
864
865                         argument_type = NULL;
866                         newly_allocated_argument_type = false;
867
868                         Dwarf_Die type_die;
869                         if (!get_type_die(&type_die, &arg_die)) {
870                                 complain(&arg_die, "Couldn't get the argument "
871                                          "type die");
872                                 CLEANUP_AND_RETURN_ERROR(false);
873                         }
874
875
876                         argument_type = get_type(&newly_allocated_argument_type,
877                                                  &type_die, plib,
878                                                  type_dieoffset_hash);
879                         if (argument_type==NULL) {
880                                 complain(&arg_die, "Couldn't parse arg "
881                                          "type from DWARF data");
882                                 CLEANUP_AND_RETURN_ERROR(false);
883                         }
884
885                         struct param param;
886                         param_init_type(&param, argument_type,
887                                         newly_allocated_argument_type);
888                         if (prototype_push_param(result, &param) <0) {
889                                 complain(&arg_die, "couldn't add argument to "
890                                          "the prototype");
891                                 CLEANUP_AND_RETURN_ERROR(false);
892                         }
893
894 #ifdef DUMP_PROTOTYPES
895                         fprintf(stderr, "Adding argument:\n");
896                         dump_ltrace_tree(argument_type);
897 #endif
898                 }
899
900                 NEXT_SIBLING(&arg_die);
901         }
902
903         return true;
904 #undef CLEANUP_AND_RETURN_ERROR
905 }
906
907 static bool import_subprogram_name(struct protolib *plib, struct library *lib,
908                                    struct dict *type_dieoffset_hash,
909                                    Dwarf_Die *die, const char* function_name)
910 {
911         if (!filter_matches_symbol(options.plt_filter,    function_name, lib) &&
912             !filter_matches_symbol(options.static_filter, function_name, lib) &&
913             !filter_matches_symbol(options.export_filter, function_name, lib)) {
914                 complain(die, "Prototype not requested by any filter");
915                 return true;
916         }
917
918         complain(die, "subroutine_type: 0x%02x; function '%s'",
919                  dwarf_tag(die), function_name);
920
921         struct prototype *proto_already_there =
922                 protolib_lookup_prototype(plib, function_name, false);
923
924         if (proto_already_there != NULL) {
925                 complain(die, "Prototype already exists. Skipping");
926                 return true;
927         }
928
929         struct prototype proto;
930         if (!get_prototype(&proto, die, plib, type_dieoffset_hash)) {
931                 complain(die, "couldn't get prototype");
932                 return false;
933         }
934
935         const char *function_name_dup = strdup(function_name);
936         if (function_name_dup == NULL) {
937                 complain(die, "couldn't strdup");
938                 prototype_destroy(&proto);
939                 return false;
940         }
941         protolib_add_prototype(plib, function_name_dup, 1, &proto);
942         return true;
943 }
944
945 static bool import_subprogram_die(struct protolib *plib, struct library *lib,
946                                   struct dict *type_dieoffset_hash,
947                                   Dwarf_Die *die)
948 {
949         // If there is a linkage name, I use it (this is required for C++ code,
950         // in particular).
951         //
952         // I use the plain name regardless, since sometimes the exported symbol
953         // corresponds to the plain name, NOT the linkage name. For instance I
954         // see this on my Debian/sid amd64 box. In its libc, the linkage name of
955         // __nanosleep is __GI___nanosleep, but the export is __nanosleep
956         const char *function_name;
957         Dwarf_Attribute attr;
958
959         if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL &&
960             (function_name = dwarf_formstring(&attr)) != NULL &&
961             !import_subprogram_name(plib, lib, type_dieoffset_hash, die,
962                                     function_name)) {
963                 return false;
964         }
965
966         if ((function_name = dwarf_diename(die)) != NULL &&
967             !import_subprogram_name(plib, lib, type_dieoffset_hash, die,
968                                     function_name)) {
969                 return false;
970         }
971
972         return true;
973 }
974
975 static bool process_die_compileunit(struct protolib *plib, struct library *lib,
976                                     struct dict *type_dieoffset_hash,
977                                     Dwarf_Die *parent)
978 {
979         complain(parent, "Processing compile unit");
980         Dwarf_Die die;
981         if (dwarf_child(parent, &die) != 0) {
982                 // no child nodes, so nothing to do
983                 return true;
984         }
985
986         while (1) {
987                 if (dwarf_tag(&die) == DW_TAG_subprogram)
988                         if (!import_subprogram_die(plib, lib, type_dieoffset_hash,
989                                                    &die))
990                                 complain(&die, "Error importing subprogram. "
991                                          "Skipping");
992
993                 NEXT_SIBLING(&die);
994         }
995
996         return true;
997 }
998
999 static void import(struct protolib *plib, struct library *lib,
1000                    Dwfl_Module *dwfl_module)
1001 {
1002         // A map from DIE addresses (Dwarf_Off) to type structures (struct
1003         // arg_type_info*). This is created and filled in at the start of each
1004         // import, and deleted when the import is complete
1005         struct dict type_dieoffset_hash;
1006
1007         dict_init(&type_dieoffset_hash, sizeof(Dwarf_Off),
1008                   sizeof(struct arg_type_info*),
1009                   dwarf_die_hash, dwarf_die_eq, NULL);
1010
1011         Dwarf_Addr bias;
1012         Dwarf_Die *die = NULL;
1013         while ((die = dwfl_module_nextcu(dwfl_module, die, &bias)) != NULL) {
1014                 if (dwarf_tag(die) == DW_TAG_compile_unit)
1015                         process_die_compileunit(plib, lib,
1016                                                 &type_dieoffset_hash, die);
1017                 else
1018                         complain(die, "A DW_TAG_compile_unit die expected. "
1019                                  "Skipping this one");
1020         }
1021
1022         dict_destroy(&type_dieoffset_hash, NULL, NULL, NULL);
1023 }
1024
1025 bool import_DWARF_prototypes(struct library *lib)
1026 {
1027         struct protolib *plib = lib->protolib;
1028
1029         debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
1030               lib->soname);
1031         if (plib == NULL) {
1032
1033                 const char *soname_dup = strdup(lib->soname);
1034                 if (soname_dup == NULL) {
1035                         fprintf(stderr, "couldn't strdup");
1036                         return false;
1037                 }
1038
1039                 plib = protolib_cache_default(&g_protocache, soname_dup, 1);
1040                 if (plib == NULL) {
1041                         fprintf(stderr, "Error loading protolib %s: %s.\n",
1042                                 lib->soname, strerror(errno));
1043                 }
1044         }
1045
1046         import(plib, lib, lib->dwfl_module);
1047         lib->protolib = plib;
1048
1049         return true;
1050 }