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 getType( struct arg_type_info** info, Dwarf_Die* type_die);
53 static bool _dump_dwarf_tree(Dwarf_Die* die, int indent)
57 fprintf(stderr, "%*sprocessing unit: 0x%02x/'%s'\n", indent*4, "",
58 dwarf_tag(die), dwarf_diename(die) );
61 if (dwarf_child(die, &child) == 0)
63 if( !_dump_dwarf_tree(&child, indent+1) )
67 int res = dwarf_siblingof(die, die);
68 if( res == 0 ) continue; // sibling exists
69 if( res < 0 ) return false; // error
70 break; // no sibling exists
76 static bool dump_dwarf_tree(Dwarf_Die* die)
78 return _dump_dwarf_tree( die, 0 );
82 #ifdef DUMP_PROTOTYPES
83 static bool _dump_ltrace_tree( const struct arg_type_info* info, int indent )
87 fprintf(stderr, "%*s%p ...\n", indent*4, "", (void*)info);
93 fprintf(stderr, "%*s%p NULL\n", indent*4, "", (void*)info);
100 fprintf(stderr, "%*s%p void\n", indent*4, "", (void*)info);
112 fprintf(stderr, "%*s%p base\n", indent*4, "", (void*)info);
116 fprintf(stderr, "%*s%p array. elements not printed\n", indent*4, "", (void*)info);
119 case ARGTYPE_POINTER:
120 fprintf(stderr, "%*s%p pointer to...\n", indent*4, "", (void*)info);
121 _dump_ltrace_tree( info->u.ptr_info.info, indent+1 );
125 fprintf(stderr, "%*s%p struct...\n", indent*4, "", (void*)info);
128 struct arg_type_info *info;
130 }* elements = (struct struct_field*)info->u.entries.data;
132 for(i=0; i<info->u.entries.size; i++)
133 _dump_ltrace_tree( elements[i].info, indent+1 );
137 fprintf(stderr, "%*s%p unknown type\n", indent*4, "", (void*)info);
144 static bool dump_ltrace_tree( const struct arg_type_info* info )
146 return _dump_ltrace_tree( info, 0 );
152 static uint64_t attr_numeric(Dwarf_Die *die, uint32_t name)
154 Dwarf_Attribute attr;
157 if (dwarf_attr(die, name, &attr) == NULL)
160 form = dwarf_whatform(&attr);
165 if (dwarf_formaddr(&attr, &addr) == 0)
174 case DW_FORM_udata: {
176 if (dwarf_formudata(&attr, &value) == 0)
181 case DW_FORM_flag_present: {
183 if (dwarf_formflag(&attr, &value) == 0)
188 complain(die, "DW_AT_<0x%x>=0x%x", name, form);
195 static enum arg_type getBaseType( Dwarf_Die* die )
197 int encoding = attr_numeric(die, DW_AT_encoding);
199 if( encoding == DW_ATE_void )
202 if( encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char )
205 if( encoding == DW_ATE_signed ||
206 encoding == DW_ATE_unsigned ||
207 encoding == DW_ATE_boolean )
209 bool is_signed = (encoding == DW_ATE_signed);
210 switch( attr_numeric(die, DW_AT_byte_size) )
216 return is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT;
219 return is_signed ? ARGTYPE_INT : ARGTYPE_UINT;
222 return is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG;
230 if( encoding == DW_ATE_float )
232 switch( attr_numeric(die, DW_AT_byte_size) )
235 return ARGTYPE_FLOAT;
238 return ARGTYPE_DOUBLE;
241 // things like long doubles. ltrace has no support yet, so I just say "void"
246 // Unknown encoding. I just say void
250 static bool getTypeDie( Dwarf_Die* type_die, Dwarf_Die* die )
252 Dwarf_Attribute attr;
254 dwarf_attr(die, DW_AT_type, &attr) != NULL &&
255 dwarf_formref_die(&attr, type_die) != NULL;
258 static size_t dwarf_die_hash(const void* x)
260 return *(const Dwarf_Off*)x;
262 static int dwarf_die_eq(const void* a, const void* b)
264 return *(const Dwarf_Off*)a == *(const Dwarf_Off*)b;
267 static bool getEnum(struct arg_type_info* enum_info, Dwarf_Die* parent)
269 enum_info->type = ARGTYPE_INT;
271 struct enum_lens *lens = calloc(1, sizeof(struct enum_lens));
274 complain(parent, "alloc error");
277 lens_init_enum(lens);
278 enum_info->lens = &lens->super;
281 if( dwarf_child(parent, &die) != 0 )
283 // empty enum. we're done
288 complain(&die, "enum element: 0x%02x/'%s'", dwarf_tag(&die), dwarf_diename(&die) );
290 if( dwarf_tag(&die) != DW_TAG_enumerator )
292 complain(&die, "Enums can have ONLY DW_TAG_enumerator elements");
296 if( !dwarf_hasattr(&die, DW_AT_const_value) )
298 complain(&die, "Enums MUST have DW_AT_const_value values");
302 const char* key = dwarf_diename(&die);
305 complain(&die, "Enums must have a DW_AT_name key");
308 const char* dupkey = strdup(key);
311 complain(&die, "Couldn't duplicate enum key");
315 struct value* value = calloc( 1, sizeof(struct value) );
318 complain(&die, "Couldn't alloc enum value");
322 value_init_detached(value, NULL, type_get_simple( ARGTYPE_INT ), 0);
323 value_set_word(value, attr_numeric(&die, DW_AT_const_value) );
325 if( lens_enum_add( lens, dupkey, 0, value, 0 ) )
327 complain(&die, "Couldn't add enum element");
331 int res = dwarf_siblingof(&die, &die);
332 if( res == 0 ) continue; /* sibling exists */
333 if( res < 0 ) return false; /* error */
334 break; /* no sibling exists */
340 static bool getArray(struct arg_type_info* array_info, Dwarf_Die* parent)
343 if( !getTypeDie( &type_die, parent ) )
345 complain( parent, "Array has unknown type" );
349 struct arg_type_info* info;
350 if( !getType( &info, &type_die ) )
352 complain( parent, "Couldn't figure out array's type" );
357 if( dwarf_child(parent, &subrange) != 0 )
359 complain( parent, "Array must have a DW_TAG_subrange_type child, but has none" );
363 Dwarf_Die next_subrange;
364 if( dwarf_siblingof(&subrange, &next_subrange) <= 0 )
366 complain( parent, "Array must have exactly one DW_TAG_subrange_type child" );
370 if( dwarf_hasattr(&subrange, DW_AT_lower_bound) )
372 if( attr_numeric(&subrange, DW_AT_lower_bound) != 0 )
374 complain( parent, "Array subrange has a nonzero lower bound. Don't know what to do");
380 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) );
395 complain(&subrange, "Couldn't alloc length value");
398 value_init_detached(value, NULL, type_get_simple( ARGTYPE_INT ), 0);
399 value_set_word(value, N );
401 struct expr_node* length = calloc( 1, sizeof(struct expr_node) );
404 complain(&subrange, "Couldn't alloc length expr");
407 expr_init_const(length, value);
409 type_init_array(array_info, info, 0, length, 0 );
414 static bool getStructure(struct arg_type_info* struct_info, Dwarf_Die* parent)
416 type_init_struct(struct_info);
419 if( dwarf_child(parent, &die) != 0 )
421 // no elements; we're done
426 complain(&die, "member: 0x%02x", dwarf_tag(&die) );
428 if( dwarf_tag(&die) != DW_TAG_member )
430 complain(&die, "Structure can have ONLY DW_TAG_member");
435 if( !getTypeDie( &type_die, &die ) )
437 complain( &die, "Couldn't get type of element");
441 struct arg_type_info* member_info = NULL;
442 if( !getType( &member_info, &type_die ) )
444 complain(&die, "Couldn't parse type from DWARF data");
447 type_struct_add( struct_info, member_info, 0 );
449 int res = dwarf_siblingof(&die, &die);
450 if( res == 0 ) continue; /* sibling exists */
451 if( res < 0 ) return false; /* error */
452 break; /* no sibling exists */
458 // Reads the type in the die into the given structure
459 // Returns true on sucess
460 static bool getType( struct arg_type_info** info, Dwarf_Die* type_die)
462 Dwarf_Off die_offset = dwarf_dieoffset(type_die);
463 struct arg_type_info** found_type = dict_find(&type_hash, &die_offset );
464 if(found_type != NULL)
467 complain(type_die, "Read pre-computed type: %p", *info);
473 switch( dwarf_tag(type_die) )
475 case DW_TAG_base_type:
476 *info = type_get_simple( getBaseType( type_die ) );
477 complain(type_die, "Storing base type: %p", *info);
478 dict_insert( &type_hash, &die_offset, info );
481 case DW_TAG_subroutine_type:
482 case DW_TAG_inlined_subroutine:
483 // function pointers are stored as void*. If ltrace tries to dereference
484 // these, it'll get a segfault
485 *info = type_get_simple( ARGTYPE_VOID );
486 complain(type_die, "Storing subroutine type: %p", *info);
487 dict_insert( &type_hash, &die_offset, info );
490 case DW_TAG_pointer_type:
492 if( !getTypeDie(&next_die, type_die ) )
494 // the pointed-to type isn't defined, so I report a void*
495 *info = type_get_simple( ARGTYPE_VOID );
496 complain(type_die, "Storing void-pointer type: %p", *info);
497 dict_insert( &type_hash, &die_offset, info );
501 *info = calloc( 1, sizeof(struct arg_type_info) );
504 complain(type_die, "alloc error");
507 type_init_pointer(*info, NULL, 0);
509 complain(type_die, "Storing pointer type: %p", *info);
510 dict_insert( &type_hash, &die_offset, info );
511 return getType( &(*info)->u.ptr_info.info, &next_die );
513 case DW_TAG_structure_type:
514 *info = calloc( 1, sizeof(struct arg_type_info) );
517 complain(type_die, "alloc error");
521 complain(type_die, "Storing struct type: %p", *info);
522 dict_insert( &type_hash, &die_offset, info );
523 return getStructure( *info, type_die );
526 case DW_TAG_typedef: ;
527 case DW_TAG_const_type: ;
528 case DW_TAG_volatile_type: ;
529 // Various tags are simply pass-through, so I just keep going
531 if( getTypeDie(&next_die, type_die ) )
533 complain(type_die, "Storing const/typedef type: %p", *info);
534 res = getType( info, &next_die );
538 // no type. Use 'void'. Normally I'd think this is bogus, but stdio
539 // typedefs something to void
540 *info = type_get_simple( ARGTYPE_VOID );
541 complain(type_die, "Storing void type: %p", *info);
544 dict_insert( &type_hash, &die_offset, info );
547 case DW_TAG_enumeration_type:
548 // We have an enumeration. This has type "int", but has a particular
549 // lens to handle the enum
550 *info = calloc( 1, sizeof(struct arg_type_info) );
553 complain(type_die, "alloc error");
557 complain(type_die, "Storing enum int: %p", *info);
558 dict_insert( &type_hash, &die_offset, info );
559 return getEnum( *info, type_die );
561 case DW_TAG_array_type:
562 *info = calloc( 1, sizeof(struct arg_type_info) );
565 complain(type_die, "alloc error");
569 complain(type_die, "Storing array: %p", *info);
570 dict_insert( &type_hash, &die_offset, info );
571 return getArray( *info, type_die );
573 case DW_TAG_union_type:
574 *info = type_get_simple( ARGTYPE_VOID );
575 complain(type_die, "Storing union-as-void type: %p", *info);
579 complain(type_die, "Unknown type tag 0x%x", dwarf_tag(type_die));
586 static bool getPrototype(struct prototype* proto, Dwarf_Die* subroutine)
588 // First, look at the return type. This is stored in a DW_AT_type tag in the
589 // subroutine DIE. If there is no such tag, this function returns void
590 Dwarf_Die return_type_die;
591 if( !getTypeDie(&return_type_die, subroutine ) )
593 proto->return_info = type_get_simple( ARGTYPE_VOID );
594 proto->own_return_info = 0;
598 proto->return_info = calloc( 1, sizeof( struct arg_type_info ) );
599 if( proto->return_info == NULL )
601 complain(subroutine, "Couldn't alloc return type");
604 proto->own_return_info = 0;
606 if( !getType( &proto->return_info, &return_type_die ) )
608 complain(subroutine, "Couldn't get return type");
614 // Now look at the arguments
616 if( dwarf_child(subroutine, &arg_die) != 0 )
618 // no args. We're done
623 if( dwarf_tag(&arg_die) != DW_TAG_formal_parameter )
624 goto next_prototype_argument;
626 complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die));
629 if( !getTypeDie(&type_die, &arg_die ) )
631 complain(&arg_die, "Couldn't get the argument type die");
635 struct arg_type_info* arg_type_info = NULL;
636 if( !getType( &arg_type_info, &type_die ) )
638 complain(&arg_die, "Couldn't parse arg type from DWARF data");
643 param_init_type(¶m, arg_type_info, 0);
644 if( prototype_push_param(proto, ¶m) <0 )
646 complain(&arg_die, "couldn't add argument to the prototype");
650 #ifdef DUMP_PROTOTYPES
651 fprintf(stderr, "Adding argument:\n");
652 dump_ltrace_tree(arg_type_info);
655 next_prototype_argument: ;
656 int res = dwarf_siblingof(&arg_die, &arg_die);
657 if( res == 0 ) continue; /* sibling exists */
658 if( res < 0 ) return false; /* error */
659 break; /* no sibling exists */
665 static bool process_die_compileunit(struct protolib* plib, struct library* lib, Dwarf_Die* parent)
668 if( dwarf_child(parent, &die) != 0 )
670 // no child nodes, so nothing to do
676 if( dwarf_tag(&die) == DW_TAG_subprogram )
678 const char* function_name = dwarf_diename(&die);
680 complain(&die, "subroutine_type: 0x%02x; function '%s'", dwarf_tag(&die), function_name);
682 struct prototype* proto =
683 protolib_lookup_prototype(plib, function_name, true );
687 complain(&die, "Prototype already exists. Skipping");
691 if( !filter_matches_symbol(options.plt_filter, function_name, lib) &&
692 !filter_matches_symbol(options.static_filter, function_name, lib) &&
693 !filter_matches_symbol(options.export_filter, function_name, lib) )
695 complain(&die, "Prototype not requested by any filter");
699 proto = malloc(sizeof(struct prototype));
702 complain(&die, "couldn't alloc prototype");
705 prototype_init( proto );
707 if( !getPrototype(proto, &die ) )
709 complain(&die, "couldn't get prototype");
713 protolib_add_prototype(plib, function_name, 0, proto);
717 int res = dwarf_siblingof(&die, &die);
718 if( res == 0 ) continue; /* sibling exists */
719 if( res < 0 ) return false; /* error */
720 break; /* no sibling exists */
726 static bool import( struct protolib* plib, struct library* lib, Dwfl* dwfl )
728 dict_init(&type_hash, sizeof(Dwarf_Off), sizeof(struct arg_type_info*),
729 dwarf_die_hash, dwarf_die_eq, NULL );
732 Dwarf_Die* die = NULL;
733 while( (die = dwfl_nextcu(dwfl, die, &bias)) != NULL )
735 if( dwarf_tag(die) == DW_TAG_compile_unit )
737 if( !process_die_compileunit(plib, lib, die) )
739 complain(die, "Error reading compile unit");
746 complain(die, "DW_TAG_compile_unit expected");
752 dict_destroy( &type_hash, NULL, NULL, NULL );
756 bool import_DWARF_prototypes( struct protolib* plib, struct library* lib,
761 plib = protolib_cache_default(&g_protocache, lib->soname, 0);
764 fprintf(stderr, "Error loading protolib %s: %s.\n",
765 lib->soname, strerror(errno));
769 return import(plib, lib, dwfl);
773 - I handle static functions now. Should I? Those do not have DW_AT_external==1
775 - should process existing prototypes to make sure they match
777 - what do function pointers look like? I'm doing void*
781 - all my *allocs leak
783 - protolib_lookup_prototype should look for imports?