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