1 /* Most of this is Copyright Dima Kogan <dima@secretsauce.net>
3 * Pieces of this were taken from dwarf_prototypes.c in the dwarves project.
4 * Those are Copyright (C) 2008 Arnaldo Carvalho de Melo <acme@redhat.com>.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of version 2 of the GNU General Public License as published by the
8 * Free Software Foundation.
12 #include <elfutils/libdwfl.h>
19 #include "prototype.h"
24 #include "lens_enum.h"
32 //#define DUMP_PROTOTYPES
35 #define complain( die, format, ... ) \
36 fprintf(stderr, "%s() die '%s' @ 0x%lx: " format "\n", \
37 __func__, dwarf_diename(die), dwarf_dieoffset(die), \
40 #define complain( die, format, ... )
43 // A map from DIE addresses (Dwarf_Off) to type structures (struct
44 // arg_type_info*). This is created and filled in at the start of each import,
45 // and deleted when the import is complete
46 static struct dict type_hash;
49 static bool get_type(struct arg_type_info** info, Dwarf_Die* type_die);
53 static bool _dump_dwarf_tree(Dwarf_Die* die, int indent)
56 fprintf(stderr, "%*sprocessing unit: 0x%02x/'%s'\n", indent*4, "",
57 dwarf_tag(die), dwarf_diename(die));
60 if (dwarf_child(die, &child) == 0) {
61 if (!_dump_dwarf_tree(&child, indent+1))
65 int res = dwarf_siblingof(die, die);
66 if (res == 0 ) continue; // sibling exists
67 if (res < 0 ) return false; // error
68 break; // no sibling exists
74 static bool dump_dwarf_tree(Dwarf_Die* die)
76 return _dump_dwarf_tree( die, 0 );
80 #ifdef DUMP_PROTOTYPES
81 static bool _dump_ltrace_tree(const struct arg_type_info* info, int indent)
84 fprintf(stderr, "%*s%p ...\n", indent*4, "", (void*)info);
89 fprintf(stderr, "%*s%p NULL\n", indent*4, "", (void*)info);
95 fprintf(stderr, "%*s%p void\n", indent*4, "", (void*)info);
107 fprintf(stderr, "%*s%p base\n", indent*4, "", (void*)info);
111 fprintf(stderr, "%*s%p array. elements not printed\n", indent*4, "",
115 case ARGTYPE_POINTER:
116 fprintf(stderr, "%*s%p pointer to...\n", indent*4, "", (void*)info);
117 _dump_ltrace_tree( info->u.ptr_info.info, indent+1 );
121 fprintf(stderr, "%*s%p struct...\n", indent*4, "", (void*)info);
124 struct arg_type_info *info;
126 }* elements = (struct struct_field*)info->u.entries.data;
128 for(i=0; i<info->u.entries.size; i++)
129 _dump_ltrace_tree( elements[i].info, indent+1 );
133 fprintf(stderr, "%*s%p unknown type\n", indent*4, "", (void*)info);
140 static bool dump_ltrace_tree(const struct arg_type_info* info)
142 return _dump_ltrace_tree( info, 0 );
148 static uint64_t attr_numeric(Dwarf_Die *die, uint32_t name)
150 Dwarf_Attribute attr;
153 if (dwarf_attr(die, name, &attr) == NULL)
156 form = dwarf_whatform(&attr);
161 if (dwarf_formaddr(&attr, &addr) == 0)
170 case DW_FORM_udata: {
172 if (dwarf_formudata(&attr, &value) == 0)
177 case DW_FORM_flag_present: {
179 if (dwarf_formflag(&attr, &value) == 0)
184 complain(die, "DW_AT_<0x%x>=0x%x", name, form);
191 static enum arg_type get_base_type(Dwarf_Die* die)
193 int encoding = attr_numeric(die, DW_AT_encoding);
195 if (encoding == DW_ATE_void )
198 if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char )
201 if (encoding == DW_ATE_signed ||
202 encoding == DW_ATE_unsigned ||
203 encoding == DW_ATE_boolean) {
204 bool is_signed = (encoding == DW_ATE_signed);
205 switch (attr_numeric(die, DW_AT_byte_size)) {
210 return is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT;
213 return is_signed ? ARGTYPE_INT : ARGTYPE_UINT;
216 return is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG;
224 if (encoding == DW_ATE_float) {
225 switch (attr_numeric(die, DW_AT_byte_size)) {
227 return ARGTYPE_FLOAT;
230 return ARGTYPE_DOUBLE;
233 // things like long doubles. ltrace has no support yet, so I just
240 if (encoding == DW_ATE_complex_float) {
241 switch (attr_numeric(die, DW_AT_byte_size)) {
242 case 2*sizeof(float):
243 return ARGTYPE_FLOAT;
245 case 2*sizeof(double):
246 return ARGTYPE_DOUBLE;
249 // things like long doubles. ltrace has no support yet, so I just
256 // Unknown encoding. I just say void
257 complain(die, "Unknown base type. Returning 'void'");
261 static bool get_type_die(Dwarf_Die* type_die, Dwarf_Die* die)
263 Dwarf_Attribute attr;
265 dwarf_attr(die, DW_AT_type, &attr) != NULL &&
266 dwarf_formref_die(&attr, type_die) != NULL;
269 static size_t dwarf_die_hash(const void* x)
271 return *(const Dwarf_Off*)x;
273 static int dwarf_die_eq(const void* a, const void* b)
275 return *(const Dwarf_Off*)a == *(const Dwarf_Off*)b;
278 static bool get_enum(struct arg_type_info* enum_info, Dwarf_Die* parent)
280 enum_info->type = ARGTYPE_INT;
282 struct enum_lens *lens = calloc(1, sizeof(struct enum_lens));
284 complain(parent, "alloc error");
287 lens_init_enum(lens);
288 enum_info->lens = &lens->super;
291 if (dwarf_child(parent, &die) != 0) {
292 // empty enum. we're done
297 complain(&die, "enum element: 0x%02x/'%s'", dwarf_tag(&die),
298 dwarf_diename(&die));
300 if (dwarf_tag(&die) != DW_TAG_enumerator) {
301 complain(&die, "Enums can have ONLY DW_TAG_enumerator elements");
305 if (!dwarf_hasattr(&die, DW_AT_const_value)) {
306 complain(&die, "Enums MUST have DW_AT_const_value values");
310 const char* key = dwarf_diename(&die);
312 complain(&die, "Enums must have a DW_AT_name key");
315 const char* dupkey = strdup(key);
316 if (dupkey == NULL) {
317 complain(&die, "Couldn't duplicate enum key");
321 struct value* value = calloc( 1, sizeof(struct value));
323 complain(&die, "Couldn't alloc enum value");
327 value_init_detached(value, NULL, type_get_simple( ARGTYPE_INT ), 0);
328 value_set_word(value, attr_numeric(&die, DW_AT_const_value));
330 if (lens_enum_add( lens, dupkey, 0, value, 0 )) {
331 complain(&die, "Couldn't add enum element");
335 int res = dwarf_siblingof(&die, &die);
336 if (res == 0) continue; /* sibling exists */
337 if (res < 0) return false; /* error */
338 break; /* no sibling exists */
344 static bool get_array(struct arg_type_info* array_info, Dwarf_Die* parent)
347 if (!get_type_die( &type_die, parent )) {
348 complain( parent, "Array has unknown type" );
352 struct arg_type_info* info;
353 if (!get_type( &info, &type_die )) {
354 complain( parent, "Couldn't figure out array's type" );
359 if (dwarf_child(parent, &subrange) != 0) {
361 "Array must have a DW_TAG_subrange_type child, but has none");
365 Dwarf_Die next_subrange;
366 if (dwarf_siblingof(&subrange, &next_subrange) <= 0) {
368 "Array must have exactly one DW_TAG_subrange_type child");
372 if (dwarf_hasattr(&subrange, DW_AT_lower_bound)) {
373 if (attr_numeric(&subrange, DW_AT_lower_bound) != 0) {
375 "Array subrange has a nonzero lower bound. Don't know what to do");
381 if (!dwarf_hasattr(&subrange, DW_AT_upper_bound)) {
382 // no upper bound is defined. This is probably a variable-width array,
383 // and I don't know how long it is. Let's say 0 to be safe
387 N = attr_numeric(&subrange, DW_AT_upper_bound)+1;
389 // I'm not checking the subrange type. It should be some sort of integer,
390 // and I don't know what it would mean for it to be something else
392 struct value* value = calloc( 1, sizeof(struct value));
394 complain(&subrange, "Couldn't alloc length value");
397 value_init_detached(value, NULL, type_get_simple( ARGTYPE_INT ), 0);
398 value_set_word(value, N );
400 struct expr_node* length = calloc( 1, sizeof(struct expr_node));
401 if (length == NULL) {
402 complain(&subrange, "Couldn't alloc length expr");
405 expr_init_const(length, value);
407 type_init_array(array_info, info, 0, length, 0 );
412 static bool get_structure(struct arg_type_info* struct_info, Dwarf_Die* parent)
414 type_init_struct(struct_info);
417 if (dwarf_child(parent, &die) != 0) {
418 // no elements; we're done
423 complain(&die, "member: 0x%02x", dwarf_tag(&die));
425 if (dwarf_tag(&die) != DW_TAG_member) {
426 complain(&die, "Structure can have ONLY DW_TAG_member");
431 if (!get_type_die( &type_die, &die )) {
432 complain( &die, "Couldn't get type of element");
436 struct arg_type_info* member_info = NULL;
437 if (!get_type( &member_info, &type_die )) {
438 complain(&die, "Couldn't parse type from DWARF data");
441 type_struct_add( struct_info, member_info, 0 );
443 int res = dwarf_siblingof(&die, &die);
444 if (res == 0) continue; /* sibling exists */
445 if (res < 0) return false; /* error */
446 break; /* no sibling exists */
452 // Reads the type in the die into the given structure
453 // Returns true on sucess
454 static bool get_type(struct arg_type_info** info, Dwarf_Die* type_die)
456 Dwarf_Off die_offset = dwarf_dieoffset(type_die);
457 struct arg_type_info** found_type = dict_find(&type_hash, &die_offset );
458 if (found_type != NULL) {
460 complain(type_die, "Read pre-computed type: %p", *info);
466 switch (dwarf_tag(type_die)) {
467 case DW_TAG_base_type:
468 *info = type_get_simple( get_base_type( type_die ));
469 complain(type_die, "Storing base type: %p", *info);
470 dict_insert( &type_hash, &die_offset, info );
473 case DW_TAG_subroutine_type:
474 case DW_TAG_inlined_subroutine:
475 // function pointers are stored as void*. If ltrace tries to dereference
476 // these, it'll get a segfault
477 *info = type_get_simple( ARGTYPE_VOID );
478 complain(type_die, "Storing subroutine type: %p", *info);
479 dict_insert( &type_hash, &die_offset, info );
482 case DW_TAG_pointer_type:
484 if (!get_type_die(&next_die, type_die )) {
485 // the pointed-to type isn't defined, so I report a void*
486 *info = type_get_simple( ARGTYPE_VOID );
487 complain(type_die, "Storing void-pointer type: %p", *info);
488 dict_insert( &type_hash, &die_offset, info );
492 *info = calloc( 1, sizeof(struct arg_type_info));
494 complain(type_die, "alloc error");
497 type_init_pointer(*info, NULL, 0);
499 complain(type_die, "Storing pointer type: %p", *info);
500 dict_insert( &type_hash, &die_offset, info );
501 return get_type( &(*info)->u.ptr_info.info, &next_die );
503 case DW_TAG_structure_type:
504 *info = calloc( 1, sizeof(struct arg_type_info));
506 complain(type_die, "alloc error");
510 complain(type_die, "Storing struct type: %p", *info);
511 dict_insert( &type_hash, &die_offset, info );
512 return get_structure( *info, type_die );
515 case DW_TAG_typedef: ;
516 case DW_TAG_const_type: ;
517 case DW_TAG_volatile_type: ;
518 // Various tags are simply pass-through, so I just keep going
520 if (get_type_die(&next_die, type_die )) {
521 complain(type_die, "Storing const/typedef type: %p", *info);
522 res = get_type( info, &next_die );
524 // no type. Use 'void'. Normally I'd think this is bogus, but stdio
525 // typedefs something to void
526 *info = type_get_simple( ARGTYPE_VOID );
527 complain(type_die, "Storing void type: %p", *info);
530 dict_insert( &type_hash, &die_offset, info );
533 case DW_TAG_enumeration_type:
534 // We have an enumeration. This has type "int", but has a particular
535 // lens to handle the enum
536 *info = calloc( 1, sizeof(struct arg_type_info));
538 complain(type_die, "alloc error");
542 complain(type_die, "Storing enum int: %p", *info);
543 dict_insert( &type_hash, &die_offset, info );
544 return get_enum( *info, type_die );
546 case DW_TAG_array_type:
547 *info = calloc( 1, sizeof(struct arg_type_info));
549 complain(type_die, "alloc error");
553 complain(type_die, "Storing array: %p", *info);
554 dict_insert( &type_hash, &die_offset, info );
555 return get_array( *info, type_die );
557 case DW_TAG_union_type:
558 *info = type_get_simple( ARGTYPE_VOID );
559 complain(type_die, "Storing union-as-void type: %p", *info);
563 complain(type_die, "Unknown type tag 0x%x", dwarf_tag(type_die));
570 static bool get_prototype(struct prototype* proto, Dwarf_Die* subroutine)
572 // First, look at the return type. This is stored in a DW_AT_type tag in the
573 // subroutine DIE. If there is no such tag, this function returns void
574 Dwarf_Die return_type_die;
575 if (!get_type_die(&return_type_die, subroutine )) {
576 proto->return_info = type_get_simple( ARGTYPE_VOID );
577 proto->own_return_info = 0;
579 proto->return_info = calloc( 1, sizeof( struct arg_type_info ));
580 if (proto->return_info == NULL) {
581 complain(subroutine, "Couldn't alloc return type");
584 proto->own_return_info = 0;
586 if (!get_type( &proto->return_info, &return_type_die )) {
587 complain(subroutine, "Couldn't get return type");
593 // Now look at the arguments
595 if (dwarf_child(subroutine, &arg_die) != 0) {
596 // no args. We're done
601 if (dwarf_tag(&arg_die) != DW_TAG_formal_parameter )
602 goto next_prototype_argument;
604 complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die));
607 if (!get_type_die(&type_die, &arg_die )) {
608 complain(&arg_die, "Couldn't get the argument type die");
612 struct arg_type_info* arg_type_info = NULL;
613 if (!get_type( &arg_type_info, &type_die )) {
614 complain(&arg_die, "Couldn't parse arg type from DWARF data");
619 param_init_type(¶m, arg_type_info, 0);
620 if (prototype_push_param(proto, ¶m) <0) {
621 complain(&arg_die, "couldn't add argument to the prototype");
625 #ifdef DUMP_PROTOTYPES
626 fprintf(stderr, "Adding argument:\n");
627 dump_ltrace_tree(arg_type_info);
630 next_prototype_argument: ;
631 int res = dwarf_siblingof(&arg_die, &arg_die);
632 if (res == 0) continue; /* sibling exists */
633 if (res < 0) return false; /* error */
634 break; /* no sibling exists */
640 static bool process_die_compileunit(struct protolib* plib, struct library* lib,
644 if (dwarf_child(parent, &die) != 0) {
645 // no child nodes, so nothing to do
650 if (dwarf_tag(&die) == DW_TAG_subprogram) {
651 const char* function_name = dwarf_diename(&die);
653 complain(&die, "subroutine_type: 0x%02x; function '%s'",
654 dwarf_tag(&die), function_name);
656 struct prototype* proto =
657 protolib_lookup_prototype(plib, function_name, true );
660 complain(&die, "Prototype already exists. Skipping");
664 if (!filter_matches_symbol(options.plt_filter, function_name, lib) &&
665 !filter_matches_symbol(options.static_filter, function_name, lib) &&
666 !filter_matches_symbol(options.export_filter, function_name, lib)) {
667 complain(&die, "Prototype not requested by any filter");
671 proto = malloc(sizeof(struct prototype));
673 complain(&die, "couldn't alloc prototype");
676 prototype_init( proto );
678 if (!get_prototype(proto, &die )) {
679 complain(&die, "couldn't get prototype");
683 protolib_add_prototype(plib, function_name, 0, proto);
687 int res = dwarf_siblingof(&die, &die);
688 if (res == 0) continue; /* sibling exists */
689 if (res < 0) return false; /* error */
690 break; /* no sibling exists */
696 static bool import(struct protolib* plib, struct library* lib, Dwfl* dwfl)
698 dict_init(&type_hash, sizeof(Dwarf_Off), sizeof(struct arg_type_info*),
699 dwarf_die_hash, dwarf_die_eq, NULL );
702 Dwarf_Die* die = NULL;
703 while ((die = dwfl_nextcu(dwfl, die, &bias)) != NULL) {
704 if (dwarf_tag(die) == DW_TAG_compile_unit) {
705 if (!process_die_compileunit(plib, lib, die)) {
706 complain(die, "Error reading compile unit");
711 complain(die, "DW_TAG_compile_unit expected");
717 dict_destroy( &type_hash, NULL, NULL, NULL );
721 bool import_DWARF_prototypes(struct protolib* plib, struct library* lib,
725 plib = protolib_cache_default(&g_protocache, lib->soname, 0);
727 fprintf(stderr, "Error loading protolib %s: %s.\n",
728 lib->soname, strerror(errno));
732 return import(plib, lib, dwfl);
736 - I handle static functions now. Should I? Those do not have DW_AT_external==1
738 - should process existing prototypes to make sure they match
740 - what do function pointers look like? I'm doing void*
744 - all my *allocs leak
746 - protolib_lookup_prototype should look for imports?