Update to add padding at the end of structs.
[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
23 #define GETTYPE 1
24 #define POSTNAME 2
25
26 int process_elf_binary_data(char* filename);
27
28 int main(int argc, char **argv) {
29   if (argc<2)
30     return 0;
31   process_elf_binary_data(argv[1]);
32   daikon_preprocess_entry_array();
33 }
34
35 // Pre-processes global dwarf_entry_array in order to place
36 // the data in a form that can easily be turned into .decls
37 // and .dtrace files
38 void daikon_preprocess_entry_array()
39 {
40   initializeTypeArray();
41 }
42
43 int typecount=0;
44 int assigntype=0;
45 int entry_is_type(dwarf_entry *entry) {
46   if (entry->tag_name==DW_TAG_structure_type||
47       entry->tag_name==DW_TAG_union_type) {
48     collection_type* collection_ptr = (collection_type*)(entry->entry_ptr);
49     /*    if (collection_ptr->name==0&&assigntype) {
50       collection_ptr->name=(char*)malloc(100);
51       sprintf(collection_ptr->name,"TYPE%ld",typecount++);
52       }*/
53     return 1;
54   }
55   return 0;
56 }
57
58 int entry_is_valid_function(dwarf_entry *entry) {
59   if (tag_is_function(entry->tag_name)) {
60     function* funcPtr = (function*)(entry->entry_ptr);
61     if (funcPtr->start_pc != 0 && funcPtr->name != 0) {
62       return 1;
63     } else {
64 #ifdef SHOW_DEBUG
65       printf("Skipping invalid-looking function %s\n", funcPtr->name);
66 #endif
67     }
68   }
69   return 0;
70 }
71
72 struct valuepair {
73   int index;
74   int value;
75 };
76
77 void initializeTypeArray()
78 {
79   int i;
80   dwarf_entry * cur_entry;
81   struct genhashtable * ght=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
82   
83   for (i = 0; i < dwarf_entry_array_size; i++)
84     {
85       cur_entry = &dwarf_entry_array[i];
86       if (entry_is_type(cur_entry))
87         {
88           collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr);
89           int j=0;
90           int offset=0;
91           int value=0;
92           for(j=0;j<collection_ptr->num_members;j++) {
93             dwarf_entry *entry=collection_ptr->members[j];
94             if (entry->tag_name==DW_TAG_inheritance) {
95               value++;
96               continue;
97             }
98             {
99               member * member_ptr=(member *)entry->entry_ptr;
100               char *name=member_ptr->name;
101               dwarf_entry *type=member_ptr->type_ptr;
102               char *typestr=printname(type,GETTYPE);
103               char *poststr=printname(type,POSTNAME);
104               
105               if (typestr!=NULL)
106                 value++;
107             }
108           }
109           if (collection_ptr->name!=NULL) {
110             struct valuepair *vp=NULL;
111             if (gencontains(ght,collection_ptr->name))
112               vp=(struct valuepair *)gengettable(ght,collection_ptr->name);
113             if (vp==NULL||vp->value<value) {
114               if (vp==NULL) {
115                 vp=(struct valuepair*)calloc(1,sizeof(struct valuepair));
116                 genputtable(ght,collection_ptr->name,vp);
117               }
118               vp->value=value;
119               vp->index=i;
120             }
121           }
122         }
123     }
124
125   assigntype=1;
126   for (i = 0; i < dwarf_entry_array_size; i++)
127     {
128       cur_entry = &dwarf_entry_array[i];
129       if (entry_is_type(cur_entry))
130         {
131           collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr);
132           int j=0;
133           int offset=0;
134           if (collection_ptr->name==NULL)
135             continue;
136           if (gencontains(ght,collection_ptr->name)) {
137             struct valuepair *vp=(struct valuepair*)gengettable(ght,collection_ptr->name);
138             if (vp->index!=i)
139               continue;
140           }
141           j=0;
142           printf("structure %s ",collection_ptr->name);
143
144           while(j<collection_ptr->num_members&&
145                 collection_ptr->members[j]->tag_name==DW_TAG_inheritance) {
146             inherit *in_ptr=(inherit*)collection_ptr->members[j]->entry_ptr;
147             dwarf_entry *typeptr=in_ptr->target_ptr;
148             collection_type* sub_ptr = (collection_type*)(typeptr->entry_ptr);
149             if (j==0)
150               printf("subclasses ");
151             else
152               printf(", ");
153             printf("%s ",sub_ptr->name);
154             j++;
155           }
156           printf("{ \n");
157           
158           for(j=0;j<collection_ptr->num_members;j++) {
159             dwarf_entry *entry=collection_ptr->members[j];
160             if (entry->tag_name==DW_TAG_inheritance) {
161               inherit * inherit_ptr=(inherit *)entry->entry_ptr;
162               if (inherit_ptr->data_member_location>offset) {
163                 printf("   reserved byte[%ld];\n",inherit_ptr->data_member_location-offset);
164                 offset=inherit_ptr->data_member_location;
165               }
166               {
167                 dwarf_entry *type=inherit_ptr->target_ptr;
168                 collection_type *c_ptr=(collection_type*)type->entry_ptr;
169                 offset+=printtype(c_ptr,ght);
170               }
171             } else {
172               member * member_ptr=(member *)entry->entry_ptr;
173               char *name=member_ptr->name;
174               dwarf_entry *type=member_ptr->type_ptr;
175               char *typestr=printname(type,GETTYPE);
176               char *poststr=printname(type,POSTNAME);
177               if (member_ptr->data_member_location>offset) {
178                 printf("   reserved byte[%ld];\n",member_ptr->data_member_location-offset);
179                 offset=member_ptr->data_member_location;
180               }
181               offset+=getsize(type);
182               
183               printf("   %s %s%s;\n",typestr,name,poststr);
184             }
185           }
186           if (offset<collection_ptr->byte_size)
187             printf("   reserved byte[%ld];\n",collection_ptr->byte_size-offset);
188           printf("}\n\n");
189         }
190     }
191 }
192
193 int printtype(collection_type *collection_ptr,struct genhashtable *ght)
194 {
195   int j=0;
196   int offset=0;
197   int value=0;
198   
199   struct valuepair *vp=NULL;
200   if (gencontains(ght,collection_ptr->name))
201     vp=(struct valuepair *)gengettable(ght,collection_ptr->name);
202   if (vp!=NULL)
203     collection_ptr=(collection_type*) dwarf_entry_array[vp->index].entry_ptr;
204
205   for(j=0;j<collection_ptr->num_members;j++) {
206     dwarf_entry *entry=collection_ptr->members[j];
207     if (entry->tag_name==DW_TAG_inheritance) {
208       inherit * inherit_ptr=(inherit *)entry->entry_ptr;
209       if (inherit_ptr->data_member_location>offset) {
210         printf("   reserved byte[%ld];\n",inherit_ptr->data_member_location-offset);
211         offset=inherit_ptr->data_member_location;
212       }
213
214       {
215         dwarf_entry *type=inherit_ptr->target_ptr;
216         collection_type *c_ptr=(collection_type*)type->entry_ptr;
217         offset+=printtype(c_ptr,ght);
218       }
219     } else {
220       member * member_ptr=(member *)entry->entry_ptr;
221       char *name=member_ptr->name;
222       dwarf_entry *type=member_ptr->type_ptr;
223       char *typestr=printname(type,GETTYPE);
224       char *poststr=printname(type,POSTNAME);
225       if (member_ptr->data_member_location>offset) {
226         printf("   reserved byte[%ld];\n",member_ptr->data_member_location-offset);
227         offset=member_ptr->data_member_location;
228       }
229       offset+=getsize(type);
230       
231       printf("   %s %s%s;\n",typestr,name,poststr);
232     }
233   }
234   return offset;
235 }
236
237
238
239 int getsize(dwarf_entry *type) {
240   if (type==NULL)
241     return 0;
242   switch(type->tag_name) {
243   case DW_TAG_enumeration_type:
244     return 4;
245   case DW_TAG_array_type: {
246     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
247     int size=1;
248     int i;
249     for(i=0;i<modifier_ptr->num_array;i++) {
250       size*=((array_bound*)modifier_ptr->array_ptr[i]->entry_ptr)->upperbound+1;
251     }
252     return size*getsize(modifier_ptr->target_ptr);
253   }
254   case DW_TAG_const_type:
255     {
256       consttype * ctype_ptr=(consttype*)type->entry_ptr;
257       return getsize(ctype_ptr->target_ptr);
258     }
259     break;
260   case DW_TAG_base_type: {
261     base_type *base=(base_type*)type->entry_ptr;
262     return base->byte_size;
263   }
264   case DW_TAG_pointer_type: {
265     return 4;
266   }
267   case DW_TAG_union_type: 
268   case DW_TAG_structure_type: {
269     collection_type *ctype=(collection_type*)type->entry_ptr;
270     return ctype->byte_size;
271   }
272   case DW_TAG_subroutine_type: {
273     return 4;
274   }
275   case DW_TAG_typedef: 
276     {
277       tdef * tdef_ptr=(tdef*)type->entry_ptr;
278       return getsize(tdef_ptr->target_ptr);
279     }
280     break;
281
282   default:
283     return 0;
284   }
285 }
286
287 char * printname(dwarf_entry * type,int op) {
288   if (type==NULL) {
289     if (op==GETTYPE)
290       return NULL;
291   }
292
293   switch(type->tag_name) {
294   case DW_TAG_enumeration_type:
295     if (op==GETTYPE)
296       return "int";
297     break;
298   case DW_TAG_array_type: {
299     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
300     if (op==GETTYPE) {
301         char *typename=printname(modifier_ptr->target_ptr,op);
302         return typename;
303     } else if (op==POSTNAME) {
304       int i;
305       int size=1;
306       char *typename=printname(modifier_ptr->target_ptr,op);
307       char *newptr=(char *)malloc(200);
308       for(i=0;i<modifier_ptr->num_array;i++) {
309         size*=((array_bound*)modifier_ptr->array_ptr[i]->entry_ptr)->upperbound+1;
310       }
311       sprintf(newptr,"%s[%ld]",typename,size);
312       return newptr;
313     }
314   }
315     break;
316   case DW_TAG_const_type:
317     {
318       consttype * ctype_ptr=(consttype*)type->entry_ptr;
319       if (op==GETTYPE) {
320         char *typename=printname(ctype_ptr->target_ptr,op);
321         return typename;
322       }
323     }
324     break;
325   case DW_TAG_subroutine_type: {
326     return "void";
327   }
328   case DW_TAG_typedef: 
329     {
330       tdef * tdef_ptr=(tdef*)type->entry_ptr;
331       if (op==GETTYPE) {
332         char *typename=printname(tdef_ptr->target_ptr,op);
333         return typename;
334       }
335     }
336     break;
337   case DW_TAG_base_type: {
338     base_type *base=(base_type*)type->entry_ptr;
339     if (op==GETTYPE)
340       switch(base->byte_size) {
341       case 1:
342         return "byte";
343       case 2:
344         return "short";
345       case 4:
346         return "int";
347       default: {
348         char *m=(char*)malloc(100);
349         sprintf(m,"error%ld",base->byte_size);
350         return m;
351       }
352       }
353   }
354     break;
355   case DW_TAG_pointer_type: {
356     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
357     if (op==GETTYPE) {
358       if (modifier_ptr->target_ptr==NULL)
359         return "void *"; /* seems like a good guess */
360       {
361         char *typename=printname(modifier_ptr->target_ptr,op);
362         /* evil hack */
363         char *newptr=(char *)malloc(200);
364         sprintf(newptr,"%s *",typename);
365         return newptr;
366       }
367     }
368   }
369     break;
370   case DW_TAG_union_type:
371   case DW_TAG_structure_type: {
372     collection_type *ctype=(collection_type*)type->entry_ptr;
373     if (op==GETTYPE&&ctype->name==NULL&&assigntype) {
374       ctype->name=(char*)malloc(100);
375       sprintf(ctype->name,"TYPE%ld",typecount++);
376     }
377     if (op==GETTYPE)
378       return ctype->name;
379   }
380     break;
381   default:
382     if (op==GETTYPE) {
383       if (!assigntype)
384         return NULL;
385       else {
386         char * p=(char *)malloc(100);
387         sprintf(p,"0x%x",type->tag_name);
388         return p;
389       }
390     }
391   }
392   if (op==POSTNAME)
393     return "";
394   return "ERROR";
395 }
396
397