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,
176 *type = ARGTYPE_CHAR;
180 *type = is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT;
184 *type = is_signed ? ARGTYPE_INT : ARGTYPE_UINT;
188 *type = is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG;
196 // returns an ltrace ARGTYPE_XXX base type from the given die. If we dont
197 // support a particular type (or an error occurred), I regturn ARGTYPE_VOID
198 static enum arg_type get_base_type(Dwarf_Die *die)
201 if (!get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding))
204 if (encoding == DW_ATE_void)
207 if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char)
211 if (!get_die_numeric(&byte_size, die, DW_AT_byte_size))
214 if (encoding == DW_ATE_signed ||
215 encoding == DW_ATE_unsigned ||
216 encoding == DW_ATE_boolean) {
218 bool is_signed = (encoding == DW_ATE_signed);
221 if (!get_integer_base_type(&type, (int)byte_size, is_signed)) {
222 complain(die, "Unknown integer base type. "
229 if (encoding == DW_ATE_float) {
232 return ARGTYPE_FLOAT;
235 return ARGTYPE_DOUBLE;
238 // things like long doubles. ltrace has no support yet,
239 // so I just say "void"
245 if (encoding == DW_ATE_complex_float) {
247 case 2*sizeof(float):
248 return ARGTYPE_FLOAT;
250 case 2*sizeof(double):
251 return ARGTYPE_DOUBLE;
254 // things like long doubles. ltrace has no support yet,
255 // so I just say "void"
261 // Unknown encoding. I just say void
262 complain(die, "Unknown base type. Returning 'void'");
266 static bool get_type_die(Dwarf_Die *type_die, Dwarf_Die *die)
268 Dwarf_Attribute attr;
270 dwarf_attr(die, DW_AT_type, &attr) != NULL &&
271 dwarf_formref_die(&attr, type_die) != NULL;
276 // type_dieoffset_hash dictionary callbacks
277 static size_t dwarf_die_hash(const void *x)
279 return *(const Dwarf_Off*)x;
281 static int dwarf_die_eq(const void *a, const void *b)
283 return *(const Dwarf_Off*)a == *(const Dwarf_Off*)b;
287 // returns a newly-allocated art_type_info*, or NULL on error
288 static struct arg_type_info *get_enum(Dwarf_Die *parent,
289 struct dict *type_dieoffset_hash)
292 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
293 if (dupkey != NULL) \
294 free((void*)dupkey); \
295 if (value != NULL) { \
296 value_destroy(value); \
299 if (lens != NULL ) { \
300 lens_destroy(&lens->super); \
303 if (result != NULL) { \
304 type_destroy(result); \
307 dict_erase (type_dieoffset_hash, &die_offset, NULL, \
309 dict_insert(type_dieoffset_hash, &die_offset, \
310 &(struct arg_type_info*){ \
311 type_get_simple(ARGTYPE_VOID)}); \
315 struct arg_type_info* result = NULL;
316 struct enum_lens* lens = NULL;
317 const char* dupkey = NULL;
318 struct value* value = NULL;
320 Dwarf_Off die_offset = dwarf_dieoffset(parent);
322 result = calloc(1, sizeof(struct arg_type_info));
323 if (result == NULL) {
324 complain(parent, "alloc error");
325 CLEANUP_AND_RETURN_ERROR(NULL);
328 dict_insert(type_dieoffset_hash, &die_offset, &result);
331 if (!get_die_numeric(&byte_size, parent, DW_AT_byte_size)) {
332 // No byte size given, assume 'int'
333 result->type = ARGTYPE_INT;
335 if (!get_integer_base_type(&result->type,
336 (int)byte_size, true)) {
337 complain(parent, "Unknown integer base type. "
339 result->type = ARGTYPE_INT;
343 lens = calloc(1, sizeof(struct enum_lens));
345 complain(parent, "alloc error");
346 CLEANUP_AND_RETURN_ERROR(NULL);
348 lens_init_enum(lens);
349 result->lens = &lens->super;
350 result->own_lens = 1;
353 if (dwarf_child(parent, &die) != 0) {
354 // empty enum. we're done
355 CLEANUP_AND_RETURN_ERROR(NULL);
360 complain(&die, "enum element: 0x%02x/'%s'", dwarf_tag(&die),
361 dwarf_diename(&die));
366 if (dwarf_tag(&die) != DW_TAG_enumerator) {
367 complain(&die, "Enums can have ONLY DW_TAG_enumerator "
369 CLEANUP_AND_RETURN_ERROR(NULL);
372 if (!dwarf_hasattr(&die, DW_AT_const_value)) {
373 complain(&die, "Enums MUST have DW_AT_const_value "
375 CLEANUP_AND_RETURN_ERROR(NULL);
378 const char *key = dwarf_diename(&die);
380 complain(&die, "Enums must have a DW_AT_name key");
381 CLEANUP_AND_RETURN_ERROR(NULL);
383 dupkey = strdup(key);
384 if (dupkey == NULL) {
385 complain(&die, "Couldn't duplicate enum key");
386 CLEANUP_AND_RETURN_ERROR(NULL);
389 value = calloc(1, sizeof(struct value));
391 complain(&die, "Couldn't alloc enum value");
392 CLEANUP_AND_RETURN_ERROR(NULL);
395 value_init_detached(value, NULL, type_get_simple(result->type),
398 if (!get_die_numeric(&enum_value, &die, DW_AT_const_value)) {
399 complain(&die, "Couldn't get enum value");
400 CLEANUP_AND_RETURN_ERROR(NULL);
403 value_set_word(value, (long)enum_value);
405 if (lens_enum_add(lens, dupkey, 1, value, 1)) {
406 complain(&die, "Couldn't add enum element");
407 CLEANUP_AND_RETURN_ERROR(NULL);
415 #undef CLEANUP_AND_RETURN_ERROR
418 // returns a newly-allocated art_type_info*, or NULL on error
419 static struct arg_type_info *get_array( Dwarf_Die *parent,
420 struct protolib *plib,
421 struct dict *type_dieoffset_hash)
424 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
425 if (length != NULL) { \
426 expr_destroy(length); \
429 if (array_type != NULL && newly_allocated_array_type) { \
430 type_destroy(array_type); \
433 if (result != NULL) { \
434 type_destroy(result); \
437 dict_erase (type_dieoffset_hash, &die_offset, \
439 dict_insert(type_dieoffset_hash, &die_offset, \
440 &(struct arg_type_info*){ \
441 type_get_simple(ARGTYPE_VOID)}); \
446 struct arg_type_info* result = NULL;
447 struct expr_node* length = NULL;
448 struct arg_type_info* array_type = NULL;
449 int newly_allocated_array_type = 0;
451 Dwarf_Off die_offset = dwarf_dieoffset(parent);
453 result = calloc(1, sizeof(struct arg_type_info));
454 if (result == NULL) {
455 complain(parent, "alloc error");
456 CLEANUP_AND_RETURN_ERROR(NULL);
460 if (!get_type_die(&type_die, parent)) {
461 complain(parent, "Array has unknown type");
462 CLEANUP_AND_RETURN_ERROR(NULL);
465 dict_insert(type_dieoffset_hash, &die_offset, &result);
466 array_type = get_type(&newly_allocated_array_type,
467 &type_die, plib, type_dieoffset_hash);
468 if ( array_type == NULL ) {
469 complain(parent, "Couldn't figure out array's type");
470 CLEANUP_AND_RETURN_ERROR(NULL);
474 if (dwarf_child(parent, &subrange) != 0) {
476 "Array must have a DW_TAG_subrange_type child, "
478 CLEANUP_AND_RETURN_ERROR(NULL);
481 Dwarf_Die next_subrange;
482 if (dwarf_siblingof(&subrange, &next_subrange) <= 0) {
484 "Array must have exactly one DW_TAG_subrange_type "
486 CLEANUP_AND_RETURN_ERROR(NULL);
489 if (dwarf_hasattr(&subrange, DW_AT_lower_bound)) {
490 uint64_t lower_bound;
491 if (!get_die_numeric(&lower_bound, &subrange,
492 DW_AT_lower_bound)) {
493 complain(parent, "Couldn't read lower bound");
494 CLEANUP_AND_RETURN_ERROR(NULL);
497 if (lower_bound != 0) {
499 "Array subrange has a nonzero lower bound. "
500 "Don't know what to do");
501 CLEANUP_AND_RETURN_ERROR(NULL);
506 if (!dwarf_hasattr(&subrange, DW_AT_upper_bound)) {
507 // no upper bound is defined. This is probably a variable-width
508 // array, and I don't know how long it is. Let's say 0 to be
514 if (!get_die_numeric(&N, &subrange, DW_AT_upper_bound)) {
515 complain(parent, "Couldn't read upper bound");
516 CLEANUP_AND_RETURN_ERROR(NULL);
521 // I'm not checking the subrange type. It should be some sort of
522 // integer, and I don't know what it would mean for it to be something
524 length = calloc(1, sizeof(struct expr_node));
525 if (length == NULL) {
526 complain(&subrange, "Couldn't alloc length expr");
527 CLEANUP_AND_RETURN_ERROR(NULL);
529 expr_init_const_word(length, N, type_get_simple(ARGTYPE_INT), 0);
531 type_init_array(result, array_type, newly_allocated_array_type,
535 #undef CLEANUP_AND_RETURN_ERROR
538 // returns a newly-allocated art_type_info*, or NULL on error
539 static struct arg_type_info *get_structure(Dwarf_Die *parent,
540 struct protolib *plib,
541 struct dict *type_dieoffset_hash)
544 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
545 if (member_type != NULL && newly_allocated_member_type) { \
546 type_destroy(member_type); \
549 if (result != NULL) { \
550 type_destroy(result); \
553 dict_erase (type_dieoffset_hash, &die_offset, \
555 dict_insert(type_dieoffset_hash, &die_offset, \
556 &(struct arg_type_info*){ \
557 type_get_simple(ARGTYPE_VOID)}); \
562 struct arg_type_info* result = NULL;
563 struct arg_type_info* member_type = NULL;
564 int newly_allocated_member_type = 0;
566 Dwarf_Off die_offset = dwarf_dieoffset(parent);
568 result = calloc(1, sizeof(struct arg_type_info));
569 if (result == NULL) {
570 complain(parent, "alloc error");
571 CLEANUP_AND_RETURN_ERROR(NULL);
573 type_init_struct(result);
574 dict_insert(type_dieoffset_hash, &die_offset, &result);
577 if (dwarf_child(parent, &die) != 0) {
578 // no elements; we're done
584 newly_allocated_member_type = 0;
586 complain(&die, "member: 0x%02x", dwarf_tag(&die));
588 if (dwarf_tag(&die) != DW_TAG_member) {
589 complain(&die, "Structure can have ONLY DW_TAG_member");
590 CLEANUP_AND_RETURN_ERROR(NULL);
594 if (!get_type_die(&type_die, &die)) {
595 complain(&die, "Couldn't get type of element");
596 CLEANUP_AND_RETURN_ERROR(NULL);
599 member_type = get_type(&newly_allocated_member_type,
600 &type_die, plib, type_dieoffset_hash);
601 if (member_type == NULL) {
602 complain(&die, "Couldn't parse type from DWARF data");
603 CLEANUP_AND_RETURN_ERROR(NULL);
605 type_struct_add(result, member_type,
606 newly_allocated_member_type);
612 #undef CLEANUP_AND_RETURN_ERROR
615 // Reads the type in the die and returns the corresponding arg_type_info*. If
616 // this was newly allocated on the heap, *newly_allocated_info = true. If an
617 // error occurred, returns NULL
618 static struct arg_type_info *get_type(int *newly_allocated_result,
620 struct protolib *plib,
621 struct dict *type_dieoffset_hash)
624 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
625 if (pointee != NULL && newly_allocated_pointee) { \
626 type_destroy(pointee); \
629 if (result != NULL && *newly_allocated_result) { \
630 type_destroy(result); \
633 dict_erase (type_dieoffset_hash, &die_offset, \
635 dict_insert(type_dieoffset_hash, &die_offset, \
636 &(struct arg_type_info*){ \
637 type_get_simple(ARGTYPE_VOID)}); \
641 struct arg_type_info* result = NULL;
642 struct arg_type_info* pointee = NULL;
643 int newly_allocated_pointee = 0;
645 Dwarf_Off die_offset = dwarf_dieoffset(type_die);
648 // by default, we say we allocated nothing. I set this to true later,
649 // when I allocate memory
650 *newly_allocated_result = 0;
652 struct arg_type_info **found_type = dict_find(type_dieoffset_hash,
654 if (found_type != NULL) {
655 complain(type_die, "Read pre-computed type");
659 const char *type_name = dwarf_diename(type_die);
660 if (type_name != NULL) {
662 struct named_type *already_defined_type =
663 protolib_lookup_type(plib, type_name, true);
665 if (already_defined_type != NULL) {
667 "Type '%s' defined in a .conf file. "
668 "Using that instead of DWARF",
670 return already_defined_type->info;
676 switch (dwarf_tag(type_die)) {
677 case DW_TAG_base_type:
678 complain(type_die, "Storing base type");
679 result = type_get_simple(get_base_type(type_die));
680 dict_insert(type_dieoffset_hash, &die_offset, &result);
683 case DW_TAG_subroutine_type:
684 case DW_TAG_inlined_subroutine:
685 // function pointers are stored as void*. If ltrace tries to
686 // dereference these, it'll get a segfault
687 complain(type_die, "Storing subroutine type");
688 result = type_get_simple(ARGTYPE_VOID);
689 dict_insert(type_dieoffset_hash, &die_offset, &result);
692 case DW_TAG_pointer_type:
693 if (!get_type_die(&next_die, type_die)) {
694 // the pointed-to type isn't defined, so I report a
696 complain(type_die, "Storing void-pointer type");
697 result = type_get_voidptr();
698 dict_insert(type_dieoffset_hash, &die_offset, &result);
702 complain(type_die, "Storing pointer type");
704 *newly_allocated_result = 1;
705 result = calloc(1, sizeof(struct arg_type_info));
706 if (result == NULL) {
707 complain(type_die, "alloc error");
708 CLEANUP_AND_RETURN_ERROR(NULL);
710 dict_insert(type_dieoffset_hash, &die_offset, &result);
711 pointee = get_type(&newly_allocated_pointee,
712 &next_die, plib, type_dieoffset_hash);
714 CLEANUP_AND_RETURN_ERROR(NULL);
716 type_init_pointer(result, pointee, newly_allocated_pointee);
719 case DW_TAG_structure_type:
720 complain(type_die, "Storing struct type");
721 *newly_allocated_result = 1;
723 result = get_structure(type_die, plib, type_dieoffset_hash);
725 CLEANUP_AND_RETURN_ERROR(NULL);
730 case DW_TAG_const_type:
731 case DW_TAG_volatile_type:
732 // Various tags are simply pass-through, so I just keep going
733 if (get_type_die(&next_die, type_die)) {
734 complain(type_die, "Storing const/typedef type");
736 result = get_type(newly_allocated_result, &next_die,
737 plib, type_dieoffset_hash);
739 CLEANUP_AND_RETURN_ERROR(NULL);
741 // no type. Use 'void'. Normally I'd think this is
742 // bogus, but stdio typedefs something to void
743 result = type_get_simple(ARGTYPE_VOID);
744 complain(type_die, "Storing void type");
746 dict_insert(type_dieoffset_hash, &die_offset, &result);
749 case DW_TAG_enumeration_type:
750 // We have an enumeration. This has a base type, but has a
751 // particular lens to handle the enum
752 *newly_allocated_result = 1;
754 complain(type_die, "Storing enum int");
755 result = get_enum(type_die, type_dieoffset_hash);
757 CLEANUP_AND_RETURN_ERROR(NULL);
760 case DW_TAG_array_type:
761 *newly_allocated_result = 1;
763 complain(type_die, "Storing array");
764 result = get_array(type_die, plib, type_dieoffset_hash);
766 CLEANUP_AND_RETURN_ERROR(NULL);
769 case DW_TAG_union_type:
770 result = type_get_simple(ARGTYPE_VOID);
771 complain(type_die, "Storing union-as-void type");
772 dict_insert(type_dieoffset_hash, &die_offset, &result);
776 complain(type_die, "Unknown type tag 0x%x. Returning void",
777 dwarf_tag(type_die));
778 result = type_get_simple(ARGTYPE_VOID);
779 dict_insert(type_dieoffset_hash, &die_offset, &result);
783 #undef CLEANUP_AND_RETURN_ERROR
786 // fills in *proto with a prototype. Returns true on success
787 static bool get_prototype( struct prototype *result,
788 Dwarf_Die *subroutine, struct protolib *plib,
789 struct dict *type_dieoffset_hash)
792 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
793 if (argument_type != NULL && newly_allocated_argument_type) { \
794 type_destroy(argument_type); \
795 free(argument_type); \
797 prototype_destroy(result); \
802 struct arg_type_info* argument_type = NULL;
803 int newly_allocated_argument_type = 0;
805 prototype_init(result);
807 // First, look at the return type. This is stored in a DW_AT_type tag in
808 // the subroutine DIE. If there is no such tag, this function returns
810 Dwarf_Die return_type_die;
811 if (!get_type_die(&return_type_die, subroutine)) {
812 result->return_info = type_get_simple(ARGTYPE_VOID);
813 result->own_return_info = 0;
815 int newly_allocated_return_type;
816 result->return_info = get_type(&newly_allocated_return_type,
817 &return_type_die, plib,
818 type_dieoffset_hash);
819 if (result->return_info == NULL) {
820 complain(subroutine, "Couldn't get return type");
821 CLEANUP_AND_RETURN_ERROR(false);
823 result->own_return_info = newly_allocated_return_type;
827 // Now look at the arguments
829 if (dwarf_child(subroutine, &arg_die) != 0) {
830 // no args. We're done
835 if (dwarf_tag(&arg_die) == DW_TAG_formal_parameter) {
837 complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die));
839 argument_type = NULL;
840 newly_allocated_argument_type = false;
843 if (!get_type_die(&type_die, &arg_die)) {
844 complain(&arg_die, "Couldn't get the argument "
846 CLEANUP_AND_RETURN_ERROR(false);
850 argument_type = get_type(&newly_allocated_argument_type,
852 type_dieoffset_hash);
853 if (argument_type==NULL) {
854 complain(&arg_die, "Couldn't parse arg "
855 "type from DWARF data");
856 CLEANUP_AND_RETURN_ERROR(false);
860 param_init_type(¶m, argument_type,
861 newly_allocated_argument_type);
862 if (prototype_push_param(result, ¶m) <0) {
863 complain(&arg_die, "couldn't add argument to "
865 CLEANUP_AND_RETURN_ERROR(false);
868 #ifdef DUMP_PROTOTYPES
869 fprintf(stderr, "Adding argument:\n");
870 dump_ltrace_tree(argument_type);
874 NEXT_SIBLING(&arg_die);
878 #undef CLEANUP_AND_RETURN_ERROR
881 static bool import_subprogram(struct protolib *plib, struct library *lib,
882 struct dict *type_dieoffset_hash,
885 // I use the linkage function name if there is one, otherwise the
887 const char *function_name = NULL;
888 Dwarf_Attribute attr;
889 if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL)
890 function_name = dwarf_formstring(&attr);
891 if (function_name == NULL)
892 function_name = dwarf_diename(die);
893 if (function_name == NULL) {
894 complain(die, "Function has no name. Not importing");
898 if (!filter_matches_symbol(options.plt_filter, function_name, lib) &&
899 !filter_matches_symbol(options.static_filter, function_name, lib) &&
900 !filter_matches_symbol(options.export_filter, function_name, lib)) {
901 complain(die, "Prototype not requested by any filter");
905 complain(die, "subroutine_type: 0x%02x; function '%s'",
906 dwarf_tag(die), function_name);
908 struct prototype *proto_already_there =
909 protolib_lookup_prototype(plib, function_name, false);
911 if (proto_already_there != NULL) {
912 complain(die, "Prototype already exists. Skipping");
916 struct prototype proto;
917 if (!get_prototype(&proto, die, plib, type_dieoffset_hash)) {
918 complain(die, "couldn't get prototype");
922 const char *function_name_dup = strdup(function_name);
923 if ( function_name_dup == NULL ) {
924 complain(die, "couldn't strdup");
925 prototype_destroy(&proto);
928 protolib_add_prototype(plib, function_name_dup, 1, &proto);
932 static bool process_die_compileunit(struct protolib *plib, struct library *lib,
933 struct dict *type_dieoffset_hash,
936 complain(parent, "Processing compile unit");
938 if (dwarf_child(parent, &die) != 0) {
939 // no child nodes, so nothing to do
944 if (dwarf_tag(&die) == DW_TAG_subprogram)
945 if (!import_subprogram(plib, lib, type_dieoffset_hash,
947 complain(&die, "Error importing subprogram. "
956 static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
958 // A map from DIE addresses (Dwarf_Off) to type structures (struct
959 // arg_type_info*). This is created and filled in at the start of each
960 // import, and deleted when the import is complete
961 struct dict type_dieoffset_hash;
963 dict_init(&type_dieoffset_hash, sizeof(Dwarf_Off),
964 sizeof(struct arg_type_info*),
965 dwarf_die_hash, dwarf_die_eq, NULL);
968 Dwarf_Die *die = NULL;
969 while ((die = dwfl_nextcu(dwfl, die, &bias)) != NULL) {
970 if (dwarf_tag(die) == DW_TAG_compile_unit)
971 process_die_compileunit(plib, lib,
972 &type_dieoffset_hash, die);
974 complain(die, "A DW_TAG_compile_unit die expected. "
975 "Skipping this one");
978 dict_destroy(&type_dieoffset_hash, NULL, NULL, NULL);
981 bool import_DWARF_prototypes(struct library *lib)
983 struct protolib* plib = lib->protolib;
984 Dwfl* dwfl = lib->dwfl;
986 debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
990 const char *soname_dup = strdup(lib->soname);
991 if ( soname_dup == NULL ) {
992 fprintf(stderr, "couldn't strdup");
996 plib = protolib_cache_default(&g_protocache, soname_dup, 1);
998 fprintf(stderr, "Error loading protolib %s: %s.\n",
999 lib->soname, strerror(errno));
1003 import(plib, lib, dwfl);
1004 lib->protolib = plib;