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