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