f56b08ab3f667aacc04750da1683d872277e7b9b
[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 #include <string.h>
25
26 #define GETTYPE 1
27 #define POSTNAME 2
28 #define GETJUSTTYPE 3
29
30 int FOLLOW_PTRS=0;
31 struct genhashtable * arrayt=NULL;
32 struct genhashtable * arraytype=NULL;
33 int process_elf_binary_data(char* filename);
34
35 char *rootfile=NULL;
36 char *arrayfile=NULL;
37
38 int main(int argc, char **argv) {
39   int i;
40   if (argc<2)
41     return 1;
42   if (argc>=3)
43     rootfile=argv[2];
44   for(i=3;i<argc;i++) {
45     if (strcmp("-r",argv[i])==0)
46       FOLLOW_PTRS=1;
47     if (strcmp("-a",argv[i])==0) {
48       i++;
49       arrayfile=argv[i];
50     }
51   }
52   process_elf_binary_data(argv[1]);
53   daikon_preprocess_entry_array();
54   return 0;
55 }
56
57 // Pre-processes global dwarf_entry_array in order to place
58 // the data in a form that can easily be turned into .decls
59 // and .dtrace files
60 void daikon_preprocess_entry_array()
61 {
62   initializeTypeArray();
63 }
64
65 int typecount=0;
66 int assigntype=0;
67 int entry_is_type(dwarf_entry *entry) {
68   if (entry->tag_name==DW_TAG_structure_type||
69       entry->tag_name==DW_TAG_union_type) {
70     collection_type* collection_ptr = (collection_type*)(entry->entry_ptr);
71     /*    if (collection_ptr->name==0&&assigntype) {
72       collection_ptr->name=(char*)malloc(100);
73       sprintf(collection_ptr->name,"TYPE%ld",typecount++);
74       }*/
75     return 1;
76   }
77   return 0;
78 }
79
80 int entry_is_valid_function(dwarf_entry *entry) {
81   if (tag_is_function(entry->tag_name)) {
82     function* funcPtr = (function*)(entry->entry_ptr);
83     if (funcPtr->start_pc != 0 && funcPtr->name != 0) {
84       return 1;
85     } else {
86 #ifdef SHOW_DEBUG
87       printf("Skipping invalid-looking function %s\n", funcPtr->name);
88 #endif
89     }
90   }
91   return 0;
92 }
93
94 struct valuepair {
95   int index;
96   int value;
97 };
98
99 void initializeTypeArray()
100 {
101   int i;
102   dwarf_entry * cur_entry;
103   struct genhashtable * ght=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
104   struct genhashtable * sht=NULL;
105
106   if (rootfile!=NULL) {
107     char buf[512];
108     char a;
109     int fd=open(rootfile,O_RDONLY);
110     int offset=0;
111     sht=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
112     while(1) {
113       if (read(fd,&a,1)>0) {
114         if (a!=13&&a!=10)
115           buf[offset++]=a;
116       } else
117           break;
118       if (offset>0&&(a==13||a==10)) {
119         buf[offset++]=0;
120         {
121           char *str=copystr(buf);
122           genputtable(sht,str,str);
123         }
124         offset=0;
125       }
126     }
127   }
128
129   if (arrayfile!=NULL) {
130     char buf[512];
131     char sizebuf[512];
132     char a;
133     int fd=open(arrayfile,O_RDONLY);
134     int offset=0;
135     int readmore=1;
136     int state=0;
137     arrayt=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
138     arraytype=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
139     while(readmore) {
140       if (read(fd,&a,1)<=0)
141         readmore=0;
142       if (readmore) {
143         if (a==' ') {
144           state=1;
145           buf[offset]=0;
146           offset=0;
147         } else if (a!=13&&a!=10) {
148           if (state==0)
149             buf[offset++]=a;
150           else
151             sizebuf[offset++]=a;
152         }
153       }
154       if ((state==1)&&offset>0&&(a==13||a==10||!readmore)) {
155         state=0;
156         sizebuf[offset]=0;
157         {
158           char *str=copystr(buf);
159           char *sizestr=copystr(sizebuf);
160           genputtable(arrayt,str,sizestr);
161         }
162         offset=0;
163       }
164     }
165   }
166
167   for (i = 0; i < dwarf_entry_array_size; i++)
168     {
169       cur_entry = &dwarf_entry_array[i];
170       if (entry_is_type(cur_entry))
171         {
172           collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr);
173           int j=0;
174           int offset=0;
175           int value=0;
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               value++;
180             } else {
181               member * member_ptr=(member *)entry->entry_ptr;
182               char *name=member_ptr->name;
183               dwarf_entry *type=member_ptr->type_ptr;
184               char *typestr=printname(type,GETTYPE);
185               char *poststr=printname(type,POSTNAME);
186
187               if (typestr!=NULL)
188                 value++;
189             }
190           }
191           if (collection_ptr->name!=NULL) {
192             struct valuepair *vp=NULL;
193             if (gencontains(ght,collection_ptr->name))
194               vp=(struct valuepair *)gengettable(ght,collection_ptr->name);
195             if (vp==NULL||vp->value<value) {
196               if (vp==NULL) {
197                 vp=(struct valuepair*)calloc(1,sizeof(struct valuepair));
198                 genputtable(ght,collection_ptr->name,vp);
199               }
200               vp->value=value;
201               vp->index=i;
202             }
203           }
204         }
205     }
206
207   assigntype=1;
208   if (sht!=NULL) {
209     int repeat=1;
210     while(repeat) {
211       repeat=0;
212       for (i = 0; i < dwarf_entry_array_size; i++) {
213         cur_entry = &dwarf_entry_array[i];
214         if (entry_is_type(cur_entry)) {
215           collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr);
216           int j=0;
217           int offset=0;
218           int value=0;
219
220           if (!gencontains(sht,collection_ptr->name))
221             continue;
222           if (gencontains(ght,collection_ptr->name)) {
223             struct valuepair *vp=(struct valuepair*)gengettable(ght,collection_ptr->name);
224             if (vp->index!=i)
225               continue;
226           }
227
228           for(j=0;j<collection_ptr->num_members;j++) {
229             dwarf_entry *entry=collection_ptr->members[j];
230             if (entry->tag_name==DW_TAG_inheritance) {
231               inherit *in_ptr=(inherit*)collection_ptr->members[j]->entry_ptr;
232               dwarf_entry *typeptr=in_ptr->target_ptr;
233               collection_type* sub_ptr = (collection_type*)(typeptr->entry_ptr);
234               if (!gencontains(sht,sub_ptr->name)) {
235                 repeat=1;
236                 genputtable(sht,sub_ptr->name,sub_ptr->name);
237               }
238             } else {
239               member * member_ptr=(member *)entry->entry_ptr;
240               char *name=member_ptr->name;
241               dwarf_entry *type=member_ptr->type_ptr;
242               char *typestr=printname(type,GETJUSTTYPE);
243               if (typestr!=NULL&&!gencontains(sht,typestr)) {
244                 repeat=1;
245                 genputtable(sht,typestr,typestr);
246               }
247             }
248           }
249         }
250       }
251     }
252   }
253
254
255   for (i = 0; i < dwarf_entry_array_size; i++)
256     {
257       cur_entry = &dwarf_entry_array[i];
258       if (entry_is_type(cur_entry))
259         {
260           collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr);
261           int j=0;
262           int offset=0;
263           if (collection_ptr->name==NULL)
264             continue;
265           if (sht!=NULL&&!gencontains(sht,collection_ptr->name))
266             continue;
267           if (gencontains(ght,collection_ptr->name)) {
268             struct valuepair *vp=(struct valuepair*)gengettable(ght,collection_ptr->name);
269             if (vp->index!=i)
270               continue;
271           }
272           j=0;
273           printf("structure %s ",collection_ptr->name);
274
275           while(j<collection_ptr->num_members&&
276                 collection_ptr->members[j]->tag_name==DW_TAG_inheritance) {
277             inherit *in_ptr=(inherit*)collection_ptr->members[j]->entry_ptr;
278             dwarf_entry *typeptr=in_ptr->target_ptr;
279             collection_type* sub_ptr = (collection_type*)(typeptr->entry_ptr);
280             if (j==0)
281               printf("subclass of ");
282             else
283               printf(", ");
284             printf("%s ",sub_ptr->name);
285             j++;
286           }
287           printf("{ \n");
288
289           for(j=0;j<collection_ptr->num_members;j++) {
290             dwarf_entry *entry=collection_ptr->members[j];
291             if (entry->tag_name==DW_TAG_inheritance) {
292               inherit * inherit_ptr=(inherit *)entry->entry_ptr;
293               if (inherit_ptr->data_member_location>offset) {
294                 printf("   reserved byte[%ld];\n",inherit_ptr->data_member_location-offset);
295                 offset=inherit_ptr->data_member_location;
296               }
297               {
298                 dwarf_entry *type=inherit_ptr->target_ptr;
299                 collection_type *c_ptr=(collection_type*)type->entry_ptr;
300                 offset+=printtype(c_ptr,ght);
301               }
302             } else {
303               member * member_ptr=(member *)entry->entry_ptr;
304               char *name=member_ptr->name;
305               dwarf_entry *type=member_ptr->type_ptr;
306               char *typestr=printname(type,GETTYPE);
307               char *poststr=printname(type,POSTNAME);
308               char *newname=NULL;
309               if (member_ptr->data_member_location>offset) {
310                 printf("   reserved byte[%ld];\n",member_ptr->data_member_location-offset);
311                 offset=member_ptr->data_member_location;
312               }
313               offset+=getsize(type);
314               newname=escapestr(name);
315               {
316                 char buf[512];
317                 char *dtype;
318                 sprintf(buf, "%s.%s\0", collection_ptr->name,newname);
319                 if (arrayt!=NULL&&gencontains(arrayt, &buf)) {
320                   genputtable(arraytype, copystr(buf), typestr);
321                   dtype=deref(typestr);
322                   printf("   %s_array * %s%s;\n",dtype,newname,poststr);
323                   free(dtype);
324                 } else
325                   printf("   %s %s%s;\n",typestr,newname,poststr);
326               }
327               free(newname);
328             }
329           }
330           if (offset<collection_ptr->byte_size)
331             printf("   reserved byte[%ld];\n",collection_ptr->byte_size-offset);
332           printf("}\n\n");
333         }
334     }
335   if (arrayt!=NULL) {
336     struct geniterator * gi=gengetiterator(arrayt);
337     while(1) {
338       char * str=(char *)gennext(gi);
339       char *size=NULL;
340       char *typestr=NULL;
341       if (str==NULL)
342         break;
343
344       size=(char *)gengettable(arrayt,str);
345       typestr=deref((char *)gengettable(arraytype,str));
346
347       printf("structure %s_array {\n",typestr);
348       printf("  %s elem[%s];\n",typestr,size);
349       printf("}\n");
350       free(typestr);
351     }
352     genfreeiterator(gi);
353   }
354
355 }
356
357 int printtype(collection_type *collection_ptr,struct genhashtable *ght)
358 {
359   int j=0;
360   int offset=0;
361   int value=0;
362
363   struct valuepair *vp=NULL;
364   if (gencontains(ght,collection_ptr->name))
365     vp=(struct valuepair *)gengettable(ght,collection_ptr->name);
366   if (vp!=NULL)
367     collection_ptr=(collection_type*) dwarf_entry_array[vp->index].entry_ptr;
368
369   for(j=0;j<collection_ptr->num_members;j++) {
370     dwarf_entry *entry=collection_ptr->members[j];
371     if (entry->tag_name==DW_TAG_inheritance) {
372       inherit * inherit_ptr=(inherit *)entry->entry_ptr;
373       if (inherit_ptr->data_member_location>offset) {
374         printf("   reserved byte[%ld];\n",inherit_ptr->data_member_location-offset);
375         offset=inherit_ptr->data_member_location;
376       }
377
378       {
379         dwarf_entry *type=inherit_ptr->target_ptr;
380         collection_type *c_ptr=(collection_type*)type->entry_ptr;
381         offset+=printtype(c_ptr,ght);
382       }
383     } else {
384       member * member_ptr=(member *)entry->entry_ptr;
385       char *name=member_ptr->name;
386       char *newname=NULL;
387       dwarf_entry *type=member_ptr->type_ptr;
388       char *typestr=printname(type,GETTYPE);
389       char *poststr=printname(type,POSTNAME);
390       if (member_ptr->data_member_location>offset) {
391         printf("   reserved byte[%ld];\n",member_ptr->data_member_location-offset);
392         offset=member_ptr->data_member_location;
393       }
394       offset+=getsize(type);
395
396       newname=escapestr(name);
397       {
398         char buf[512];
399         char *dtype;
400         sprintf(buf, "%s.%s\0", collection_ptr->name,newname);
401         if (arrayt!=NULL&&gencontains(arrayt, &buf)) {
402           genputtable(arraytype, buf, typestr);
403           dtype=deref(typestr);
404           printf("   %s_array * %s%s;\n",dtype,newname,poststr);
405           free(dtype);
406         } else
407           printf("   %s %s%s;\n",typestr,newname,poststr);
408       }
409       free(newname);
410     }
411   }
412   return offset;
413 }
414
415 int getsize(dwarf_entry *type) {
416   if (type==NULL)
417     return 0;
418   switch(type->tag_name) {
419   case DW_TAG_enumeration_type:
420     return 4;
421   case DW_TAG_array_type: {
422     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
423     int size=1;
424     int i;
425     for(i=0;i<modifier_ptr->num_array;i++) {
426       size*=((array_bound*)modifier_ptr->array_ptr[i]->entry_ptr)->upperbound+1;
427     }
428     return size*getsize(modifier_ptr->target_ptr);
429   }
430   case DW_TAG_const_type:
431     {
432       consttype * ctype_ptr=(consttype*)type->entry_ptr;
433       return getsize(ctype_ptr->target_ptr);
434     }
435     break;
436   case DW_TAG_base_type: {
437     base_type *base=(base_type*)type->entry_ptr;
438     return base->byte_size;
439   }
440   case DW_TAG_pointer_type: {
441     return 4;
442   }
443   case DW_TAG_union_type:
444   case DW_TAG_structure_type: {
445     collection_type *ctype=(collection_type*)type->entry_ptr;
446     return ctype->byte_size;
447   }
448   case DW_TAG_subroutine_type: {
449     return 4;
450   }
451   case DW_TAG_typedef:
452     {
453       tdef * tdef_ptr=(tdef*)type->entry_ptr;
454       return getsize(tdef_ptr->target_ptr);
455     }
456     break;
457
458   default:
459     return 0;
460   }
461 }
462
463 char * deref(char *name) {
464   char *str=copystr(name);
465   char *initstr=str;
466   for(;(*str)!=0;str++)
467     ;
468   for(;(str!=initstr)&&((*str)!='*');str--)
469     ;
470   if ((*str)=='*') {
471     (*str)=0;
472     str--;
473     for(;(str!=initstr)&&((*str)==' ');str--)
474       (*str)=0;
475   }
476   return initstr;
477 }
478
479 char * printname(dwarf_entry * type,int op) {
480   if (type==NULL) {
481     if (op==GETTYPE||op==GETJUSTTYPE)
482       return NULL;
483   }
484
485   switch(type->tag_name) {
486   case DW_TAG_enumeration_type:
487     if (op==GETTYPE)
488       return "int";
489     break;
490   case DW_TAG_array_type: {
491     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
492     if (op==GETTYPE||op==GETJUSTTYPE) {
493         char *typename=printname(modifier_ptr->target_ptr,op);
494         return typename;
495     } else if (op==POSTNAME) {
496       int i;
497       int size=1;
498       char *typename=printname(modifier_ptr->target_ptr,op);
499       char *newptr=(char *)malloc(200);
500       for(i=0;i<modifier_ptr->num_array;i++) {
501         size*=((array_bound*)modifier_ptr->array_ptr[i]->entry_ptr)->upperbound+1;
502       }
503       sprintf(newptr,"%s[%ld]",typename,size);
504       return newptr;
505     }
506   }
507     break;
508   case DW_TAG_const_type:
509     {
510       consttype * ctype_ptr=(consttype*)type->entry_ptr;
511       if (op==GETTYPE||op==GETJUSTTYPE) {
512         char *typename=printname(ctype_ptr->target_ptr,op);
513         return typename;
514       }
515     }
516     break;
517   case DW_TAG_subroutine_type: {
518     return "void";
519   }
520   case DW_TAG_typedef:
521     {
522       tdef * tdef_ptr=(tdef*)type->entry_ptr;
523       if (op==GETTYPE||op==GETJUSTTYPE) {
524         if (tdef_ptr->target_ptr==NULL)
525           return tdef_ptr->name;
526         if (tdef_ptr->target_ptr->tag_name==DW_TAG_union_type||
527             tdef_ptr->target_ptr->tag_name==DW_TAG_structure_type) {
528           collection_type *ctype=(collection_type*)tdef_ptr->target_ptr->entry_ptr;
529           if (ctype->name!=NULL)
530             return ctype->name;
531           ctype->name=tdef_ptr->name;
532           return tdef_ptr->name;
533         }
534         char *typename=printname(tdef_ptr->target_ptr,op);
535         return typename;
536       }
537     }
538     break;
539   case DW_TAG_base_type: {
540     base_type *base=(base_type*)type->entry_ptr;
541     if (op==GETTYPE)
542       switch(base->byte_size) {
543       case 1:
544         return "byte";
545       case 2:
546         return "short";
547       case 4:
548         return "int";
549       default: {
550         char *m=(char*)malloc(100);
551         sprintf(m,"error%ld",base->byte_size);
552         return m;
553       }
554       }
555   }
556     break;
557   case DW_TAG_pointer_type: {
558     modifier_type * modifier_ptr=(modifier_type*)type->entry_ptr;
559     if (op==GETTYPE) {
560       if (modifier_ptr->target_ptr==NULL)
561         return "void *"; /* seems like a good guess */
562       {
563         char *typename=printname(modifier_ptr->target_ptr,op);
564         /* evil hack */
565         char *newptr=(char *)malloc(200);
566         sprintf(newptr,"%s *",typename);
567         return newptr;
568       }
569     } else if (op==GETJUSTTYPE) {
570       if (!FOLLOW_PTRS)
571         return NULL;
572
573       if (modifier_ptr->target_ptr==NULL)
574         return NULL;
575       {
576         char *typename=printname(modifier_ptr->target_ptr,op);
577         return typename;
578       }
579     }
580   }
581     break;
582   case DW_TAG_union_type:
583   case DW_TAG_structure_type: {
584     collection_type *ctype=(collection_type*)type->entry_ptr;
585     if (op==GETTYPE&&ctype->name==NULL&&assigntype) {
586       char *newb=(char *)malloc(1000);
587       int newchars=0;
588       int i;
589       ctype->name=newb;
590       newchars=sprintf(newb,"unnamed_",type->ID);
591       newb+=newchars;
592       for(i=0;i<ctype->num_members;i++) {
593         dwarf_entry * de=ctype->members[i];
594         if (de->tag_name==DW_TAG_member) {
595           member * me=(member *)de->entry_ptr;
596           newchars=sprintf(newb,"%s",me->name);
597           newb+=newchars;
598         }
599       }
600     }
601     if (op==GETTYPE)
602       return ctype->name;
603     if (op==GETJUSTTYPE&&ctype->name==NULL&&assigntype) {
604       char *newb=(char *)malloc(1000);
605       int newchars=0;
606       int i;
607       ctype->name=newb;
608       newchars=sprintf(newb,"unnamed_",type->ID);
609       newb+=newchars;
610       for(i=0;i<ctype->num_members;i++) {
611         dwarf_entry * de=ctype->members[i];
612         if (de->tag_name==DW_TAG_member) {
613           member * me=(member *)de->entry_ptr;
614           newchars=sprintf(newb,"%s",me->name);
615           newb+=newchars;
616         }
617       }
618     }
619     if (op==GETJUSTTYPE)
620       return ctype->name;
621
622   }
623     break;
624   default:
625     if (op==GETTYPE) {
626       if (!assigntype)
627         return NULL;
628       else {
629         char * p=(char *)malloc(100);
630         sprintf(p,"0x%x",type->tag_name);
631         return p;
632       }
633     }
634   }
635   if (op==POSTNAME)
636     return "";
637   if (op==GETJUSTTYPE)
638     return NULL;
639   return "ERROR";
640 }