types defined in .conf files now take precedence over DWARF types
[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
28
29 //#define DUMP_PROTOTYPES
30
31 #if 1
32 #define complain(die, format, ...)                                                              \
33         fprintf(stderr, "%s() die '%s' @ 0x%lx: " format "\n",          \
34                         __func__, dwarf_diename(die), dwarf_dieoffset(die),     \
35                         ##__VA_ARGS__)
36 #else
37 #define complain(die, format, ...)
38 #endif
39
40 #define NEXT_SIBLING(die)                                                               \
41         int res = dwarf_siblingof(die, die);                            \
42         if (res == 0) continue;     /* sibling exists    */     \
43         if (res < 0)  return false; /* error             */     \
44         break                       /* no sibling exists */
45
46 // A map from DIE addresses (Dwarf_Off) to type structures (struct
47 // arg_type_info*). This is created and filled in at the start of each import,
48 // and deleted when the import is complete
49 static struct dict type_hash;
50
51
52 static bool get_type(struct arg_type_info** info, Dwarf_Die* type_die, struct protolib* plib);
53
54
55 #if 0
56 static bool _dump_dwarf_tree(Dwarf_Die* die, int indent)
57 {
58     while (1) {
59         fprintf(stderr, "%*sprocessing unit: 0x%02x/'%s'\n", indent*4, "",
60                dwarf_tag(die), dwarf_diename(die));
61
62         Dwarf_Die child;
63         if (dwarf_child(die, &child) == 0) {
64                         if (!_dump_dwarf_tree(&child, indent+1))
65                                 return false;
66         }
67
68         SIBLING(die);
69     }
70
71     return true;
72 }
73
74 static bool dump_dwarf_tree(Dwarf_Die* die)
75 {
76     return _dump_dwarf_tree(die, 0);
77 }
78 #endif
79
80 #ifdef DUMP_PROTOTYPES
81 static bool _dump_ltrace_tree(const struct arg_type_info* info, int indent)
82 {
83         if (indent > 7) {
84                 fprintf(stderr, "%*s%p ...\n", indent*4, "", (void*)info);
85                 return true;
86         }
87
88         if (info == NULL) {
89                 fprintf(stderr, "%*s%p NULL\n", indent*4, "", (void*)info);
90                 return true;
91         }
92
93         switch (info->type) {
94         case ARGTYPE_VOID:
95                 fprintf(stderr, "%*s%p void\n", indent*4, "", (void*)info);
96                 break;
97
98         case ARGTYPE_INT:
99         case ARGTYPE_UINT:
100         case ARGTYPE_LONG:
101         case ARGTYPE_ULONG:
102         case ARGTYPE_CHAR:
103         case ARGTYPE_SHORT:
104         case ARGTYPE_USHORT:
105         case ARGTYPE_FLOAT:
106         case ARGTYPE_DOUBLE:
107                 fprintf(stderr, "%*s%p base\n", indent*4, "", (void*)info);
108                 break;
109
110         case ARGTYPE_ARRAY:
111                 fprintf(stderr, "%*s%p array. elements not printed\n", indent*4, "",
112                                 (void*)info);
113                 break;
114
115         case ARGTYPE_POINTER:
116                 fprintf(stderr, "%*s%p pointer to...\n", indent*4, "", (void*)info);
117                 _dump_ltrace_tree(info->u.ptr_info.info, indent+1);
118                 break;
119
120         case ARGTYPE_STRUCT:
121                 fprintf(stderr, "%*s%p struct...\n", indent*4, "", (void*)info);
122                 struct struct_field
123                 {
124                         struct arg_type_info *info;
125                         int own_info;
126                 }* elements = (struct struct_field*)info->u.entries.data;
127                 unsigned int i;
128                 for(i=0; i<info->u.entries.size; i++)
129                         _dump_ltrace_tree(elements[i].info, indent+1);
130                 break;
131
132         default:
133                 fprintf(stderr, "%*s%p unknown type\n", indent*4, "", (void*)info);
134                 return false;;
135         }
136
137         return true;
138 }
139
140 static bool dump_ltrace_tree(const struct arg_type_info* info)
141 {
142         return _dump_ltrace_tree(info, 0);
143 }
144 #endif
145
146
147 // pulls a numerical value out of a particular attribute in a die. Returns true
148 // if successful. The result is returned in *result. Note that this is cast to
149 // (uint64_t), regardless of the actual type of the input
150 static bool get_die_numeric(uint64_t* result,
151                                                         Dwarf_Die *die, unsigned int attr_name)
152 {
153         Dwarf_Attribute attr ;
154
155         union {
156                 Dwarf_Word              udata;
157                 Dwarf_Sword     sdata;
158                 Dwarf_Addr              addr;
159                 bool                    flag;
160         } u;
161
162         if (dwarf_attr(die, attr_name, &attr) == NULL)
163                 return false;
164
165         unsigned int form = dwarf_whatform(&attr);
166
167 #define PROCESS_NUMERIC(type)                                           \
168         if (dwarf_form ## type(&attr, &u.type) != 0)    \
169                 return false;                                                           \
170         *result = (uint64_t)u.type;                                             \
171         return true
172
173
174         switch (form) {
175         case DW_FORM_addr:
176                 PROCESS_NUMERIC(addr);
177
178         case DW_FORM_data1:
179         case DW_FORM_data2:
180         case DW_FORM_data4:
181         case DW_FORM_data8:
182         case DW_FORM_udata:
183                 PROCESS_NUMERIC(udata);
184
185         case DW_FORM_sdata:
186                 PROCESS_NUMERIC(sdata);
187
188         case DW_FORM_flag:
189                 PROCESS_NUMERIC(flag);
190
191         default:
192                 complain(die, "Unknown numeric form %d for attr_name: %d", form, attr_name);
193                 return false;
194         }
195 #undef PROCESS_NUMERIC
196 }
197
198 static bool get_integer_base_type(enum arg_type* type, int byte_size, bool is_signed)
199 {
200         switch (byte_size) {
201         case sizeof(char):
202                 *type = ARGTYPE_CHAR;
203                 return true;
204
205         case sizeof(short):
206                 *type = is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT;
207                 return true;
208
209         case sizeof(int):
210                 *type = is_signed ? ARGTYPE_INT : ARGTYPE_UINT;
211                 return true;
212
213         case sizeof(long):
214                 *type = is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG;
215                 return true;
216
217         default:
218                 return false;
219         }
220 }
221
222 static enum arg_type get_base_type(Dwarf_Die* die)
223 {
224         int64_t encoding;
225         if(!get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding))
226                 return ARGTYPE_VOID;
227
228         if (encoding == DW_ATE_void)
229                 return ARGTYPE_VOID;
230
231         if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char)
232                 return ARGTYPE_CHAR;
233
234                 uint64_t byte_size;
235                 if (!get_die_numeric(&byte_size, die, DW_AT_byte_size))
236                         return ARGTYPE_VOID;
237
238         if (encoding == DW_ATE_signed   ||
239                 encoding == DW_ATE_unsigned ||
240                 encoding == DW_ATE_boolean) {
241
242                 bool is_signed = (encoding == DW_ATE_signed);
243
244                 enum arg_type type;
245                 if(!get_integer_base_type(&type, (int)byte_size, is_signed)) {
246                         complain(die, "Unknown integer base type. Using 'void'");
247                         return ARGTYPE_VOID;
248                 }
249                 return type;
250         }
251
252         if (encoding == DW_ATE_float) {
253                 switch (byte_size) {
254                 case sizeof(float):
255                         return ARGTYPE_FLOAT;
256
257                 case sizeof(double):
258                         return ARGTYPE_DOUBLE;
259
260                 default:
261                         // things like long doubles. ltrace has no support yet, so I just
262                         // say "void"
263                         return ARGTYPE_VOID;
264                 }
265         }
266
267 #if 0
268         if (encoding == DW_ATE_complex_float) {
269                 switch (byte_size) {
270                 case 2*sizeof(float):
271                         return ARGTYPE_FLOAT;
272
273                 case 2*sizeof(double):
274                         return ARGTYPE_DOUBLE;
275
276                 default:
277                         // things like long doubles. ltrace has no support yet, so I just
278                         // say "void"
279                         return ARGTYPE_VOID;
280                 }
281         }
282 #endif
283
284         // Unknown encoding. I just say void
285         complain(die, "Unknown base type. Returning 'void'");
286         return ARGTYPE_VOID;
287 }
288
289 static bool get_type_die(Dwarf_Die* type_die, Dwarf_Die* die)
290 {
291         Dwarf_Attribute attr;
292         return
293                 dwarf_attr(die, DW_AT_type, &attr) != NULL &&
294                 dwarf_formref_die(&attr, type_die) != NULL;
295 }
296
297 static size_t dwarf_die_hash(const void* x)
298 {
299         return *(const Dwarf_Off*)x;
300 }
301 static int dwarf_die_eq(const void* a, const void* b)
302 {
303         return *(const Dwarf_Off*)a == *(const Dwarf_Off*)b;
304 }
305
306 static bool get_enum(struct arg_type_info* enum_info, Dwarf_Die* parent)
307 {
308         uint64_t byte_size;
309         if (!get_die_numeric(&byte_size, parent, DW_AT_byte_size)) {
310                 // No byte size given, assume 'int'
311                 enum_info->type = ARGTYPE_INT;
312         } else {
313                 if(!get_integer_base_type(&enum_info->type, (int)byte_size, true)) {
314                         complain(parent, "Unknown integer base type. Using 'int'");
315                         enum_info->type = ARGTYPE_INT;
316                 }
317         }
318
319         struct enum_lens *lens = calloc(1, sizeof(struct enum_lens));
320         if (lens == NULL) {
321                 complain(parent, "alloc error");
322                 return false;
323         }
324         lens_init_enum(lens);
325         enum_info->lens = &lens->super;
326
327         Dwarf_Die die;
328         if (dwarf_child(parent, &die) != 0) {
329                 // empty enum. we're done
330                 return true;
331         }
332
333         while(1) {
334                 complain(&die, "enum element: 0x%02x/'%s'", dwarf_tag(&die),
335                                  dwarf_diename(&die));
336
337                 if (dwarf_tag(&die) != DW_TAG_enumerator) {
338                         complain(&die, "Enums can have ONLY DW_TAG_enumerator elements");
339                         return false;
340                 }
341
342                 if (!dwarf_hasattr(&die, DW_AT_const_value)) {
343                         complain(&die, "Enums MUST have DW_AT_const_value values");
344                         return false;
345                 }
346
347                 const char* key = dwarf_diename(&die);
348                 if (key == NULL) {
349                         complain(&die, "Enums must have a DW_AT_name key");
350                         return false;
351                 }
352                 const char* dupkey = strdup(key);
353                 if (dupkey == NULL) {
354                         complain(&die, "Couldn't duplicate enum key");
355                         return false;
356                 }
357
358                 struct value* value = calloc(1, sizeof(struct value));
359                 if (value == NULL) {
360                         complain(&die, "Couldn't alloc enum value");
361                         return false;
362                 }
363
364                 value_init_detached(value, NULL, type_get_simple(enum_info->type), 0);
365                 uint64_t enum_value;
366                 if (!get_die_numeric(&enum_value, &die, DW_AT_const_value)) {
367                         complain(&die, "Couldn't get enum value");
368                         return false;
369                 }
370
371                 value_set_word(value, (long)enum_value);
372
373                 if (lens_enum_add(lens, dupkey, 0, value, 0)) {
374                         complain(&die, "Couldn't add enum element");
375                         return false;
376                 }
377
378                 NEXT_SIBLING(&die);
379         }
380
381         return true;
382 }
383
384 static bool get_array(struct arg_type_info* array_info, Dwarf_Die* parent, struct protolib* plib)
385 {
386         Dwarf_Die type_die;
387         if (!get_type_die(&type_die, parent)) {
388                 complain(parent, "Array has unknown type");
389                 return false;
390         }
391
392         struct arg_type_info* info;
393         if (!get_type(&info, &type_die, plib)) {
394                 complain(parent, "Couldn't figure out array's type");
395                 return false;
396         }
397
398         Dwarf_Die subrange;
399         if (dwarf_child(parent, &subrange) != 0) {
400                 complain(parent,
401                                  "Array must have a DW_TAG_subrange_type child, but has none");
402                 return false;
403         }
404
405         Dwarf_Die next_subrange;
406         if (dwarf_siblingof(&subrange, &next_subrange) <= 0) {
407                 complain(parent,
408                                  "Array must have exactly one DW_TAG_subrange_type child");
409                 return false;
410         }
411
412         if (dwarf_hasattr(&subrange, DW_AT_lower_bound)) {
413                 uint64_t lower_bound;
414                 if (!get_die_numeric(&lower_bound, &subrange, DW_AT_lower_bound)) {
415                         complain(parent, "Couldn't read lower bound");
416                         return false;
417                 }
418
419                 if (lower_bound != 0) {
420                         complain(parent,
421                                           "Array subrange has a nonzero lower bound. Don't know what to do");
422                         return false;
423                 }
424         }
425
426         uint64_t N;
427         if (!dwarf_hasattr(&subrange, DW_AT_upper_bound)) {
428                 // no upper bound is defined. This is probably a variable-width array,
429                 // and I don't know how long it is. Let's say 0 to be safe
430                 N = 0;
431         }
432         else
433         {
434                 if (!get_die_numeric(&N, &subrange, DW_AT_upper_bound)) {
435                         complain(parent, "Couldn't read upper bound");
436                         return false;
437                 }
438                 N++;
439         }
440
441         // I'm not checking the subrange type. It should be some sort of integer,
442         // and I don't know what it would mean for it to be something else
443
444         struct value* value = calloc(1, sizeof(struct value));
445         if (value == NULL) {
446                 complain(&subrange, "Couldn't alloc length value");
447                 return false;
448         }
449         value_init_detached(value, NULL, type_get_simple(ARGTYPE_INT), 0);
450         value_set_word(value, N);
451
452         struct expr_node* length = calloc(1, sizeof(struct expr_node));
453         if (length == NULL) {
454                 complain(&subrange, "Couldn't alloc length expr");
455                 return false;
456         }
457         expr_init_const(length, value);
458
459         type_init_array(array_info, info, 0, length, 0);
460
461         return true;
462 }
463
464 static bool get_structure(struct arg_type_info* struct_info, Dwarf_Die* parent, struct protolib* plib)
465 {
466         type_init_struct(struct_info);
467
468         Dwarf_Die die;
469         if (dwarf_child(parent, &die) != 0) {
470                 // no elements; we're done
471                 return true;
472         }
473
474         while(1) {
475                 complain(&die, "member: 0x%02x", dwarf_tag(&die));
476
477                 if (dwarf_tag(&die) != DW_TAG_member) {
478                         complain(&die, "Structure can have ONLY DW_TAG_member");
479                         return false;
480                 }
481
482                 Dwarf_Die type_die;
483                 if (!get_type_die(&type_die, &die)) {
484                         complain(&die, "Couldn't get type of element");
485                         return false;
486                 }
487
488                 struct arg_type_info* member_info = NULL;
489                 if (!get_type(&member_info, &type_die, plib)) {
490                         complain(&die, "Couldn't parse type from DWARF data");
491                         return false;
492                 }
493                 type_struct_add(struct_info, member_info, 0);
494
495                 NEXT_SIBLING(&die);
496         }
497
498         return true;
499 }
500
501 // Reads the type in the die into the given structure
502 // Returns true on sucess
503 static bool get_type(struct arg_type_info** info, Dwarf_Die* type_die, struct protolib* plib)
504 {
505         Dwarf_Off die_offset = dwarf_dieoffset(type_die);
506         struct arg_type_info** found_type = dict_find(&type_hash, &die_offset);
507         if (found_type != NULL) {
508                 *info = *found_type;
509                 complain(type_die, "Read pre-computed type: %p", *info);
510                 return true;
511         }
512
513         const char* type_name = dwarf_diename(type_die);
514         if (type_name != NULL) {
515
516                 struct named_type* already_defined_type =
517                         protolib_lookup_type(plib, type_name, false);
518
519                 if (already_defined_type != NULL) {
520                         complain(type_die,
521                                          "Type '%s' defined in a .conf file. Using that instead of DWARF",
522                                          type_name);
523                         *info = already_defined_type->info;
524                         return true;
525                 }
526         }
527
528         Dwarf_Die next_die;
529
530         switch (dwarf_tag(type_die)) {
531         case DW_TAG_base_type:
532                 *info = type_get_simple(get_base_type(type_die));
533                 complain(type_die, "Storing base type: %p", *info);
534                 dict_insert(&type_hash, &die_offset, info);
535                 return true;
536
537         case DW_TAG_subroutine_type:
538         case DW_TAG_inlined_subroutine:
539                 // function pointers are stored as void*. If ltrace tries to dereference
540                 // these, it'll get a segfault
541                 *info = type_get_simple(ARGTYPE_VOID);
542                 complain(type_die, "Storing subroutine type: %p", *info);
543                 dict_insert(&type_hash, &die_offset, info);
544                 return true;
545
546         case DW_TAG_pointer_type:
547
548                 if (!get_type_die(&next_die, type_die)) {
549                         // the pointed-to type isn't defined, so I report a void*
550                         *info = type_get_simple(ARGTYPE_VOID);
551                         complain(type_die, "Storing void-pointer type: %p", *info);
552                         dict_insert(&type_hash, &die_offset, info);
553                         return true;
554                 }
555
556                 *info = calloc(1, sizeof(struct arg_type_info));
557                 if (*info == NULL) {
558                         complain(type_die, "alloc error");
559                         return false;
560                 }
561                 type_init_pointer(*info, NULL, 0);
562
563                 complain(type_die, "Storing pointer type: %p", *info);
564                 dict_insert(&type_hash, &die_offset, info);
565                 return get_type(&(*info)->u.ptr_info.info, &next_die, plib);
566
567         case DW_TAG_structure_type:
568                 *info = calloc(1, sizeof(struct arg_type_info));
569                 if (*info == NULL) {
570                         complain(type_die, "alloc error");
571                         return false;
572                 }
573
574                 complain(type_die, "Storing struct type: %p", *info);
575                 dict_insert(&type_hash, &die_offset, info);
576                 return get_structure(*info, type_die, plib);
577
578
579         case DW_TAG_typedef:
580         case DW_TAG_const_type:
581         case DW_TAG_volatile_type: {
582                 // Various tags are simply pass-through, so I just keep going
583                 bool res = true;
584                 if (get_type_die(&next_die, type_die)) {
585                         complain(type_die, "Storing const/typedef type: %p", *info);
586                         res = get_type(info, &next_die, plib);
587                 } else {
588                         // no type. Use 'void'. Normally I'd think this is bogus, but stdio
589                         // typedefs something to void
590                         *info = type_get_simple(ARGTYPE_VOID);
591                         complain(type_die, "Storing void type: %p", *info);
592                 }
593                 if (res)
594                         dict_insert(&type_hash, &die_offset, info);
595                 return res;
596         }
597
598         case DW_TAG_enumeration_type:
599                 // We have an enumeration. This has type "int", but has a particular
600                 // lens to handle the enum
601                 *info = calloc(1, sizeof(struct arg_type_info));
602                 if (*info == NULL) {
603                         complain(type_die, "alloc error");
604                         return false;
605                 }
606
607                 complain(type_die, "Storing enum int: %p", *info);
608                 dict_insert(&type_hash, &die_offset, info);
609                 return get_enum(*info, type_die);
610
611         case DW_TAG_array_type:
612                 *info = calloc(1, sizeof(struct arg_type_info));
613                 if (*info == NULL) {
614                         complain(type_die, "alloc error");
615                         return false;
616                 }
617
618                 complain(type_die, "Storing array: %p", *info);
619                 dict_insert(&type_hash, &die_offset, info);
620                 return get_array(*info, type_die, plib);
621
622         case DW_TAG_union_type:
623                 *info = type_get_simple(ARGTYPE_VOID);
624                 complain(type_die, "Storing union-as-void type: %p", *info);
625                 return true;
626
627         default:
628                 complain(type_die, "Unknown type tag 0x%x", dwarf_tag(type_die));
629                 break;
630         }
631
632         return false;
633 }
634
635 static bool get_prototype(struct prototype* proto, Dwarf_Die* subroutine, struct protolib* plib)
636 {
637         // First, look at the return type. This is stored in a DW_AT_type tag in the
638         // subroutine DIE. If there is no such tag, this function returns void
639         Dwarf_Die return_type_die;
640         if (!get_type_die(&return_type_die, subroutine)) {
641                 proto->return_info = type_get_simple(ARGTYPE_VOID);
642                 proto->own_return_info = 0;
643         } else {
644                 proto->return_info = calloc(1, sizeof(struct arg_type_info));
645                 if (proto->return_info == NULL) {
646                         complain(subroutine, "Couldn't alloc return type");
647                         return false;
648                 }
649                 proto->own_return_info = 0;
650
651                 if (!get_type(&proto->return_info, &return_type_die, plib)) {
652                         complain(subroutine, "Couldn't get return type");
653                         return false;
654                 }
655         }
656
657
658         // Now look at the arguments
659         Dwarf_Die arg_die;
660         if (dwarf_child(subroutine, &arg_die) != 0) {
661                 // no args. We're done
662                 return true;
663         }
664
665         while(1) {
666                 if (dwarf_tag(&arg_die) == DW_TAG_formal_parameter) {
667
668                         complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die));
669
670                         Dwarf_Die type_die;
671                         if (!get_type_die(&type_die, &arg_die)) {
672                                 complain(&arg_die, "Couldn't get the argument type die");
673                                 return false;
674                         }
675
676                         struct arg_type_info* arg_type_info = NULL;
677                         if (!get_type(&arg_type_info, &type_die, plib)) {
678                                 complain(&arg_die, "Couldn't parse arg type from DWARF data");
679                                 return false;
680                         }
681
682                         struct param param;
683                         param_init_type(&param, arg_type_info, 0);
684                         if (prototype_push_param(proto, &param) <0) {
685                                 complain(&arg_die, "couldn't add argument to the prototype");
686                                 return false;
687                         }
688
689 #ifdef DUMP_PROTOTYPES
690                         fprintf(stderr, "Adding argument:\n");
691                         dump_ltrace_tree(arg_type_info);
692 #endif
693                 }
694
695                 NEXT_SIBLING(&arg_die);
696         }
697
698         return true;
699 }
700
701 static bool import_subprogram(struct protolib* plib, struct library* lib,
702                                                           Dwarf_Die* die)
703 {
704         // I use the linkage function name if there is one, otherwise the
705         // plain name
706         const char* function_name = NULL;
707         Dwarf_Attribute attr;
708         if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL)
709                 function_name = dwarf_formstring(&attr);
710         if (function_name == NULL)
711                 function_name = dwarf_diename(die);
712         if (function_name == NULL) {
713                 complain(die, "Function has no name. Not importing");
714                 return true;
715         }
716
717
718         complain(die, "subroutine_type: 0x%02x; function '%s'",
719                          dwarf_tag(die), function_name);
720
721         struct prototype* proto =
722                 protolib_lookup_prototype(plib, function_name, false);
723
724         if (proto != NULL) {
725                 complain(die, "Prototype already exists. Skipping");
726                 return true;
727         }
728
729         if (!filter_matches_symbol(options.plt_filter,    function_name, lib) &&
730                 !filter_matches_symbol(options.static_filter, function_name, lib) &&
731                 !filter_matches_symbol(options.export_filter, function_name, lib)) {
732                 complain(die, "Prototype not requested by any filter");
733                 return true;
734         }
735
736         proto = malloc(sizeof(struct prototype));
737         if (proto == NULL) {
738                 complain(die, "couldn't alloc prototype");
739                 return false;
740         }
741         prototype_init(proto);
742
743         if (!get_prototype(proto, die, plib)) {
744                 complain(die, "couldn't get prototype");
745                 return false;
746         }
747
748         protolib_add_prototype(plib, function_name, 0, proto);
749         return true;
750 }
751
752 static bool process_die_compileunit(struct protolib* plib, struct library* lib,
753                                                                         Dwarf_Die* parent)
754 {
755         Dwarf_Die die;
756         if (dwarf_child(parent, &die) != 0) {
757                 // no child nodes, so nothing to do
758                 return true;
759         }
760
761         while (1) {
762                 if (dwarf_tag(&die) == DW_TAG_subprogram)
763                         if(!import_subprogram(plib, lib, &die))
764                                 return false;
765
766                 NEXT_SIBLING(&die);
767         }
768
769         return true;
770 }
771
772 static bool import(struct protolib* plib, struct library* lib, Dwfl* dwfl)
773 {
774         dict_init(&type_hash, sizeof(Dwarf_Off), sizeof(struct arg_type_info*),
775                           dwarf_die_hash, dwarf_die_eq, NULL);
776
777         Dwarf_Addr bias;
778     Dwarf_Die* die = NULL;
779     while ((die = dwfl_nextcu(dwfl, die, &bias)) != NULL) {
780         if (dwarf_tag(die) == DW_TAG_compile_unit) {
781             if (!process_die_compileunit(plib, lib, die)) {
782                 complain(die, "Error reading compile unit");
783                                 exit(1);
784                                 return false;
785             }
786         } else {
787             complain(die, "DW_TAG_compile_unit expected");
788                         exit(1);
789             return false;
790         }
791     }
792
793         dict_destroy(&type_hash, NULL, NULL, NULL);
794         return true;
795 }
796
797 bool import_DWARF_prototypes(struct library* lib)
798 {
799         struct protolib*        plib = lib->protolib;
800         Dwfl*                           dwfl = lib->dwfl;
801
802         if (plib == NULL) {
803                 plib = protolib_cache_default(&g_protocache, lib->soname, 0);
804                 if (plib == NULL) {
805                         fprintf(stderr, "Error loading protolib %s: %s.\n",
806                                         lib->soname, strerror(errno));
807                 }
808         }
809
810         if (import(plib, lib, dwfl)) {
811                 lib->protolib = plib;
812                 return true;
813         }
814         return false;
815 }
816
817 /*
818 - I handle static functions now. Should I? Those do not have DW_AT_external==1
819
820 - should process existing prototypes to make sure they match
821
822 - what do function pointers look like? I'm doing void*
823
824 - unions
825
826 - all my *allocs leak
827
828
829 */