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(&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 if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
332 complain(parent, "Couldn't insert into cache dict");
333 CLEANUP_AND_RETURN_ERROR(NULL);
337 if (!get_die_numeric(&byte_size, parent, DW_AT_byte_size)) {
338 // No byte size given, assume 'int'
339 result->type = ARGTYPE_INT;
341 if (!get_integer_base_type(&result->type,
342 (int)byte_size, true)) {
343 complain(parent, "Unknown integer base type. "
345 result->type = ARGTYPE_INT;
349 lens = calloc(1, sizeof(struct enum_lens));
351 complain(parent, "alloc error");
352 CLEANUP_AND_RETURN_ERROR(NULL);
354 lens_init_enum(lens);
355 result->lens = &lens->super;
356 result->own_lens = 1;
359 if (dwarf_child(parent, &die) != 0) {
360 // empty enum. we're done
361 CLEANUP_AND_RETURN_ERROR(NULL);
366 complain(&die, "enum element: 0x%02x/'%s'", dwarf_tag(&die),
367 dwarf_diename(&die));
372 if (dwarf_tag(&die) != DW_TAG_enumerator) {
373 complain(&die, "Enums can have ONLY DW_TAG_enumerator "
375 CLEANUP_AND_RETURN_ERROR(NULL);
378 if (!dwarf_hasattr(&die, DW_AT_const_value)) {
379 complain(&die, "Enums MUST have DW_AT_const_value "
381 CLEANUP_AND_RETURN_ERROR(NULL);
384 const char *key = dwarf_diename(&die);
386 complain(&die, "Enums must have a DW_AT_name key");
387 CLEANUP_AND_RETURN_ERROR(NULL);
389 dupkey = strdup(key);
390 if (dupkey == NULL) {
391 complain(&die, "Couldn't duplicate enum key");
392 CLEANUP_AND_RETURN_ERROR(NULL);
395 value = calloc(1, sizeof(struct value));
397 complain(&die, "Couldn't alloc enum value");
398 CLEANUP_AND_RETURN_ERROR(NULL);
401 value_init_detached(value, NULL, type_get_simple(result->type),
404 if (!get_die_numeric(&enum_value, &die, DW_AT_const_value)) {
405 complain(&die, "Couldn't get enum value");
406 CLEANUP_AND_RETURN_ERROR(NULL);
409 value_set_word(value, (long)enum_value);
411 if (lens_enum_add(lens, dupkey, 1, value, 1)) {
412 complain(&die, "Couldn't add enum element");
413 CLEANUP_AND_RETURN_ERROR(NULL);
421 #undef CLEANUP_AND_RETURN_ERROR
424 // returns a newly-allocated art_type_info*, or NULL on error
425 static struct arg_type_info *get_array(Dwarf_Die *parent,
426 struct protolib *plib,
427 struct dict *type_dieoffset_hash)
430 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
431 if (length != NULL) { \
432 expr_destroy(length); \
435 if (array_type != NULL && newly_allocated_array_type) { \
436 type_destroy(array_type); \
439 if (result != NULL) { \
440 type_destroy(result); \
443 dict_erase (type_dieoffset_hash, &die_offset, \
445 dict_insert(type_dieoffset_hash, &die_offset, \
446 &(struct arg_type_info*){ \
447 type_get_simple(ARGTYPE_VOID)}); \
452 struct arg_type_info *result = NULL;
453 struct expr_node *length = NULL;
454 struct arg_type_info *array_type = NULL;
455 int newly_allocated_array_type = 0;
457 Dwarf_Off die_offset = dwarf_dieoffset(parent);
459 result = calloc(1, sizeof(struct arg_type_info));
460 if (result == NULL) {
461 complain(parent, "alloc error");
462 CLEANUP_AND_RETURN_ERROR(NULL);
466 if (!get_type_die(&type_die, parent)) {
467 complain(parent, "Array has unknown type");
468 CLEANUP_AND_RETURN_ERROR(NULL);
471 if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
472 complain(parent, "Couldn't insert into cache dict");
473 CLEANUP_AND_RETURN_ERROR(NULL);
475 array_type = get_type(&newly_allocated_array_type,
476 &type_die, plib, type_dieoffset_hash);
477 if (array_type == NULL) {
478 complain(parent, "Couldn't figure out array's type");
479 CLEANUP_AND_RETURN_ERROR(NULL);
483 if (dwarf_child(parent, &subrange) != 0) {
485 "Array must have a DW_TAG_subrange_type child, "
487 CLEANUP_AND_RETURN_ERROR(NULL);
490 Dwarf_Die next_subrange;
491 if (dwarf_siblingof(&subrange, &next_subrange) <= 0) {
493 "Array must have exactly one DW_TAG_subrange_type "
495 CLEANUP_AND_RETURN_ERROR(NULL);
498 if (dwarf_hasattr(&subrange, DW_AT_lower_bound)) {
499 uint64_t lower_bound;
500 if (!get_die_numeric(&lower_bound, &subrange,
501 DW_AT_lower_bound)) {
502 complain(parent, "Couldn't read lower bound");
503 CLEANUP_AND_RETURN_ERROR(NULL);
506 if (lower_bound != 0) {
508 "Array subrange has a nonzero lower bound. "
509 "Don't know what to do");
510 CLEANUP_AND_RETURN_ERROR(NULL);
515 if (!dwarf_hasattr(&subrange, DW_AT_upper_bound)) {
516 // no upper bound is defined. This is probably a variable-width
517 // array, and I don't know how long it is. Let's say 0 to be
523 if (!get_die_numeric(&N, &subrange, DW_AT_upper_bound)) {
524 complain(parent, "Couldn't read upper bound");
525 CLEANUP_AND_RETURN_ERROR(NULL);
530 // I'm not checking the subrange type. It should be some sort of
531 // integer, and I don't know what it would mean for it to be something
533 length = calloc(1, sizeof(struct expr_node));
534 if (length == NULL) {
535 complain(&subrange, "Couldn't alloc length expr");
536 CLEANUP_AND_RETURN_ERROR(NULL);
538 expr_init_const_word(length, N, type_get_simple(ARGTYPE_INT), 0);
540 type_init_array(result, array_type, newly_allocated_array_type,
544 #undef CLEANUP_AND_RETURN_ERROR
547 // returns a newly-allocated art_type_info*, or NULL on error
548 static struct arg_type_info *get_structure(Dwarf_Die *parent,
549 struct protolib *plib,
550 struct dict *type_dieoffset_hash)
553 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
554 if (member_type != NULL && newly_allocated_member_type) { \
555 type_destroy(member_type); \
558 if (result != NULL) { \
559 type_destroy(result); \
562 dict_erase (type_dieoffset_hash, &die_offset, \
564 dict_insert(type_dieoffset_hash, &die_offset, \
565 &(struct arg_type_info*){ \
566 type_get_simple(ARGTYPE_VOID)}); \
571 struct arg_type_info *result = NULL;
572 struct arg_type_info *member_type = NULL;
573 int newly_allocated_member_type = 0;
575 Dwarf_Off die_offset = dwarf_dieoffset(parent);
577 result = calloc(1, sizeof(struct arg_type_info));
578 if (result == NULL) {
579 complain(parent, "alloc error");
580 CLEANUP_AND_RETURN_ERROR(NULL);
582 type_init_struct(result);
583 if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
584 complain(parent, "Couldn't insert into cache dict");
585 CLEANUP_AND_RETURN_ERROR(NULL);
589 if (dwarf_child(parent, &die) != 0) {
590 // no elements; we're done
596 newly_allocated_member_type = 0;
598 complain(&die, "member: 0x%02x", dwarf_tag(&die));
600 if (dwarf_tag(&die) != DW_TAG_member) {
601 complain(&die, "Structure can have ONLY DW_TAG_member");
602 CLEANUP_AND_RETURN_ERROR(NULL);
606 if (!get_type_die(&type_die, &die)) {
607 complain(&die, "Couldn't get type of element");
608 CLEANUP_AND_RETURN_ERROR(NULL);
611 member_type = get_type(&newly_allocated_member_type,
612 &type_die, plib, type_dieoffset_hash);
613 if (member_type == NULL) {
614 complain(&die, "Couldn't parse type from DWARF data");
615 CLEANUP_AND_RETURN_ERROR(NULL);
617 if (type_struct_add(result, member_type,
618 newly_allocated_member_type) != 0) {
619 complain(&die, "Couldn't add type to struct");
620 CLEANUP_AND_RETURN_ERROR(NULL);
627 #undef CLEANUP_AND_RETURN_ERROR
630 // Reads the type in the die and returns the corresponding arg_type_info*. If
631 // this was newly allocated on the heap, *newly_allocated_info = true. If an
632 // error occurred, returns NULL
633 static struct arg_type_info *get_type(int *newly_allocated_result,
635 struct protolib *plib,
636 struct dict *type_dieoffset_hash)
639 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
640 if (pointee != NULL && newly_allocated_pointee) { \
641 type_destroy(pointee); \
644 if (result != NULL && *newly_allocated_result) { \
645 type_destroy(result); \
648 dict_erase (type_dieoffset_hash, &die_offset, \
650 dict_insert(type_dieoffset_hash, &die_offset, \
651 &(struct arg_type_info*){ \
652 type_get_simple(ARGTYPE_VOID)}); \
656 #define DICT_INSERT_AND_CHECK(type_dieoffset_hash, die_offset, result) \
658 if (dict_insert(type_dieoffset_hash, \
659 die_offset, result) != 0) { \
661 "Couldn't insert into cache dict"); \
662 CLEANUP_AND_RETURN_ERROR(NULL); \
666 struct arg_type_info *result = NULL;
667 struct arg_type_info *pointee = NULL;
668 int newly_allocated_pointee = 0;
670 Dwarf_Off die_offset = dwarf_dieoffset(type_die);
673 // by default, we say we allocated nothing. I set this to true later,
674 // when I allocate memory
675 *newly_allocated_result = 0;
677 struct arg_type_info **found_type = dict_find(type_dieoffset_hash,
679 if (found_type != NULL) {
680 complain(type_die, "Read pre-computed type");
684 const char *type_name = dwarf_diename(type_die);
685 if (type_name != NULL) {
687 struct named_type *already_defined_type =
688 protolib_lookup_type(plib, type_name, true);
690 if (already_defined_type != NULL) {
692 "Type '%s' defined in a .conf file. "
693 "Using that instead of DWARF",
695 return already_defined_type->info;
701 switch (dwarf_tag(type_die)) {
702 case DW_TAG_base_type:
703 complain(type_die, "Storing base type");
704 result = type_get_simple(get_base_type(type_die));
705 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
708 case DW_TAG_subroutine_type:
709 case DW_TAG_inlined_subroutine:
710 // function pointers are stored as void*. If ltrace tries to
711 // dereference these, it'll get a segfault
712 complain(type_die, "Storing subroutine type");
713 result = type_get_simple(ARGTYPE_VOID);
714 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
717 case DW_TAG_pointer_type:
718 if (!get_type_die(&next_die, type_die)) {
719 // the pointed-to type isn't defined, so I report a
721 complain(type_die, "Storing void-pointer type");
722 result = type_get_voidptr();
723 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
727 complain(type_die, "Storing pointer type");
729 *newly_allocated_result = 1;
730 result = calloc(1, sizeof(struct arg_type_info));
731 if (result == NULL) {
732 complain(type_die, "alloc error");
733 CLEANUP_AND_RETURN_ERROR(NULL);
735 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
736 pointee = get_type(&newly_allocated_pointee,
737 &next_die, plib, type_dieoffset_hash);
739 CLEANUP_AND_RETURN_ERROR(NULL);
741 type_init_pointer(result, pointee, newly_allocated_pointee);
744 case DW_TAG_structure_type:
745 complain(type_die, "Storing struct type");
746 *newly_allocated_result = 1;
748 result = get_structure(type_die, plib, type_dieoffset_hash);
750 CLEANUP_AND_RETURN_ERROR(NULL);
755 case DW_TAG_const_type:
756 case DW_TAG_volatile_type:
757 // Various tags are simply pass-through, so I just keep going
758 if (get_type_die(&next_die, type_die)) {
759 complain(type_die, "Storing const/typedef type");
761 result = get_type(newly_allocated_result, &next_die,
762 plib, type_dieoffset_hash);
764 CLEANUP_AND_RETURN_ERROR(NULL);
766 // no type. Use 'void'. Normally I'd think this is
767 // bogus, but stdio typedefs something to void
768 result = type_get_simple(ARGTYPE_VOID);
769 complain(type_die, "Storing void type");
771 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
774 case DW_TAG_enumeration_type:
775 // We have an enumeration. This has a base type, but has a
776 // particular lens to handle the enum
777 *newly_allocated_result = 1;
779 complain(type_die, "Storing enum int");
780 result = get_enum(type_die, type_dieoffset_hash);
782 CLEANUP_AND_RETURN_ERROR(NULL);
785 case DW_TAG_array_type:
786 *newly_allocated_result = 1;
788 complain(type_die, "Storing array");
789 result = get_array(type_die, plib, type_dieoffset_hash);
791 CLEANUP_AND_RETURN_ERROR(NULL);
794 case DW_TAG_union_type:
795 result = type_get_simple(ARGTYPE_VOID);
796 complain(type_die, "Storing union-as-void type");
797 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
801 complain(type_die, "Unknown type tag 0x%x. Returning void",
802 dwarf_tag(type_die));
803 result = type_get_simple(ARGTYPE_VOID);
804 DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
808 #undef DICT_INSERT_AND_CHECK
809 #undef CLEANUP_AND_RETURN_ERROR
812 // fills in *proto with a prototype. Returns true on success
813 static bool get_prototype(struct prototype *result,
814 Dwarf_Die *subroutine, struct protolib *plib,
815 struct dict *type_dieoffset_hash)
818 #define CLEANUP_AND_RETURN_ERROR(ret) do { \
819 if (argument_type != NULL && newly_allocated_argument_type) { \
820 type_destroy(argument_type); \
821 free(argument_type); \
823 prototype_destroy(result); \
828 struct arg_type_info *argument_type = NULL;
829 int newly_allocated_argument_type = 0;
831 prototype_init(result);
833 // First, look at the return type. This is stored in a DW_AT_type tag in
834 // the subroutine DIE. If there is no such tag, this function returns
836 Dwarf_Die return_type_die;
837 if (!get_type_die(&return_type_die, subroutine)) {
838 result->return_info = type_get_simple(ARGTYPE_VOID);
839 result->own_return_info = 0;
841 int newly_allocated_return_type;
842 result->return_info = get_type(&newly_allocated_return_type,
843 &return_type_die, plib,
844 type_dieoffset_hash);
845 if (result->return_info == NULL) {
846 complain(subroutine, "Couldn't get return type");
847 CLEANUP_AND_RETURN_ERROR(false);
849 result->own_return_info = newly_allocated_return_type;
853 // Now look at the arguments
855 if (dwarf_child(subroutine, &arg_die) != 0) {
856 // no args. We're done
861 if (dwarf_tag(&arg_die) == DW_TAG_formal_parameter) {
863 complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die));
865 argument_type = NULL;
866 newly_allocated_argument_type = false;
869 if (!get_type_die(&type_die, &arg_die)) {
870 complain(&arg_die, "Couldn't get the argument "
872 CLEANUP_AND_RETURN_ERROR(false);
876 argument_type = get_type(&newly_allocated_argument_type,
878 type_dieoffset_hash);
879 if (argument_type==NULL) {
880 complain(&arg_die, "Couldn't parse arg "
881 "type from DWARF data");
882 CLEANUP_AND_RETURN_ERROR(false);
886 param_init_type(¶m, argument_type,
887 newly_allocated_argument_type);
888 if (prototype_push_param(result, ¶m) <0) {
889 complain(&arg_die, "couldn't add argument to "
891 CLEANUP_AND_RETURN_ERROR(false);
894 #ifdef DUMP_PROTOTYPES
895 fprintf(stderr, "Adding argument:\n");
896 dump_ltrace_tree(argument_type);
900 NEXT_SIBLING(&arg_die);
904 #undef CLEANUP_AND_RETURN_ERROR
907 static bool import_subprogram(struct protolib *plib, struct library *lib,
908 struct dict *type_dieoffset_hash,
911 // I use the linkage function name if there is one, otherwise the
913 const char *function_name = NULL;
914 Dwarf_Attribute attr;
915 if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL)
916 function_name = dwarf_formstring(&attr);
917 if (function_name == NULL)
918 function_name = dwarf_diename(die);
919 if (function_name == NULL) {
920 complain(die, "Function has no name. Not importing");
924 if (!filter_matches_symbol(options.plt_filter, function_name, lib) &&
925 !filter_matches_symbol(options.static_filter, function_name, lib) &&
926 !filter_matches_symbol(options.export_filter, function_name, lib)) {
927 complain(die, "Prototype not requested by any filter");
931 complain(die, "subroutine_type: 0x%02x; function '%s'",
932 dwarf_tag(die), function_name);
934 struct prototype *proto_already_there =
935 protolib_lookup_prototype(plib, function_name, false);
937 if (proto_already_there != NULL) {
938 complain(die, "Prototype already exists. Skipping");
942 struct prototype proto;
943 if (!get_prototype(&proto, die, plib, type_dieoffset_hash)) {
944 complain(die, "couldn't get prototype");
948 const char *function_name_dup = strdup(function_name);
949 if (function_name_dup == NULL) {
950 complain(die, "couldn't strdup");
951 prototype_destroy(&proto);
954 protolib_add_prototype(plib, function_name_dup, 1, &proto);
958 static bool process_die_compileunit(struct protolib *plib, struct library *lib,
959 struct dict *type_dieoffset_hash,
962 complain(parent, "Processing compile unit");
964 if (dwarf_child(parent, &die) != 0) {
965 // no child nodes, so nothing to do
970 if (dwarf_tag(&die) == DW_TAG_subprogram)
971 if (!import_subprogram(plib, lib, type_dieoffset_hash,
973 complain(&die, "Error importing subprogram. "
982 static void import(struct protolib *plib, struct library *lib,
983 Dwfl_Module *dwfl_module)
985 // A map from DIE addresses (Dwarf_Off) to type structures (struct
986 // arg_type_info*). This is created and filled in at the start of each
987 // import, and deleted when the import is complete
988 struct dict type_dieoffset_hash;
990 dict_init(&type_dieoffset_hash, sizeof(Dwarf_Off),
991 sizeof(struct arg_type_info*),
992 dwarf_die_hash, dwarf_die_eq, NULL);
995 Dwarf_Die *die = NULL;
996 while ((die = dwfl_module_nextcu(dwfl_module, die, &bias)) != NULL) {
997 if (dwarf_tag(die) == DW_TAG_compile_unit)
998 process_die_compileunit(plib, lib,
999 &type_dieoffset_hash, die);
1001 complain(die, "A DW_TAG_compile_unit die expected. "
1002 "Skipping this one");
1005 dict_destroy(&type_dieoffset_hash, NULL, NULL, NULL);
1008 bool import_DWARF_prototypes(struct library *lib)
1010 struct protolib *plib = lib->protolib;
1012 debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
1016 const char *soname_dup = strdup(lib->soname);
1017 if (soname_dup == NULL) {
1018 fprintf(stderr, "couldn't strdup");
1022 plib = protolib_cache_default(&g_protocache, soname_dup, 1);
1024 fprintf(stderr, "Error loading protolib %s: %s.\n",
1025 lib->soname, strerror(errno));
1029 import(plib, lib, lib->dwfl_module);
1030 lib->protolib = plib;