1 /* Copyright Dima Kogan <dima@secretsauce.net>
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.
9 #include <elfutils/libdwfl.h>
16 #include "prototype.h"
21 #include "lens_enum.h"
29 #define complain(die, format, ...) \
30 debug(DEBUG_FUNCTION, "%s() die '%s' @ 0x%lx: " format, \
31 __func__, dwarf_diename(die), dwarf_dieoffset(die), \
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 */
40 static struct arg_type_info *get_type(int *newly_allocated_info,
42 struct protolib *plib,
43 struct dict *type_dieoffset_hash);
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)
53 fprintf(stderr, "%*s%p ...\n", indent*4, "", (void*)info);
58 fprintf(stderr, "%*s%p NULL\n", indent*4, "", (void*)info);
64 fprintf(stderr, "%*s%p void\n", indent*4, "", (void*)info);
76 fprintf(stderr, "%*s%p base\n", indent*4, "", (void*)info);
80 fprintf(stderr, "%*s%p array. elements not printed\n", indent*4,
85 fprintf(stderr, "%*s%p pointer to...\n", indent*4,
87 _dump_ltrace_tree(info->u.ptr_info.info, indent+1);
91 fprintf(stderr, "%*s%p struct...\n", indent*4,
95 struct arg_type_info *info;
97 } *elements = (struct struct_field*)info->u.entries.data;
99 for(i=0; i<info->u.entries.size; i++)
100 _dump_ltrace_tree(elements[i].info, indent+1);
104 fprintf(stderr, "%*s%p unknown type\n", indent*4,
112 static bool dump_ltrace_tree(const struct arg_type_info *info)
114 return _dump_ltrace_tree(info, 0);
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)
125 Dwarf_Attribute attr ;
134 if (dwarf_attr(die, attr_name, &attr) == NULL)
137 unsigned int form = dwarf_whatform(&attr);
139 #define PROCESS_NUMERIC(type) \
140 if (dwarf_form ## type(&attr, &u.type) != 0) \
142 *result = (uint64_t)u.type; \
148 PROCESS_NUMERIC(addr);
155 PROCESS_NUMERIC(udata);
158 PROCESS_NUMERIC(sdata);
161 PROCESS_NUMERIC(flag);
164 complain(die, "Unknown numeric form %d for attr_name: %d",
168 #undef PROCESS_NUMERIC
171 static bool get_integer_base_type(enum arg_type *type, int byte_size,
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;
181 if (byte_size == sizeof(short)) {
182 *type = is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT;
186 if (byte_size == sizeof(int)) {
187 *type = is_signed ? ARGTYPE_INT : ARGTYPE_UINT;
191 if (byte_size == sizeof(long)) {
192 *type = is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG;
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)
204 if (!get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding))
207 if (encoding == DW_ATE_void)
210 if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char)
214 if (!get_die_numeric(&byte_size, die, DW_AT_byte_size))
217 if (encoding == DW_ATE_signed ||
218 encoding == DW_ATE_unsigned ||
219 encoding == DW_ATE_boolean) {
221 bool is_signed = (encoding == DW_ATE_signed);
224 if (!get_integer_base_type(&type, (int)byte_size, is_signed)) {
225 complain(die, "Unknown integer base type. "
232 if (encoding == DW_ATE_float) {
235 return ARGTYPE_FLOAT;
238 return ARGTYPE_DOUBLE;
241 // things like long doubles. ltrace has no support yet,
242 // so I just say "void"
248 if (encoding == DW_ATE_complex_float) {
250 case 2*sizeof(float):
251 return ARGTYPE_FLOAT;
253 case 2*sizeof(double):
254 return ARGTYPE_DOUBLE;
257 // things like long doubles. ltrace has no support yet,
258 // so I just say "void"
264 // Unknown encoding. I just say void
265 complain(die, "Unknown base type. Returning 'void'");
269 static bool get_type_die(Dwarf_Die *type_die, Dwarf_Die *die)
271 Dwarf_Attribute attr;
273 dwarf_attr(die, DW_AT_type, &attr) != NULL &&
274 dwarf_formref_die(&attr, type_die) != NULL;
279 // type_dieoffset_hash dictionary callbacks
280 static size_t dwarf_die_hash(const void *x)
282 return *(const Dwarf_Off*)x;
284 static int dwarf_die_eq(const void *a, const void *b)
286 return *(const Dwarf_Off*)a == *(const Dwarf_Off*)b;
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)
295 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
296 if (dupkey != NULL) \
297 free((void*)dupkey); \
298 if (value != NULL) { \
299 value_destroy(value); \
302 if (lens != NULL) { \
303 lens_destroy(&lens->super); \
306 if (result != NULL) { \
307 type_destroy(result); \
310 dict_erase (type_dieoffset_hash, &die_offset, NULL, \
312 dict_insert(type_dieoffset_hash, &die_offset, \
313 &(struct arg_type_info*){ \
314 type_get_simple(ARGTYPE_VOID)}); \
318 struct arg_type_info *result = NULL;
319 struct enum_lens *lens = NULL;
320 const char *dupkey = NULL;
321 struct value *value = NULL;
323 Dwarf_Off die_offset = dwarf_dieoffset(parent);
325 result = calloc(1, sizeof(struct arg_type_info));
326 if (result == NULL) {
327 complain(parent, "alloc error");
328 CLEANUP_AND_RETURN_ERROR(NULL);
331 dict_insert(type_dieoffset_hash, &die_offset, &result);
334 if (!get_die_numeric(&byte_size, parent, DW_AT_byte_size)) {
335 // No byte size given, assume 'int'
336 result->type = ARGTYPE_INT;
338 if (!get_integer_base_type(&result->type,
339 (int)byte_size, true)) {
340 complain(parent, "Unknown integer base type. "
342 result->type = ARGTYPE_INT;
346 lens = calloc(1, sizeof(struct enum_lens));
348 complain(parent, "alloc error");
349 CLEANUP_AND_RETURN_ERROR(NULL);
351 lens_init_enum(lens);
352 result->lens = &lens->super;
353 result->own_lens = 1;
356 if (dwarf_child(parent, &die) != 0) {
357 // empty enum. we're done
358 CLEANUP_AND_RETURN_ERROR(NULL);
363 complain(&die, "enum element: 0x%02x/'%s'", dwarf_tag(&die),
364 dwarf_diename(&die));
369 if (dwarf_tag(&die) != DW_TAG_enumerator) {
370 complain(&die, "Enums can have ONLY DW_TAG_enumerator "
372 CLEANUP_AND_RETURN_ERROR(NULL);
375 if (!dwarf_hasattr(&die, DW_AT_const_value)) {
376 complain(&die, "Enums MUST have DW_AT_const_value "
378 CLEANUP_AND_RETURN_ERROR(NULL);
381 const char *key = dwarf_diename(&die);
383 complain(&die, "Enums must have a DW_AT_name key");
384 CLEANUP_AND_RETURN_ERROR(NULL);
386 dupkey = strdup(key);
387 if (dupkey == NULL) {
388 complain(&die, "Couldn't duplicate enum key");
389 CLEANUP_AND_RETURN_ERROR(NULL);
392 value = calloc(1, sizeof(struct value));
394 complain(&die, "Couldn't alloc enum value");
395 CLEANUP_AND_RETURN_ERROR(NULL);
398 value_init_detached(value, NULL, type_get_simple(result->type),
401 if (!get_die_numeric(&enum_value, &die, DW_AT_const_value)) {
402 complain(&die, "Couldn't get enum value");
403 CLEANUP_AND_RETURN_ERROR(NULL);
406 value_set_word(value, (long)enum_value);
408 if (lens_enum_add(lens, dupkey, 1, value, 1)) {
409 complain(&die, "Couldn't add enum element");
410 CLEANUP_AND_RETURN_ERROR(NULL);
418 #undef CLEANUP_AND_RETURN_ERROR
421 // returns a newly-allocated art_type_info*, or NULL on error
422 static struct arg_type_info *get_array(Dwarf_Die *parent,
423 struct protolib *plib,
424 struct dict *type_dieoffset_hash)
427 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
428 if (length != NULL) { \
429 expr_destroy(length); \
432 if (array_type != NULL && newly_allocated_array_type) { \
433 type_destroy(array_type); \
436 if (result != NULL) { \
437 type_destroy(result); \
440 dict_erase (type_dieoffset_hash, &die_offset, \
442 dict_insert(type_dieoffset_hash, &die_offset, \
443 &(struct arg_type_info*){ \
444 type_get_simple(ARGTYPE_VOID)}); \
449 struct arg_type_info *result = NULL;
450 struct expr_node *length = NULL;
451 struct arg_type_info *array_type = NULL;
452 int newly_allocated_array_type = 0;
454 Dwarf_Off die_offset = dwarf_dieoffset(parent);
456 result = calloc(1, sizeof(struct arg_type_info));
457 if (result == NULL) {
458 complain(parent, "alloc error");
459 CLEANUP_AND_RETURN_ERROR(NULL);
463 if (!get_type_die(&type_die, parent)) {
464 complain(parent, "Array has unknown type");
465 CLEANUP_AND_RETURN_ERROR(NULL);
468 dict_insert(type_dieoffset_hash, &die_offset, &result);
469 array_type = get_type(&newly_allocated_array_type,
470 &type_die, plib, type_dieoffset_hash);
471 if (array_type == NULL) {
472 complain(parent, "Couldn't figure out array's type");
473 CLEANUP_AND_RETURN_ERROR(NULL);
477 if (dwarf_child(parent, &subrange) != 0) {
479 "Array must have a DW_TAG_subrange_type child, "
481 CLEANUP_AND_RETURN_ERROR(NULL);
484 Dwarf_Die next_subrange;
485 if (dwarf_siblingof(&subrange, &next_subrange) <= 0) {
487 "Array must have exactly one DW_TAG_subrange_type "
489 CLEANUP_AND_RETURN_ERROR(NULL);
492 if (dwarf_hasattr(&subrange, DW_AT_lower_bound)) {
493 uint64_t lower_bound;
494 if (!get_die_numeric(&lower_bound, &subrange,
495 DW_AT_lower_bound)) {
496 complain(parent, "Couldn't read lower bound");
497 CLEANUP_AND_RETURN_ERROR(NULL);
500 if (lower_bound != 0) {
502 "Array subrange has a nonzero lower bound. "
503 "Don't know what to do");
504 CLEANUP_AND_RETURN_ERROR(NULL);
509 if (!dwarf_hasattr(&subrange, DW_AT_upper_bound)) {
510 // no upper bound is defined. This is probably a variable-width
511 // array, and I don't know how long it is. Let's say 0 to be
517 if (!get_die_numeric(&N, &subrange, DW_AT_upper_bound)) {
518 complain(parent, "Couldn't read upper bound");
519 CLEANUP_AND_RETURN_ERROR(NULL);
524 // I'm not checking the subrange type. It should be some sort of
525 // integer, and I don't know what it would mean for it to be something
527 length = calloc(1, sizeof(struct expr_node));
528 if (length == NULL) {
529 complain(&subrange, "Couldn't alloc length expr");
530 CLEANUP_AND_RETURN_ERROR(NULL);
532 expr_init_const_word(length, N, type_get_simple(ARGTYPE_INT), 0);
534 type_init_array(result, array_type, newly_allocated_array_type,
538 #undef CLEANUP_AND_RETURN_ERROR
541 // returns a newly-allocated art_type_info*, or NULL on error
542 static struct arg_type_info *get_structure(Dwarf_Die *parent,
543 struct protolib *plib,
544 struct dict *type_dieoffset_hash)
547 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
548 if (member_type != NULL && newly_allocated_member_type) { \
549 type_destroy(member_type); \
552 if (result != NULL) { \
553 type_destroy(result); \
556 dict_erase (type_dieoffset_hash, &die_offset, \
558 dict_insert(type_dieoffset_hash, &die_offset, \
559 &(struct arg_type_info*){ \
560 type_get_simple(ARGTYPE_VOID)}); \
565 struct arg_type_info *result = NULL;
566 struct arg_type_info *member_type = NULL;
567 int newly_allocated_member_type = 0;
569 Dwarf_Off die_offset = dwarf_dieoffset(parent);
571 result = calloc(1, sizeof(struct arg_type_info));
572 if (result == NULL) {
573 complain(parent, "alloc error");
574 CLEANUP_AND_RETURN_ERROR(NULL);
576 type_init_struct(result);
577 dict_insert(type_dieoffset_hash, &die_offset, &result);
580 if (dwarf_child(parent, &die) != 0) {
581 // no elements; we're done
587 newly_allocated_member_type = 0;
589 complain(&die, "member: 0x%02x", dwarf_tag(&die));
591 if (dwarf_tag(&die) != DW_TAG_member) {
592 complain(&die, "Structure can have ONLY DW_TAG_member");
593 CLEANUP_AND_RETURN_ERROR(NULL);
597 if (!get_type_die(&type_die, &die)) {
598 complain(&die, "Couldn't get type of element");
599 CLEANUP_AND_RETURN_ERROR(NULL);
602 member_type = get_type(&newly_allocated_member_type,
603 &type_die, plib, type_dieoffset_hash);
604 if (member_type == NULL) {
605 complain(&die, "Couldn't parse type from DWARF data");
606 CLEANUP_AND_RETURN_ERROR(NULL);
608 type_struct_add(result, member_type,
609 newly_allocated_member_type);
615 #undef CLEANUP_AND_RETURN_ERROR
618 // Reads the type in the die and returns the corresponding arg_type_info*. If
619 // this was newly allocated on the heap, *newly_allocated_info = true. If an
620 // error occurred, returns NULL
621 static struct arg_type_info *get_type(int *newly_allocated_result,
623 struct protolib *plib,
624 struct dict *type_dieoffset_hash)
627 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
628 if (pointee != NULL && newly_allocated_pointee) { \
629 type_destroy(pointee); \
632 if (result != NULL && *newly_allocated_result) { \
633 type_destroy(result); \
636 dict_erase (type_dieoffset_hash, &die_offset, \
638 dict_insert(type_dieoffset_hash, &die_offset, \
639 &(struct arg_type_info*){ \
640 type_get_simple(ARGTYPE_VOID)}); \
644 struct arg_type_info *result = NULL;
645 struct arg_type_info *pointee = NULL;
646 int newly_allocated_pointee = 0;
648 Dwarf_Off die_offset = dwarf_dieoffset(type_die);
651 // by default, we say we allocated nothing. I set this to true later,
652 // when I allocate memory
653 *newly_allocated_result = 0;
655 struct arg_type_info **found_type = dict_find(type_dieoffset_hash,
657 if (found_type != NULL) {
658 complain(type_die, "Read pre-computed type");
662 const char *type_name = dwarf_diename(type_die);
663 if (type_name != NULL) {
665 struct named_type *already_defined_type =
666 protolib_lookup_type(plib, type_name, true);
668 if (already_defined_type != NULL) {
670 "Type '%s' defined in a .conf file. "
671 "Using that instead of DWARF",
673 return already_defined_type->info;
679 switch (dwarf_tag(type_die)) {
680 case DW_TAG_base_type:
681 complain(type_die, "Storing base type");
682 result = type_get_simple(get_base_type(type_die));
683 dict_insert(type_dieoffset_hash, &die_offset, &result);
686 case DW_TAG_subroutine_type:
687 case DW_TAG_inlined_subroutine:
688 // function pointers are stored as void*. If ltrace tries to
689 // dereference these, it'll get a segfault
690 complain(type_die, "Storing subroutine type");
691 result = type_get_simple(ARGTYPE_VOID);
692 dict_insert(type_dieoffset_hash, &die_offset, &result);
695 case DW_TAG_pointer_type:
696 if (!get_type_die(&next_die, type_die)) {
697 // the pointed-to type isn't defined, so I report a
699 complain(type_die, "Storing void-pointer type");
700 result = type_get_voidptr();
701 dict_insert(type_dieoffset_hash, &die_offset, &result);
705 complain(type_die, "Storing pointer type");
707 *newly_allocated_result = 1;
708 result = calloc(1, sizeof(struct arg_type_info));
709 if (result == NULL) {
710 complain(type_die, "alloc error");
711 CLEANUP_AND_RETURN_ERROR(NULL);
713 dict_insert(type_dieoffset_hash, &die_offset, &result);
714 pointee = get_type(&newly_allocated_pointee,
715 &next_die, plib, type_dieoffset_hash);
717 CLEANUP_AND_RETURN_ERROR(NULL);
719 type_init_pointer(result, pointee, newly_allocated_pointee);
722 case DW_TAG_structure_type:
723 complain(type_die, "Storing struct type");
724 *newly_allocated_result = 1;
726 result = get_structure(type_die, plib, type_dieoffset_hash);
728 CLEANUP_AND_RETURN_ERROR(NULL);
733 case DW_TAG_const_type:
734 case DW_TAG_volatile_type:
735 // Various tags are simply pass-through, so I just keep going
736 if (get_type_die(&next_die, type_die)) {
737 complain(type_die, "Storing const/typedef type");
739 result = get_type(newly_allocated_result, &next_die,
740 plib, type_dieoffset_hash);
742 CLEANUP_AND_RETURN_ERROR(NULL);
744 // no type. Use 'void'. Normally I'd think this is
745 // bogus, but stdio typedefs something to void
746 result = type_get_simple(ARGTYPE_VOID);
747 complain(type_die, "Storing void type");
749 dict_insert(type_dieoffset_hash, &die_offset, &result);
752 case DW_TAG_enumeration_type:
753 // We have an enumeration. This has a base type, but has a
754 // particular lens to handle the enum
755 *newly_allocated_result = 1;
757 complain(type_die, "Storing enum int");
758 result = get_enum(type_die, type_dieoffset_hash);
760 CLEANUP_AND_RETURN_ERROR(NULL);
763 case DW_TAG_array_type:
764 *newly_allocated_result = 1;
766 complain(type_die, "Storing array");
767 result = get_array(type_die, plib, type_dieoffset_hash);
769 CLEANUP_AND_RETURN_ERROR(NULL);
772 case DW_TAG_union_type:
773 result = type_get_simple(ARGTYPE_VOID);
774 complain(type_die, "Storing union-as-void type");
775 dict_insert(type_dieoffset_hash, &die_offset, &result);
779 complain(type_die, "Unknown type tag 0x%x. Returning void",
780 dwarf_tag(type_die));
781 result = type_get_simple(ARGTYPE_VOID);
782 dict_insert(type_dieoffset_hash, &die_offset, &result);
786 #undef CLEANUP_AND_RETURN_ERROR
789 // fills in *proto with a prototype. Returns true on success
790 static bool get_prototype(struct prototype *result,
791 Dwarf_Die *subroutine, struct protolib *plib,
792 struct dict *type_dieoffset_hash)
795 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
796 if (argument_type != NULL && newly_allocated_argument_type) { \
797 type_destroy(argument_type); \
798 free(argument_type); \
800 prototype_destroy(result); \
805 struct arg_type_info *argument_type = NULL;
806 int newly_allocated_argument_type = 0;
808 prototype_init(result);
810 // First, look at the return type. This is stored in a DW_AT_type tag in
811 // the subroutine DIE. If there is no such tag, this function returns
813 Dwarf_Die return_type_die;
814 if (!get_type_die(&return_type_die, subroutine)) {
815 result->return_info = type_get_simple(ARGTYPE_VOID);
816 result->own_return_info = 0;
818 int newly_allocated_return_type;
819 result->return_info = get_type(&newly_allocated_return_type,
820 &return_type_die, plib,
821 type_dieoffset_hash);
822 if (result->return_info == NULL) {
823 complain(subroutine, "Couldn't get return type");
824 CLEANUP_AND_RETURN_ERROR(false);
826 result->own_return_info = newly_allocated_return_type;
830 // Now look at the arguments
832 if (dwarf_child(subroutine, &arg_die) != 0) {
833 // no args. We're done
838 if (dwarf_tag(&arg_die) == DW_TAG_formal_parameter) {
840 complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die));
842 argument_type = NULL;
843 newly_allocated_argument_type = false;
846 if (!get_type_die(&type_die, &arg_die)) {
847 complain(&arg_die, "Couldn't get the argument "
849 CLEANUP_AND_RETURN_ERROR(false);
853 argument_type = get_type(&newly_allocated_argument_type,
855 type_dieoffset_hash);
856 if (argument_type==NULL) {
857 complain(&arg_die, "Couldn't parse arg "
858 "type from DWARF data");
859 CLEANUP_AND_RETURN_ERROR(false);
863 param_init_type(¶m, argument_type,
864 newly_allocated_argument_type);
865 if (prototype_push_param(result, ¶m) <0) {
866 complain(&arg_die, "couldn't add argument to "
868 CLEANUP_AND_RETURN_ERROR(false);
871 #ifdef DUMP_PROTOTYPES
872 fprintf(stderr, "Adding argument:\n");
873 dump_ltrace_tree(argument_type);
877 NEXT_SIBLING(&arg_die);
881 #undef CLEANUP_AND_RETURN_ERROR
884 static bool import_subprogram(struct protolib *plib, struct library *lib,
885 struct dict *type_dieoffset_hash,
888 // I use the linkage function name if there is one, otherwise the
890 const char *function_name = NULL;
891 Dwarf_Attribute attr;
892 if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL)
893 function_name = dwarf_formstring(&attr);
894 if (function_name == NULL)
895 function_name = dwarf_diename(die);
896 if (function_name == NULL) {
897 complain(die, "Function has no name. Not importing");
901 if (!filter_matches_symbol(options.plt_filter, function_name, lib) &&
902 !filter_matches_symbol(options.static_filter, function_name, lib) &&
903 !filter_matches_symbol(options.export_filter, function_name, lib)) {
904 complain(die, "Prototype not requested by any filter");
908 complain(die, "subroutine_type: 0x%02x; function '%s'",
909 dwarf_tag(die), function_name);
911 struct prototype *proto_already_there =
912 protolib_lookup_prototype(plib, function_name, false);
914 if (proto_already_there != NULL) {
915 complain(die, "Prototype already exists. Skipping");
919 struct prototype proto;
920 if (!get_prototype(&proto, die, plib, type_dieoffset_hash)) {
921 complain(die, "couldn't get prototype");
925 const char *function_name_dup = strdup(function_name);
926 if (function_name_dup == NULL) {
927 complain(die, "couldn't strdup");
928 prototype_destroy(&proto);
931 protolib_add_prototype(plib, function_name_dup, 1, &proto);
935 static bool process_die_compileunit(struct protolib *plib, struct library *lib,
936 struct dict *type_dieoffset_hash,
939 complain(parent, "Processing compile unit");
941 if (dwarf_child(parent, &die) != 0) {
942 // no child nodes, so nothing to do
947 if (dwarf_tag(&die) == DW_TAG_subprogram)
948 if (!import_subprogram(plib, lib, type_dieoffset_hash,
950 complain(&die, "Error importing subprogram. "
959 static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
961 // A map from DIE addresses (Dwarf_Off) to type structures (struct
962 // arg_type_info*). This is created and filled in at the start of each
963 // import, and deleted when the import is complete
964 struct dict type_dieoffset_hash;
966 dict_init(&type_dieoffset_hash, sizeof(Dwarf_Off),
967 sizeof(struct arg_type_info*),
968 dwarf_die_hash, dwarf_die_eq, NULL);
971 Dwarf_Die *die = NULL;
972 while ((die = dwfl_nextcu(dwfl, die, &bias)) != NULL) {
973 if (dwarf_tag(die) == DW_TAG_compile_unit)
974 process_die_compileunit(plib, lib,
975 &type_dieoffset_hash, die);
977 complain(die, "A DW_TAG_compile_unit die expected. "
978 "Skipping this one");
981 dict_destroy(&type_dieoffset_hash, NULL, NULL, NULL);
984 bool import_DWARF_prototypes(struct library *lib)
986 struct protolib *plib = lib->protolib;
987 Dwfl *dwfl = lib->dwfl;
989 debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
993 const char *soname_dup = strdup(lib->soname);
994 if (soname_dup == NULL) {
995 fprintf(stderr, "couldn't strdup");
999 plib = protolib_cache_default(&g_protocache, soname_dup, 1);
1001 fprintf(stderr, "Error loading protolib %s: %s.\n",
1002 lib->soname, strerror(errno));
1006 import(plib, lib, dwfl);
1007 lib->protolib = plib;