2 This file is part of Kvasir, a Valgrind skin that implements the
3 C language front-end for the Daikon Invariant Detection System
5 Copyright (C) 2004 Philip Guo, MIT CSAIL Program Analysis Group
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
14 This file contains functions that serve to complement readelf.c
15 and arrange the DWARF2 debugging information in an orderly
16 format within dwarf_entry_array
24 #include "elf/dwarf2.h"
26 // Global array of all dwarf entries, sorted (hopefully) by dwarf_entry.ID
27 // so that binary search is possible
28 // DO NOT MODIFY THIS POINTER MANUALLY!!!
29 // Representation invariants:
30 // 1. Every entry in dwarf_entry_array is sorted by ascending ID
31 // (This makes binary search possible)
32 // 2. dwarf_entry_array points to the beginning of the array
33 // 3. The size of the array is specified by dwarf_entry_array_size
34 // 4. All function entries are listed adjacent to their formal parameters
35 // 5. All struct, union, and enumeration entries are listed adjacent
37 // 6. All entries in the array belong to the file specified by the first
38 // compile_unit entry to its left (lower indices) in the array
39 dwarf_entry* dwarf_entry_array = 0;
41 // The size of this array
42 unsigned long dwarf_entry_array_size = 0;
45 /*----------------------------------------
46 Extracting type information from DWARF tag
47 -----------------------------------------*/
53 Returns: 1 if tag = {DW_TAG_base_type, _const_type, _enumerator,
54 _formal_parameter, _pointer_type, _array_type, _subprogram,
55 _union_type, _enumeration_type, _member,
56 _structure_type, _volatile_type, _compile_unit},
58 Effects: Used to determine which entries to record into a dwarf_entry structure;
59 All relevant entries should be included here
61 char tag_is_relevant_entry(unsigned long tag)
66 case DW_TAG_enumeration_type:
67 case DW_TAG_formal_parameter:
69 case DW_TAG_pointer_type:
70 case DW_TAG_structure_type:
71 case DW_TAG_union_type:
72 case DW_TAG_base_type:
73 case DW_TAG_const_type:
74 case DW_TAG_enumerator:
75 case DW_TAG_subprogram:
76 case DW_TAG_volatile_type:
77 case DW_TAG_compile_unit:
78 case DW_TAG_array_type:
79 case DW_TAG_subroutine_type:
80 case DW_TAG_subrange_type:
90 Returns: 1 if tag = {DW_TAG_pointer_type, _array_type, _const_type, _volatile_type},
92 Effects: Used to determine if the type is a modifier - modifier types
93 refer to another type within the dwarf_entry_array after
96 char tag_is_modifier_type(unsigned long tag)
100 case DW_TAG_pointer_type:
101 case DW_TAG_array_type:
102 case DW_TAG_const_type:
103 case DW_TAG_volatile_type:
113 Returns: 1 if tag = {DW_TAG_enumeration_type, _structure_type, _union_type},
115 Effects: Used to determine if the type is a collection of some sort -
116 collections have members and unique type names
118 char tag_is_collection_type(unsigned long tag)
122 case DW_TAG_enumeration_type:
123 case DW_TAG_structure_type:
124 case DW_TAG_union_type:
131 // The rest of these should be self-explanatory:
132 char tag_is_base_type(unsigned long tag)
134 return (tag == DW_TAG_base_type);
137 char tag_is_member(unsigned long tag)
139 return (tag == DW_TAG_member);
142 char tag_is_enumerator(unsigned long tag)
144 return (tag == DW_TAG_enumerator);
147 char tag_is_function(unsigned long tag)
149 return (tag == DW_TAG_subprogram);
152 char tag_is_formal_parameter(unsigned long tag)
154 return (tag == DW_TAG_formal_parameter);
157 char tag_is_compile_unit(unsigned long tag)
159 return (tag == DW_TAG_compile_unit);
162 char tag_is_function_type(unsigned long tag) {
163 return (tag == DW_TAG_subroutine_type);
170 // Each type stored in dwarf_entry.entry_ptr listens for particular
171 // attributes. e.g. collection_type listens for DW_AT_name and DW_AT_byte_size
173 // DW_AT_location: formal_parameter
174 // DW_AT_name: collection_type, member, enumerator, function, formal_parameter, compile_unit
175 // DW_AT_byte_size: base_type, collection_type, member
176 // DW_AT_bit_offset: base_type, member
177 // DW_AT_bit_size: base_type, member
178 // DW_AT_const_value: enumerator
179 // DW_AT_data_member_location: member
180 // DW_AT_type: modifier, member, function, formal_parameter
181 // DW_AT_encoding: base_type
182 // DW_AT_comp_dir: compile_unit
183 // DW_AT_external: function
184 // DW_AT_low_pc: function
186 // Returns: 1 if the entry has a type that is listening for the
187 // given attribute (attr), 0 otherwise
188 char entry_is_listening_for_attribute(dwarf_entry* e, unsigned long attr)
199 return tag_is_formal_parameter(tag);
201 return (tag_is_collection_type(tag) ||
202 tag_is_member(tag) ||
203 tag_is_enumerator(tag) ||
204 tag_is_function(tag) ||
205 tag_is_formal_parameter(tag) ||
206 tag_is_compile_unit(tag));
207 case DW_AT_byte_size:
208 return (tag_is_base_type(tag) ||
209 tag_is_collection_type(tag) ||
211 case DW_AT_bit_offset:
212 return (tag_is_base_type(tag) ||
215 return (tag_is_base_type(tag) ||
217 case DW_AT_const_value:
218 return tag_is_enumerator(tag);
219 case DW_AT_data_member_location:
220 return tag_is_member(tag);
222 return (tag_is_modifier_type(tag) ||
223 tag_is_member(tag) ||
224 tag_is_function(tag) ||
225 tag_is_formal_parameter(tag) ||
226 tag_is_function_type(tag));
227 case DW_AT_upper_bound:
228 return (tag==DW_TAG_subrange_type);
230 return tag_is_base_type(tag);
232 return tag_is_compile_unit(tag);
234 return tag_is_function(tag);
236 return tag_is_function(tag);
245 // Harvest attribute values into the appropriate entry
246 // Returns a boolean to signal success or failure
247 // Remember to only harvest attribute value if the type is listening for it
249 char harvest_type_value(dwarf_entry* e, unsigned long value)
252 if ((e == 0) || (e->entry_ptr == 0))
257 if (tag ==DW_TAG_subrange_type) {
258 ((array_bound*)e->entry_ptr)->target_ID = value;
260 } else if (tag_is_modifier_type(tag))
262 ((modifier_type*)e->entry_ptr)->target_ID = value;
265 else if (tag_is_member(tag))
267 ((member*)e->entry_ptr)->type_ID = value;
270 else if (tag_is_function(tag))
272 ((function*)e->entry_ptr)->return_type_ID = value;
275 else if (tag_is_formal_parameter(tag))
277 ((formal_parameter*)e->entry_ptr)->type_ID = value;
280 else if (tag_is_function_type(tag))
282 ((function_type *)e->entry_ptr)->return_type_ID = value;
289 char harvest_byte_size_value(dwarf_entry* e, unsigned long value)
292 if ((e == 0) || (e->entry_ptr == 0))
297 if (tag_is_base_type(tag))
299 ((base_type*)e->entry_ptr)->byte_size = value;
302 else if (tag_is_collection_type(tag))
304 ((collection_type*)e->entry_ptr)->byte_size = value;
307 else if (tag_is_member(tag))
309 ((member*)e->entry_ptr)->byte_size = value;
316 char harvest_encoding_value(dwarf_entry* e, unsigned long value)
319 if ((e == 0) || (e->entry_ptr == 0))
324 if (tag_is_base_type(tag))
326 ((base_type*)e->entry_ptr)->encoding = value;
333 char harvest_bit_size_value(dwarf_entry* e, unsigned long value)
336 if ((e == 0) || (e->entry_ptr == 0))
341 if (tag_is_base_type(tag))
343 ((base_type*)e->entry_ptr)->bit_size = value;
346 else if (tag_is_member(tag))
348 ((member*)e->entry_ptr)->bit_size = value;
356 char harvest_bit_offset_value(dwarf_entry* e, unsigned long value)
359 if ((e == 0) || (e->entry_ptr == 0))
364 if (tag_is_base_type(tag))
366 ((base_type*)e->entry_ptr)->bit_offset = value;
369 else if (tag_is_member(tag))
371 ((member*)e->entry_ptr)->bit_offset = value;
378 char harvest_const_value(dwarf_entry* e, unsigned long value)
381 if ((e == 0) || (e->entry_ptr == 0))
386 if (tag_is_enumerator(tag))
388 ((enumerator*)e->entry_ptr)->const_value = value;
395 char harvest_upper_bound(dwarf_entry* e, unsigned long value)
398 if ((e == 0) || (e->entry_ptr == 0))
403 if (tag==DW_TAG_subrange_type)
405 ((array_bound*)e->entry_ptr)->upperbound = value;
412 // REMEMBER to use strdup to make a COPY of the string
413 // or else you will run into SERIOUS memory corruption
414 // problems when readelf.c frees those strings from memory!!!
415 char harvest_name(dwarf_entry* e, const char* str)
418 if ((e == 0) || (e->entry_ptr == 0))
423 if (tag_is_enumerator(tag))
425 ((enumerator*)e->entry_ptr)->name = strdup(str);
428 else if (tag_is_collection_type(tag))
430 ((collection_type*)e->entry_ptr)->name = strdup(str);
433 else if (tag_is_member(tag))
435 ((member*)e->entry_ptr)->name = strdup(str);
438 else if (tag_is_function(tag))
440 ((function*)e->entry_ptr)->name = strdup(str);
443 else if (tag_is_formal_parameter(tag))
445 ((formal_parameter*)e->entry_ptr)->name = strdup(str);
448 else if (tag_is_compile_unit(tag))
450 ((compile_unit*)e->entry_ptr)->filename = strdup(str);
457 char harvest_comp_dir(dwarf_entry* e, const char* str)
460 if ((e == 0) || (e->entry_ptr == 0))
465 if (tag_is_compile_unit(tag))
467 ((compile_unit*)e->entry_ptr)->comp_dir = strdup(str);
474 char harvest_location(dwarf_entry* e, long value)
477 if ((e == 0) || (e->entry_ptr == 0))
482 if (tag_is_formal_parameter(tag))
484 ((formal_parameter*)e->entry_ptr)->location = value;
491 char harvest_data_member_location(dwarf_entry* e, long value)
494 if ((e == 0) || (e->entry_ptr == 0))
499 if (tag_is_member(tag))
501 ((member*)e->entry_ptr)->data_member_location = value;
508 char harvest_string(dwarf_entry* e, unsigned long attr, const char* str)
510 if ((e == 0) || (e->entry_ptr == 0))
513 if (attr == DW_AT_name)
514 return harvest_name(e, str);
515 else if (attr == DW_AT_comp_dir)
516 return harvest_comp_dir(e, str);
521 char harvest_external_flag_value(dwarf_entry *e, unsigned long value) {
523 if ((e == 0) || (e->entry_ptr == 0))
528 if (tag_is_function(tag))
530 ((function*)e->entry_ptr)->is_external = value;
537 char harvest_address_value(dwarf_entry* e, unsigned long attr,
538 unsigned long value) {
540 if ((e == 0) || (e->entry_ptr == 0))
545 if (tag_is_function(tag) && attr == DW_AT_low_pc)
547 ((function*)e->entry_ptr)->start_pc = value;
555 char harvest_ordinary_unsigned_value(dwarf_entry* e, unsigned long attr, unsigned long value)
557 if ((e == 0) || (e->entry_ptr == 0))
561 // DW_AT_byte_size, DW_AT_encoding, DW_AT_const_value,
562 // DW_AT_bit_size, DW_AT_bit_offset and DW_AT_external
563 // return ordinary unsigned data
566 case DW_AT_byte_size:
567 return harvest_byte_size_value(e, value);
569 return harvest_encoding_value(e, value);
570 case DW_AT_const_value:
571 return harvest_const_value(e, value);
572 case DW_AT_upper_bound:
573 return harvest_upper_bound(e, value);
575 return harvest_bit_size_value(e, value);
576 case DW_AT_bit_offset:
577 return harvest_bit_offset_value(e, value);
579 return harvest_external_flag_value(e, value);
586 Requires: dwarf_entry_array initialized
589 Effects: Performs a binary search through dwarf_entry_array, looking for
590 the entry with the matching ID field (target_ID).
591 Stores the index of the matching entry in index_ptr
593 char binary_search_dwarf_entry_array(unsigned long target_ID, unsigned long* index_ptr)
595 unsigned long upper = dwarf_entry_array_size - 1;
596 unsigned long lower = 0;
598 // printf("--target_ID: 0x%x, index_ptr: 0x%x, upper.ID: 0x%x, lower.ID: 0x%x\n",
601 // dwarf_entry_array[upper].ID,
602 // dwarf_entry_array[lower].ID);
604 // First do boundary sanity check to save ourselves lots of useless work:
605 if ((target_ID > dwarf_entry_array[upper].ID) ||
606 (target_ID < dwarf_entry_array[lower].ID))
609 while (upper > lower)
611 unsigned long mid = (upper + lower) / 2;
612 unsigned long cur_ID = dwarf_entry_array[mid].ID;
614 // printf("**lower: %d, mid: %d, upper: %d, target_ID: 0x%x, cur_ID: 0x%x\n",
621 // Special case - (upper == (lower + 1)) - that means only 2 entries left to check:
622 if (upper == (lower + 1))
624 if (target_ID == dwarf_entry_array[lower].ID)
629 else if (target_ID == dwarf_entry_array[upper].ID)
636 // YOU LOSE! The target_ID is BETWEEN the lower and upper entries
640 else if (target_ID == cur_ID) // Right on!
645 else if (target_ID < cur_ID)
649 else if (target_ID > cur_ID)
655 // Return 0 if no answer found
660 Requires: dwarf_entry_array initialized
661 Modifies: certain fields within certain entries within dwarf_entry_array
662 (modifier_type::target_ptr, function::return_type,
663 member::type_ptr, formal_parameter::type_ptr)
665 Effects: Links every entry with a type_ID to the actual entry of that type
666 within dwarf_entry_array. Sets the appropriate type_ptr pointers to point
667 to entries within dwarf_entry_array where that type resides
668 (relevant for modifier_type, member, function, and formal_parameter entries)
670 void link_entries_to_type_entries()
673 dwarf_entry* cur_entry = 0;
675 for (idx = 0; idx < dwarf_entry_array_size; idx++)
678 cur_entry = &dwarf_entry_array[idx];
679 tag = cur_entry->tag_name;
681 if (tag_is_modifier_type(tag))
684 unsigned long target_index = 0;
685 modifier_type* modifier_ptr = (modifier_type*)(cur_entry->entry_ptr);
686 unsigned long target_ID = modifier_ptr->target_ID;
688 // Use a binary search to try to find the index of the entry in the
689 // array with the corresponding target_ID
690 success = binary_search_dwarf_entry_array(target_ID, &target_index);
693 modifier_ptr->target_ptr=&dwarf_entry_array[target_index];
695 if (tag==DW_TAG_array_type) {
696 int currentlevel=cur_entry->level;
697 dwarf_entry* tmp_entry = cur_entry+1;
698 int dist_to_end=dwarf_entry_array_size-idx;
700 while ((member_count < dist_to_end) // put this first! short-circuit eval.
701 && tmp_entry->level> currentlevel)
703 if (tmp_entry->tag_name==DW_TAG_subrange_type&&(tmp_entry->level==(currentlevel+1)))
707 modifier_ptr->array_ptr=(dwarf_entry**)calloc(1,member_count*sizeof(dwarf_entry*));
708 modifier_ptr->num_array=member_count;
710 tmp_entry=cur_entry+1;
711 while ((member_count < dist_to_end) // put this first! short-circuit eval.
712 && tmp_entry->level> currentlevel)
714 if (tmp_entry->tag_name==DW_TAG_subrange_type&&(tmp_entry->level==(currentlevel+1)))
715 modifier_ptr->array_ptr[member_count++]=tmp_entry;
720 else if (tag==DW_TAG_subrange_type) {
722 unsigned long target_index = 0;
723 array_bound* bound_ptr = (array_bound*)(cur_entry->entry_ptr);
724 unsigned long target_ID = bound_ptr->target_ID;
726 // Use a binary search to try to find the index of the entry in the
727 // array with the corresponding target_ID
728 success = binary_search_dwarf_entry_array(target_ID, &target_index);
731 bound_ptr->target_ptr=&dwarf_entry_array[target_index];
734 else if (tag_is_function(tag))
737 unsigned long target_index = 0;
738 function* function_ptr = (function*)(cur_entry->entry_ptr);
739 unsigned long target_ID = function_ptr->return_type_ID;
741 // Use a binary search to try to find the index of the entry in the
742 // array with the corresponding target_ID
743 success = binary_search_dwarf_entry_array(target_ID, &target_index);
746 function_ptr->return_type=&dwarf_entry_array[target_index];
749 else if (tag_is_function_type(tag))
752 unsigned long target_index = 0;
753 function_type *function_ptr
754 = (function_type *)(cur_entry->entry_ptr);
755 unsigned long target_ID = function_ptr->return_type_ID;
757 // Use a binary search to try to find the index of the entry in the
758 // array with the corresponding target_ID
759 success = binary_search_dwarf_entry_array(target_ID, &target_index);
762 function_ptr->return_type=&dwarf_entry_array[target_index];
765 else if (tag_is_member(tag))
768 unsigned long target_index = 0;
769 member* member_ptr = (member*)(cur_entry->entry_ptr);
770 unsigned long target_ID = member_ptr->type_ID;
772 // Use a binary search to try to find the index of the entry in the
773 // array with the corresponding target_ID
774 success = binary_search_dwarf_entry_array(target_ID, &target_index);
777 member_ptr->type_ptr=&dwarf_entry_array[target_index];
780 else if (tag_is_formal_parameter(tag))
783 unsigned long target_index = 0;
784 formal_parameter* formal_param_ptr = (formal_parameter*)(cur_entry->entry_ptr);
785 unsigned long target_ID = formal_param_ptr->type_ID;
787 // Use a binary search to try to find the index of the entry in the
788 // array with the corresponding target_ID
789 success = binary_search_dwarf_entry_array(target_ID, &target_index);
792 formal_param_ptr->type_ptr=&dwarf_entry_array[target_index];
799 Requires: dist_to_end indicates distance from e until end of dwarf_entry_array,
800 e points to an element of dwarf_entry_array
801 Modifies: e->num_members, e->members
803 Effects: Links the collection entry to its members, which are located
804 adjacent to it in the dwarf_entry array, making sure not to
805 accidentally segfault by indexing out of bounds
806 (indicated by dist_to_end param
807 which indicates distance until the end of the array)
809 void link_collection_to_members(dwarf_entry* e, unsigned long dist_to_end)
811 // 1. Figure out what kind of collection it is (struct, union, enumeration)
812 // 2. Traverse through subsequent entries, checking if the type_ID
813 // is the appropriate member type for that collection
814 // 3. Stop either when you hit a type_ID that is not a member OR
815 // when you are about to run out of array bounds
816 // 4. Store the subsequent array entry (e + 1) as pointer to first member
817 // (as long as its not out of bounds) and store the number of entries
818 // you traversed as the number of members
820 unsigned long member_count = 0;
821 unsigned int currentlevel=e->level;
822 dwarf_entry* cur_entry = e;
823 collection_type* collection_ptr = (collection_type*)(e->entry_ptr);
825 // If you are at the end of the array, you're screwed anyways
831 // enumerations expect DW_TAG_enumerator as members
832 case DW_TAG_enumeration_type:
833 cur_entry++; // Move to the next entry - safe since dist_to_end > 0 by this point
834 while ((member_count < dist_to_end) // put this first! short-circuit eval.
835 && cur_entry->level> currentlevel)
837 if (cur_entry->tag_name==DW_TAG_enumerator&&(cur_entry->level==(currentlevel+1)))
842 // structs and unions expect DW_TAG_member as members
843 case DW_TAG_structure_type:
844 case DW_TAG_union_type:
845 cur_entry++; // Move to the next entry - safe since dist_to_end > 0 by this point
846 while ((member_count < dist_to_end) // put this first! short-circuit eval.
847 && cur_entry->level>currentlevel)
849 if (cur_entry->tag_name==DW_TAG_member&&cur_entry->level==(currentlevel+1))
858 collection_ptr->num_members = member_count;
859 collection_ptr->members = (dwarf_entry **)calloc(1,member_count*sizeof(dwarf_entry *));
865 // enumerations expect DW_TAG_enumerator as members
866 case DW_TAG_enumeration_type:
867 cur_entry++; // Move to the next entry - safe since dist_to_end > 0 by this point
868 while ((member_count < dist_to_end) // put this first! short-circuit eval.
869 && cur_entry->level> currentlevel)
871 if (cur_entry->tag_name==DW_TAG_enumerator&&(cur_entry->level==(currentlevel+1)))
872 collection_ptr->members[member_count++]=cur_entry;
876 // structs and unions expect DW_TAG_member as members
877 case DW_TAG_structure_type:
878 case DW_TAG_union_type:
879 cur_entry++; // Move to the next entry - safe since dist_to_end > 0 by this point
880 while ((member_count < dist_to_end) // put this first! short-circuit eval.
881 && cur_entry->level>currentlevel)
883 if (cur_entry->tag_name==DW_TAG_member&&cur_entry->level==(currentlevel+1))
884 collection_ptr->members[member_count++]=cur_entry;
893 // Same as above except linking functions with formal parameters
894 void link_function_to_params(dwarf_entry* e, unsigned long dist_to_end)
896 unsigned long param_count = 0;
897 dwarf_entry* cur_entry = e;
898 function* function_ptr = (function*)(e->entry_ptr);
900 // If you are at the end of the array, you're screwed anyways
904 cur_entry++; // Move to the next entry - safe since dist_to_end > 0 by this point
905 // functions expect DW_TAG_formal_parameter as parameters
906 while ((param_count < dist_to_end) // important that this is first! short-circuit eval.
907 && cur_entry->tag_name == DW_TAG_formal_parameter)
913 function_ptr->num_formal_params = param_count;
914 function_ptr->params = (e + 1);
918 Requires: dwarf_entry_array is initialized
919 Modifies: ((function*)cur_entry->entry_ptr)->filename for function entries
921 Effects: Initialize the filename field of each function entry
922 by linearly traversing dwarf_entry_array and noting that every compile_unit
923 entry describes a file and all functions to the right of that entry
924 (but to the left of the next entry) belong to that file
925 e.g. [compile_unit foo.c][...][func1][...][func2][...][compile_unit bar.c][func3]
926 func1 and func2 belong to foo.c and func3 belongs to bar.c
928 void initialize_function_filenames()
932 dwarf_entry* cur_entry = 0;
934 for (idx = 0; idx < dwarf_entry_array_size; idx++)
936 cur_entry = &dwarf_entry_array[idx];
938 if (tag_is_compile_unit(cur_entry->tag_name))
939 cur_file = ((compile_unit*)cur_entry->entry_ptr)->filename;
940 else if (tag_is_function(cur_entry->tag_name))
941 ((function*)cur_entry->entry_ptr)->filename = cur_file;
946 Requires: dwarf_entry_array is initialized
947 Modifies: function and collection entries within dwarf_entry_array
949 Effects: Links function and collections entries to their respective members
950 e.g. functions need to have a list of their formal parameters
951 while structs, unions, and enumeration types need to have lists of members
952 THIS ALGORITHM EXPLOITS THE FACT THAT MEMBERS/PARAMETERS ARE LISTED
953 RIGHT AFTER THE RESPECTIVE FUNCTION OR STRUCT
954 e.g. [function][param1][param2][param3][something_else]
956 void link_array_entries_to_members()
959 dwarf_entry* cur_entry = 0;
961 // Linearly traverse the array and pick off function or collections
962 // (struct, union, enumeration) entries to link to members:
963 for (idx = 0; idx < dwarf_entry_array_size; idx++)
965 cur_entry = &dwarf_entry_array[idx];
966 if (tag_is_collection_type(cur_entry->tag_name))
967 link_collection_to_members(cur_entry, dwarf_entry_array_size - idx - 1);
968 else if (tag_is_function(cur_entry->tag_name))
969 link_function_to_params(cur_entry, dwarf_entry_array_size - idx - 1);
973 // Prints the contents of the entry depending on its type
974 void print_dwarf_entry(dwarf_entry* e)
978 printf("ERROR! Pointer e is null in print_dwarf_entry\n");
982 printf("ID:0x%lx, TAG:%s\n", e->ID, get_TAG_name(e->tag_name));
986 case DW_TAG_subprogram:
988 function* function_ptr = (function*)(e->entry_ptr);
989 printf(" Name: %s, Filename: %s, Return Type ID (addr): 0x%lx (%p), Num. params: %ld, 1st param addr: %p\n",
991 function_ptr->filename,
992 function_ptr->return_type_ID,
993 function_ptr->return_type,
994 function_ptr->num_formal_params,
995 function_ptr->params);
998 case DW_TAG_formal_parameter:
1000 formal_parameter* formal_param_ptr = (formal_parameter*)(e->entry_ptr);
1001 printf(" Name: %s, Type ID (addr): 0x%lx (%p), Location: %ld\n",
1002 formal_param_ptr->name,
1003 formal_param_ptr->type_ID,
1004 formal_param_ptr->type_ptr,
1005 formal_param_ptr->location);
1010 member* member_ptr = (member*)(e->entry_ptr);
1011 printf(" Name: %s, Type ID (addr): 0x%lx (%p), Data member location: %ld, Byte size: %ld, Bit offset: %ld, Bit size: %ld\n",
1013 member_ptr->type_ID,
1014 member_ptr->type_ptr,
1015 member_ptr->data_member_location,
1016 member_ptr->byte_size,
1017 member_ptr->bit_offset,
1018 member_ptr->bit_size);
1021 case DW_TAG_enumerator:
1023 enumerator* enumerator_ptr = (enumerator*)(e->entry_ptr);
1024 printf(" Name: %s, Const value: %ld\n",
1025 enumerator_ptr->name,
1026 enumerator_ptr->const_value);
1030 case DW_TAG_structure_type:
1031 case DW_TAG_union_type:
1032 case DW_TAG_enumeration_type:
1034 collection_type* collection_ptr = (collection_type*)(e->entry_ptr);
1035 printf(" Name: %s, Byte size: %ld, Num. members: %ld, 1st member addr: %p\n",
1036 collection_ptr->name,
1037 collection_ptr->byte_size,
1038 collection_ptr->num_members,
1039 collection_ptr->members);
1043 case DW_TAG_base_type:
1045 base_type* base_ptr = (base_type*)(e->entry_ptr);
1046 printf(" Byte size: %ld, Encoding: %ld ",
1047 base_ptr->byte_size,
1048 base_ptr->encoding);
1050 // More detailed encoding information
1051 switch (base_ptr->encoding)
1053 case DW_ATE_void: printf ("(void)"); break;
1054 case DW_ATE_address: printf ("(machine address)"); break;
1055 case DW_ATE_boolean: printf ("(boolean)"); break;
1056 case DW_ATE_complex_float: printf ("(complex float)"); break;
1057 case DW_ATE_float: printf ("(float)"); break;
1058 case DW_ATE_signed: printf ("(signed)"); break;
1059 case DW_ATE_signed_char: printf ("(signed char)"); break;
1060 case DW_ATE_unsigned: printf ("(unsigned)"); break;
1061 case DW_ATE_unsigned_char: printf ("(unsigned char)"); break;
1062 /* DWARF 2.1 value. */
1063 case DW_ATE_imaginary_float: printf ("(imaginary float)"); break;
1065 if (base_ptr->encoding >= DW_ATE_lo_user
1066 && base_ptr->encoding <= DW_ATE_hi_user)
1068 printf ("(user defined type)");
1072 printf ("(unknown type)");
1077 printf(", Bit size: %ld, Bit offset: %ld\n",
1079 base_ptr->bit_offset);
1083 case DW_TAG_const_type:
1084 case DW_TAG_pointer_type:
1085 case DW_TAG_array_type:
1086 case DW_TAG_volatile_type:
1088 modifier_type* modifier_ptr = (modifier_type*)(e->entry_ptr);
1089 printf(" Target ID (addr): 0x%lx (%p)\n",
1090 modifier_ptr->target_ID,
1091 modifier_ptr->target_ptr);
1095 case DW_TAG_compile_unit:
1097 compile_unit* compile_ptr = (compile_unit*)(e->entry_ptr);
1098 printf(" Filename: %s, Compile dir: %s\n",
1099 compile_ptr->filename,
1100 compile_ptr->comp_dir);
1103 case DW_TAG_subroutine_type:
1105 function_type * func_type = (function_type *)(e->entry_ptr);
1106 printf(" Return type ID (addr): 0x%lx (%p)\n",
1107 func_type->return_type_ID, func_type->return_type);
1117 Modifies: dwarf_entry_array (initializes and blanks all entries to zero)
1119 Effects: Initializes sets up dwarf_entry_array to hold num_entries components
1121 void initialize_dwarf_entry_array(unsigned long num_entries)
1123 // use calloc to blank everything upon initialization
1124 dwarf_entry_array = calloc(num_entries, sizeof *dwarf_entry_array);
1128 Requires: dwarf_entry_array is initialized
1129 Modifies: dwarf_entry_array (free and set to 0)
1131 Effects: Destroys dwarf_entry_array and all entry_ptr fields of all entries
1133 void destroy_dwarf_entry_array()
1135 // Traverse the array and free the entry_ptr of all entries within array
1138 for (i = 0; i < dwarf_entry_array_size; i++)
1140 free(dwarf_entry_array[i].entry_ptr);
1143 // Free the array itself
1144 free(dwarf_entry_array);
1147 void print_dwarf_entry_array()
1150 printf("--- BEGIN DWARF ENTRY ARRAY - size: %ld\n", dwarf_entry_array_size);
1151 for (i = 0; i < dwarf_entry_array_size; i++)
1153 printf("array[%ld] (%p): ", i, dwarf_entry_array + i);
1154 print_dwarf_entry(&dwarf_entry_array[i]);
1156 printf("--- END DWARF ENTRY ARRAY\n");
1160 Requires: e is initialized and has a e->tag_name
1161 Modifies: e->entry_ptr (initializes and set to 0)
1163 Effects: Initialize the value of e->entry_ptr to the appropriate sub-type
1164 based on the value of tag_name
1165 If tag_name is 0, then don't do anything
1167 void initialize_dwarf_entry_ptr(dwarf_entry* e)
1171 if (tag_is_base_type(e->tag_name))
1173 e->entry_ptr = calloc(1, sizeof(base_type));
1175 else if (e->tag_name==DW_TAG_subrange_type) {
1176 e->entry_ptr=calloc(1,sizeof(array_bound));
1178 else if (tag_is_modifier_type(e->tag_name))
1180 e->entry_ptr = calloc(1, sizeof(modifier_type));
1182 else if (tag_is_collection_type(e->tag_name))
1184 e->entry_ptr = calloc(1, sizeof(collection_type));
1186 else if (tag_is_member(e->tag_name))
1188 e->entry_ptr = calloc(1, sizeof(member));
1190 else if (tag_is_enumerator(e->tag_name))
1192 e->entry_ptr = calloc(1, sizeof(enumerator));
1194 else if (tag_is_function(e->tag_name))
1196 e->entry_ptr = calloc(1, sizeof(function));
1198 else if (tag_is_formal_parameter(e->tag_name))
1200 e->entry_ptr = calloc(1, sizeof(formal_parameter));
1202 else if (tag_is_compile_unit(e->tag_name))
1204 e->entry_ptr = calloc(1, sizeof(compile_unit));
1206 else if (tag_is_function_type(e->tag_name))
1208 e->entry_ptr = calloc(1, sizeof(function_type));
1213 // Now that dwarf_entry_array is initialized with values, we must link
1214 // the entries together in a coherent manner
1215 void finish_dwarf_entry_array_init(void)
1217 // These must be done in this order or else things will go screwy!!!
1218 link_array_entries_to_members();
1219 initialize_function_filenames();
1220 link_entries_to_type_entries();