Automatic structure extraction tool...works on binaries with dwarf-2 debug informatio...
[repair.git] / Repair / RepairCompiler / structextract / dumpstructures.c
1 /*
2    This file is part of Kvasir, a Valgrind skin that implements the
3    C language front-end for the Daikon Invariant Detection System
4
5    Copyright (C) 2004 Philip Guo, MIT CSAIL Program Analysis Group
6
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.
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17
18 #include "dumpstructures.h"
19 #include "typedata.h"
20 #include "elf/dwarf2.h"
21
22 #define GETTYPE 1
23 #define POSTNAME 2
24
25 int process_elf_binary_data(char* filename);
26
27 int main(int argc, char **argv) {
28   if (argc<2)
29     return 0;
30   process_elf_binary_data(argv[1]);
31   daikon_preprocess_entry_array();
32 }
33
34 // Pre-processes global dwarf_entry_array in order to place
35 // the data in a form that can easily be turned into .decls
36 // and .dtrace files
37 void daikon_preprocess_entry_array()
38 {
39   initializeTypeArray();
40 }
41
42 int typecount=0;
43
44 int entry_is_type(dwarf_entry *entry) {
45   if (entry->tag_name==DW_TAG_structure_type||
46       entry->tag_name==DW_TAG_union_type) {
47     collection_type* collection_ptr = (collection_type*)(entry->entry_ptr);
48     if (collection_ptr->name==0) {
49       collection_ptr->name=(char*)malloc(100);
50       sprintf(collection_ptr->name,"TYPE%ld",typecount++);
51     }
52     return 1;
53   }
54   return 0;
55 }
56
57 int entry_is_valid_function(dwarf_entry *entry) {
58   if (tag_is_function(entry->tag_name)) {
59     function* funcPtr = (function*)(entry->entry_ptr);
60     if (funcPtr->start_pc != 0 && funcPtr->name != 0) {
61       return 1;
62     } else {
63 #ifdef SHOW_DEBUG
64       printf("Skipping invalid-looking function %s\n", funcPtr->name);
65 #endif
66     }
67   }
68   return 0;
69 }
70
71 // Finds the number of function entries in the dwarf_entry_array
72 // and creates the DaikonFunctionInfo array to match that size
73
74 void initializeTypeArray()
75 {
76   int i;
77   dwarf_entry * cur_entry;
78   for (i = 0; i < dwarf_entry_array_size; i++)
79     {
80       cur_entry = &dwarf_entry_array[i];
81       if (entry_is_type(cur_entry))
82         {
83           collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr);
84           int j=0;
85           int offset=0;
86           printf("structure %s {\n",collection_ptr->name);
87           
88           for(j=0;j<collection_ptr->num_members;j++) {
89             dwarf_entry *entry=collection_ptr->members[j];
90             member * member_ptr=(member *)entry->entry_ptr;
91             char *name=member_ptr->name;
92             dwarf_entry *type=member_ptr->type_ptr;
93             char *typestr=printname(type,GETTYPE);
94             char *poststr=printname(type,POSTNAME);
95             if (member_ptr->data_member_location>offset) {
96               printf("   reserved byte[%ld];\n",member_ptr->data_member_location-offset);
97               offset=member_ptr->data_member_location;
98             }
99             offset+=getsize(type);
100
101             printf("   %s %s%s;\n",typestr,name,poststr);
102           }
103           printf("}\n\n");
104         }
105     }
106 }
107
108 int getsize(dwarf_entry *type) {
109   if (type==NULL)
110     return 0;
111   switch(type->tag_name) {
112   case DW_TAG_enumeration_type:
113     return 4;
114   case DW_TAG_array_type: {
115     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
116     int size=((array_bound*)modifier_ptr->array_ptr[0]->entry_ptr)->upperbound+1;
117     return size*getsize(modifier_ptr->target_ptr);
118   }
119   case DW_TAG_base_type: {
120     base_type *base=(base_type*)type->entry_ptr;
121     return base->byte_size;
122   }
123   case DW_TAG_pointer_type: {
124     return 4;
125   }
126   case DW_TAG_structure_type: {
127     collection_type *ctype=(collection_type*)type->entry_ptr;
128     return ctype->byte_size;
129   }
130   default:
131     return 0;
132   }
133 }
134
135 char * printname(dwarf_entry * type,int op) {
136   if (type==NULL) {
137     if (op==GETTYPE)
138       return NULL;
139   }
140
141   switch(type->tag_name) {
142   case DW_TAG_enumeration_type:
143     if (op==GETTYPE)
144       return "int";
145     break;
146   case DW_TAG_array_type: {
147     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
148     if (op==GETTYPE) {
149         char *typename=printname(modifier_ptr->target_ptr,op);
150         return typename;
151     } else if (op==POSTNAME) {
152       int size=((array_bound*)modifier_ptr->array_ptr[0]->entry_ptr)->upperbound+1;
153       char *typename=printname(modifier_ptr->target_ptr,op);
154       char *newptr=(char *)malloc(200);
155       sprintf(newptr,"%s[%ld]",typename,size);
156       return newptr;
157     }
158   }
159     break;
160   case DW_TAG_base_type: {
161     base_type *base=(base_type*)type->entry_ptr;
162     if (op==GETTYPE)
163       switch(base->byte_size) {
164       case 1:
165         return "byte";
166       case 2:
167         return "short";
168       case 4:
169         return "int";
170       default: {
171         char *m=(char*)malloc(100);
172         sprintf(m,"error%ld",base->byte_size);
173         return m;
174       }
175       }
176   }
177     break;
178   case DW_TAG_pointer_type: {
179     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
180     if (op==GETTYPE) {
181       if (modifier_ptr->target_ptr==NULL)
182         return "void *"; /* seems like a good guess */
183       {
184         char *typename=printname(modifier_ptr->target_ptr,op);
185         /* evil hack */
186         char *newptr=(char *)malloc(200);
187         sprintf(newptr,"%s *",typename);
188         return newptr;
189       }
190     }
191   }
192     break;
193   case DW_TAG_structure_type: {
194     collection_type *ctype=(collection_type*)type->entry_ptr;
195     if (op==GETTYPE&&ctype->name==NULL) {
196       ctype->name=(char*)malloc(100);
197       sprintf(ctype->name,"TYPE%ld",typecount++);
198     }
199     if (op==GETTYPE)
200       return ctype->name;
201   }
202     break;
203   default:
204     if (op==GETTYPE)
205       return "unknown";
206   }
207   if (op==POSTNAME)
208     return "";
209   return "ERROR";
210 }
211
212