void printrolechanges(struct heap_state *heap, struct rolemethod *rm) { struct genhashtable *rolechanges=rm->rolechanges; struct geniterator *it=gengetiterator(rolechanges); while(1) { struct rolechangesum *rcs=(struct rolechangesum *)gennext(it); struct rolechangeheader *rch; struct rolechangepath *rcp; if (rcs==NULL) break; fprintf(heap->methodfile, "%s -> %s ",rcs->origrole, rcs->newrole); rch=(struct rolechangeheader *)gengettable(rolechanges, rcs); rcp=rch->rcp; while(rcp!=NULL) { fprintf(heap->methodfile," Path: "); if (rcp->exact==rm->numberofcalls) fprintf(heap->methodfile,"Exact "); if (rcp->inner==2) fprintf(heap->methodfile,"Inner "); else if(rcp->inner==1) fprintf(heap->methodfile,"Maybe Inner "); printeffectregexpr(heap,rcp->expr); fprintf(heap->methodfile,"\n"); rcp=rcp->next; } } genfreeiterator(it); }
int printtype(collection_type *collection_ptr,struct genhashtable *ght) { int j=0; int offset=0; int value=0; struct valuepair *vp=NULL; if (gencontains(ght,collection_ptr->name)) vp=(struct valuepair *)gengettable(ght,collection_ptr->name); if (vp!=NULL) collection_ptr=(collection_type*) dwarf_entry_array[vp->index].entry_ptr; for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { inherit * inherit_ptr=(inherit *)entry->entry_ptr; if (inherit_ptr->data_member_location>offset) { printf(" reserved byte[%ld];\n",inherit_ptr->data_member_location-offset); offset=inherit_ptr->data_member_location; } { dwarf_entry *type=inherit_ptr->target_ptr; collection_type *c_ptr=(collection_type*)type->entry_ptr; offset+=printtype(c_ptr,ght); } } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; char *newname=NULL; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETTYPE); char *poststr=printname(type,POSTNAME); if (member_ptr->data_member_location>offset) { printf(" reserved byte[%ld];\n",member_ptr->data_member_location-offset); offset=member_ptr->data_member_location; } offset+=getsize(type); newname=escapestr(name); { char buf[512]; char *dtype; sprintf(buf, "%s.%s\0", collection_ptr->name,newname); if (arrayt!=NULL&&gencontains(arrayt, &buf)) { genputtable(arraytype, buf, typestr); dtype=deref(typestr); printf(" %s_array * %s%s;\n",dtype,newname,poststr); free(dtype); } else printf(" %s %s%s;\n",typestr,newname,poststr); } free(newname); } } return offset; }
struct rolemethod * methodaddtable(struct heap_state * heap , struct rolemethod *method) { if (gencontains(heap->methodtable, method)) { struct rolemethod * retval=gengettable(heap->methodtable, method); methodfree(method); return retval; } else { genputtable(heap->methodtable, method,method); return method; } }
void dotrolemethod(struct genhashtable * htable, struct genhashtable *reverseroletable, struct rolemethod *rm) { int i; struct geniterator * it=gengetiterator(rm->rolechanges); while(1) { struct rolechangesum * rcs=(struct rolechangesum *) gennext(it); struct role* role; char buf[600]; struct rolechangeheader *rch=NULL; if (rcs==NULL) break; rch=(struct rolechangeheader *)gengettable(rm->rolechanges,rcs); if (rch->inner) { role=(struct role *)gengettable(reverseroletable, rcs->origrole); sprintf(buf,"%s.%s\\n%s", rm->methodname->classname->classname, rm->methodname->methodname, rm->methodname->signature); addtransition(htable, role->class, rcs->origrole, buf ,rcs->newrole,1); } }
void outputinfo(struct namer* namer, struct genhashtable *calltable, struct genhashtable *statictable) { FILE *classfile=fopen("fs-class","w"); FILE *methodfile=fopen("fs-method","w"); FILE *fieldfile=fopen("fs-field","w"); FILE *callgraphfile=fopen("fs-callgraph","w"); struct geniterator *it=gengetiterator(namer->classtable); while(1) { struct classname *cn=gennext(it); if (cn==NULL) break; fprintf(classfile, "%s ", cn->classname); } genfreeiterator(it); it=gengetiterator(namer->methodtable); while(1) { struct methodname *mn=gennext(it); if (mn==NULL) break; fprintf(methodfile, "%s.%s%s %d ", mn->classname->classname, mn->methodname, mn->signature, *((int *) gengettable(statictable, mn))); } genfreeiterator(it); it=gengetiterator(namer->fieldtable); while(1) { struct fieldname *fn=gennext(it); if (fn==NULL) break; fprintf(fieldfile, "%s %s %s ", fn->classname->classname, fn->fieldname, fn->fielddesc->fielddesc); } genfreeiterator(it); it=gengetiterator(calltable); while(1) { struct methodname *mn=gennext(it); struct methodchain *mc=NULL; if (mn==NULL) break; mc=gengettable(calltable, mn); while(mc!=NULL) { fprintf(callgraphfile, "%s.%s%s ", mn->classname->classname, mn->methodname, mn->signature); fprintf(callgraphfile, "%s.%s%s ", mc->method->classname->classname, mc->method->methodname, mc->method->signature); mc=mc->caller; } } genfreeiterator(it); fclose(callgraphfile); fclose(classfile); fclose(methodfile); fclose(fieldfile); }
struct referencelist * calculatedominators(struct genhashtable * dommapping,struct heap_object *ho) { struct referencelist *rl=ho->rl; struct referencelist *dominators=NULL; while(rl!=NULL) { if ((*((int*)gengettable(dommapping, (rl->lv!=NULL)?((void *)rl->lv):((void *)rl->gl))))==1) { struct referencelist * tmpptr=(struct referencelist *)calloc(1, sizeof(struct referencelist)); tmpptr->lv=rl->lv; tmpptr->gl=rl->gl; tmpptr->next=dominators; dominators=tmpptr; } rl=rl->next; } return dominators; }
// We will utilize this information to pause the target program at // function entrances. For further information on how Fjalar // determines the address for function entrances please see the // "HANDLING FUNCTION ENTRY" comment below. This is called from // mc_translate.c. void handle_possible_entry(MCEnv* mce, Addr64 addr, IRSB* bb_orig) { // REMEMBER TO ALWAYS UPDATE THIS regardless of whether this is // truly a function entry so that handle_possible_exit() can work // properly: currentAddr = (Addr)addr; if(!fjalar_gcc3) { FunctionEntry *entry = gengettable(FunctionTable, (void *)(Addr)addr); if(entry) { find_entry_pt(bb_orig, entry); } } // We're not splitting entry handling based on GCC version. // for GCC 3.x we're going to enter at the instruction // corresponding to the first line of code in a function // (f->entryPC in Fjalar's terms) // For GCC 4.x we're going to use a special heuristic for // determining the instruction to enter at. See comment // "HANDLING FUNCTION ENTRY" above find_entry_pt() if(fjalar_gcc3) { /* If this is the very first instruction in the function, add a call to the prime_function helper. */ handle_possible_entry_func(mce, addr, FunctionTable, "prime_function", &prime_function); /* If this is the first instruction in the function after the prolog (not exclusive with the condition above), add a call to the enter_function helper. */ handle_possible_entry_func(mce, addr, FunctionTable_by_entryPC, "enter_function", &enter_function); } else { handle_possible_entry_func(mce, addr, FunctionTable_by_endOfBb, "enter_function", &enter_function); } }
void mergerolechanges(struct heap_state *heap) { struct geniterator *it=gengetiterator(heap->methodlist->rolechangetable); while(1) { struct rolechange *rc=(struct rolechange *)gennext(it); struct method *method=heap->methodlist; int inner=2; if (rc==NULL) break; while(method!=NULL) { struct rolemethod *rm=method->rm; struct genhashtable * rolechanges=rm->rolechanges; struct rolechangesum *rcs=(struct rolechangesum *)calloc(1,sizeof(struct rolechangesum)); struct rolechangeheader *rch; struct effectregexpr *ere=NULL; struct rolechangepath *rcp; if (!(heap->options&OPTION_NORCEXPR)) ere=buildregexpr(method->pathtable, rc->uid); rcs->origrole=copystr(rc->origrole); rcs->newrole=copystr(rc->newrole); if (!gencontains(rolechanges, rcs)) { rch=(struct rolechangeheader *)calloc(1,sizeof(struct rolechangeheader)); if (inner) rch->inner=1; genputtable(rolechanges,rcs,rch); } else { rch=(struct rolechangeheader *) gengettable(rolechanges,rcs); if (inner) rch->inner=1; free(rcs->origrole); free(rcs->newrole); free(rcs); } /* rch points to appropriate rolechangeheader */ /* ere points to our regular expression */ rcp=rch->rcp; if (!(heap->options&OPTION_NORCEXPR)) { while(rcp!=NULL) { struct effectregexpr *ere2=rcp->expr; struct effectregexpr *erem=mergeeffectregexpr(ere,ere2); if (erem!=NULL) { rcp->expr=erem; if ((rcp->inner||inner)&&((inner==0)||(rcp->inner==0))) { rcp->inner=1; } /*Update count */ if ((rcp->exact+1)==rm->numberofcalls) rcp->exact=rm->numberofcalls; if (rcp->exact<rm->numberofcalls) rcp->exact=0; freeeffectregexpr(ere2); freeeffectregexpr(ere); break; } rcp=rcp->next; } if(rcp==NULL) { /* Couldn't merge in */ struct rolechangepath *rcp2=(struct rolechangepath *)calloc(1, sizeof(struct rolechangepath)); rcp2->expr=ere; if(rm->numberofcalls==1) rcp2->exact=1; rcp2->next=rch->rcp; rcp2->inner=inner; rch->rcp=rcp2; } } method=method->caller; inner=0; } free(rc->origrole); free(rc->newrole); free(rc); } genfreeiterator(it); genfreehashtable(heap->methodlist->rolechangetable); heap->methodlist->rolechangetable=NULL; }
void enter_function(FunctionEntry* f) { FunctionExecutionState* newEntry; extern FunctionExecutionState* curFunctionExecutionStatePtr; ThreadId tid = VG_(get_running_tid)(); Addr stack_ptr= VG_(get_SP)(tid); Addr frame_ptr = 0; /* E.g., %ebp */ int local_stack, size; FJALAR_DPRINTF("[enter_function] startPC is: %x, entryPC is: %x, cu_base: %p\n", (UInt)f->startPC, (UInt)f->entryPC,(void *)f->cuBase); FJALAR_DPRINTF("Value of edi: %lx, esi: %lx, edx: %lx, ecx: %lx\n", (long)VG_(get_xDI)(tid), (long)VG_(get_xSI)(tid), (long)VG_(get_xDX)(tid), (long)VG_(get_xCX)(tid)); // Determine the frame pointer for this function using DWARF // location lists. This is a "virtual frame pointer" in that it is // used by the DWARF debugging information in providing the address // of formal parameters and local variables, but it may or may not // correspond to an actual frame pointer in the architecture. For // example: This will not always return %xbp on x86{-64} platforms // and *SHOULD*(untested) work with the -fomit-frame-pointer flag in GCC // // It usually points just above the function return address. The // .debug_loc info tells how to find (calculate) the frame base // at any point in the program. (markro) if(f->locList) { Addr eip = f->entryPC; location_list *ll; eip = eip - f->cuBase; FJALAR_DPRINTF("\tCurrent EIP is: %x\n", (UInt)eip); FJALAR_DPRINTF("\tLocation list based function(offset from base: %x). offset is %lu\n",(UInt)eip, f->locListOffset); if (gencontains(loc_list_map, (void *)f->locListOffset)) { ll = gengettable(loc_list_map, (void *)f->locListOffset); // (comment added 2009) // HACK. g++ and GCC handle location lists differently. GCC puts lists offsets // relative to the compilation unit, g++ uses the actual address. I'm going to // compare the location list ranges both to the cu_base offset, as well as // the function's entry point. This might break if there's every a case // where the compilation unit offset is a valid address in the program while(ll && !(((ll->begin <= eip) && (ll->end >= eip)) || ((ll->begin <= f->entryPC) && (ll->end >= f->entryPC)))) { FJALAR_DPRINTF("\tExamining loc list entry: %x - %x - %x\n", (UInt)ll->offset, (UInt)ll->begin, (UInt)ll->end); ll = ll->next; } if(ll) { FJALAR_DPRINTF("\tFound location list entry, finding location corresponding to dwarf #: %d with offset: %lld\n", ll->atom, ll->atom_offset); // (comment added 2013) // It turns out it might not be just the contents of a register. Some // 32bit x86 code does some tricky stack alignment and has to save a // pointer to the orginal stack frame. This means we get passed a // DW_OP_deref instead of a DW_OP_breg. The tricky bit is we don't // want to go back to that address because it probably won't be equal // to the local frame pointer due to the stack alignment. So the HACK // is to just assume the frame pointer is at EBP+8 like normal. (markro) if (ll->atom == DW_OP_deref) { ll->atom = DW_OP_breg5; ll->atom_offset = 8; } if(get_reg[ll->atom - DW_OP_breg0]) { frame_ptr = (*get_reg[ll->atom - DW_OP_breg0])(tid) + ll->atom_offset; } } } } // This is the old code to determine the frame. Fallback to it if we don't // have a frame_base from the location_list path. This should keep GCC 3 working // fine. if(frame_ptr == 0) { if (f != primed_function) { printf("No location list or frame pointer giving up(Mangled name: %s)\n", f->mangled_name); return; } primed_function = 0; if (f->entryPC != f->startPC) { /* Prolog has run, so just use the real %ebp */ frame_ptr = VG_(get_FP)(VG_(get_running_tid)()); } else { FJALAR_DPRINTF("Faking prolog\n"); /* Don't know about prolog, so fake its effects, given we know that ESP hasn't yet been modified: */ // Looks like we never get here for amd64 as -4 is clearly wrong. (10/26/2015) frame_ptr = stack_ptr - 4; } } FJALAR_DPRINTF("\tEnter function: %s - StartPC: %p, EntryPC: %p, frame_ptr: %p\n", f->fjalar_name, (void *)f->startPC, (void *)f->entryPC, (void *)frame_ptr); newEntry = fnStackPush(tid); newEntry->func = f; newEntry->func->FP = frame_ptr; newEntry->func->lowestSP = stack_ptr; newEntry->FP = frame_ptr; newEntry->lowSP = stack_ptr; newEntry->lowestSP = stack_ptr; newEntry->xAX = 0; newEntry->xDX = 0; newEntry->FPU = 0; newEntry->invocation_nonce = cur_nonce++; newEntry->func->nonce = newEntry->invocation_nonce; // FJALAR VIRTUAL STACK // Fjalar maintains a virtual stack for invocation a function. This // allows Fjalar to provide tools with unaltered values of formal // parameters at both function entry and exit, regardless of whether // or not the compiler chooses to use the original formal parameter // locations as storage for local values. // Initialize virtual stack and copy parts of the Valgrind stack // into that virtual stack local_stack = frame_ptr - stack_ptr + VG_STACK_REDZONE_SZB; /* in our frame */ tl_assert(local_stack >= 0); FJALAR_DPRINTF("frame_ptr: %p, stack_ptr: %p, VG_STACK_REDZONE: %d\n", (void *)frame_ptr, (void *)stack_ptr, VG_STACK_REDZONE_SZB); // The virtual stack consists of: // (1) local_stack: the entirety of the function's local stack (the // memory between the frame pointer and the stack pointer (including the extra // redzone) // (2) The return pointer, which is sizeof(Addr) bytes // (3) The saved base pointer, which is sizeof(Addr) bytes // (4) All formal parameters passed on the stack, which is // f->formalParamStackByteSize bytes // Let's be conservative in how much we copy over to the Virtual stack. Due to the // stack alignment operations in main, we may need as much as 16 bytes over the above. size = local_stack + f->formalParamStackByteSize + sizeof(Addr)*2 + 32;/* plus stuff in caller's*/ FJALAR_DPRINTF("local_stack: %p, arg_size: %x\n", (void *)(frame_ptr - f->formalParamLowerStackByteSize), f->formalParamLowerStackByteSize); int delta = stack_ptr - (frame_ptr - f->formalParamLowerStackByteSize); if (delta < 0 ) delta = 0; tl_assert(size >= 0); if (size != 0) { newEntry->virtualStack = VG_(calloc)("fjalar_main.c: enter_func", size, sizeof(char)); newEntry->virtualStackByteSize = size; newEntry->virtualStackFPOffset = local_stack; clear_all_tags_in_range(stack_ptr - VG_STACK_REDZONE_SZB, VG_STACK_REDZONE_SZB - delta); VG_(memcpy)(newEntry->virtualStack, (char*)stack_ptr - VG_STACK_REDZONE_SZB, size); // VERY IMPORTANT!!! Copy all the A & V bits over the real stack to // virtualStack!!! (As a consequence, this copies over the tags // as well - look in mc_main.c). Note that the way do this means // that the copy is now guest-accessible, if they guessed the // VG_(calloc)ed address, which is a bit weird. It would be more // elegant to copy the metadata to an inaccessible place, but that // would be more work. FJALAR_DPRINTF("Copying over stack [%p] -> [%p] %d bytes\n",(void *)(stack_ptr - VG_STACK_REDZONE_SZB), (void *)newEntry->virtualStack, size); mc_copy_address_range_state(stack_ptr - VG_STACK_REDZONE_SZB, (Addr)(newEntry->virtualStack), size); newEntry->func->guestStackStart = stack_ptr - VG_STACK_REDZONE_SZB; newEntry->func->guestStackEnd = newEntry->func->guestStackStart + size; newEntry->func->lowestVirtSP = (Addr)newEntry->virtualStack; } else { printf("Obtained a stack size of 0 for Function: %s. Aborting\n", f->fjalar_name); tl_assert(0); } // Do this AFTER initializing virtual stack and lowestSP curFunctionExecutionStatePtr = newEntry; fjalar_tool_handle_function_entrance(newEntry); }
// This inserts an IR Statement responsible for calling func // code before the instruction at addr is executed. This is primarily // used for inserting the call to enter_function on function entry. // It is also used for handling of 'function priming' for GCC 3 (see // comment above prime_function). The result of looking up addr in // table will be passed to func as it's only argument. This function // does nothing if it is unable to successfully look up addr in the // provided table. static void handle_possible_entry_func(MCEnv *mce, Addr64 addr, struct genhashtable *table, const char *func_name, entry_func func) { IRDirty *di; FunctionEntry *entry = gengettable(table, (void *)(Addr)addr); if(!entry) { return; } // If fjalar_trace_prog_pts_filename is on (we are using a ppt list // file), then DO NOT generate IR code to call helper functions for // functions whose name is NOT located in prog_pts_tree. It's faster // to filter them out at translation-time instead of run-time if (entry && (!fjalar_trace_prog_pts_filename || prog_pts_tree_entry_found(entry))) { UWord entry_w = (UWord)entry; di = unsafeIRDirty_0_N(1/*regparms*/, func_name, func, mkIRExprVec_1(IRExpr_Const(IRConst_UWord(entry_w)))); // For function entry, we are interested in observing the stack // and frame pointers so make sure that they're updated by setting // the proper annotations: entry->entryPC = addr; FJALAR_DPRINTF("Found a valid entry point at %x for\n", (UInt)addr); // We need all general purpose registers. di->nFxState = 9; vex_bzero(&di->fxState, sizeof(di->fxState)); di->fxState[0].fx = Ifx_Read; di->fxState[0].offset = mce->layout->offset_SP; di->fxState[0].size = mce->layout->sizeof_SP; di->fxState[1].fx = Ifx_Read; di->fxState[1].offset = mce->layout->offset_FP; di->fxState[1].size = mce->layout->sizeof_FP; di->fxState[2].fx = Ifx_Read; di->fxState[2].offset = mce->layout->offset_IP; di->fxState[2].size = mce->layout->sizeof_IP; di->fxState[3].fx = Ifx_Read; di->fxState[3].offset = mce->layout->offset_xAX; di->fxState[3].size = mce->layout->sizeof_xAX; di->fxState[4].fx = Ifx_Read; di->fxState[4].offset = mce->layout->offset_xBX; di->fxState[4].size = mce->layout->sizeof_xBX; di->fxState[5].fx = Ifx_Read; di->fxState[5].offset = mce->layout->offset_xCX; di->fxState[5].size = mce->layout->sizeof_xCX; di->fxState[6].fx = Ifx_Read; di->fxState[6].offset = mce->layout->offset_xDX; di->fxState[6].size = mce->layout->sizeof_xDX; di->fxState[7].fx = Ifx_Read; di->fxState[7].offset = mce->layout->offset_xSI; di->fxState[7].size = mce->layout->sizeof_xSI; di->fxState[8].fx = Ifx_Read; di->fxState[8].offset = mce->layout->offset_xDI; di->fxState[8].size = mce->layout->sizeof_xDI; stmt('V', mce, IRStmt_Dirty(di) ); } }
void initializeTypeArray() { int i; dwarf_entry * cur_entry; struct genhashtable * ght=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings); struct genhashtable * sht=NULL; if (rootfile!=NULL) { char buf[512]; char a; int fd=open(rootfile,O_RDONLY); int offset=0; sht=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings); while(1) { if (read(fd,&a,1)>0) { if (a!=13&&a!=10) buf[offset++]=a; } else break; if (offset>0&&(a==13||a==10)) { buf[offset++]=0; { char *str=copystr(buf); genputtable(sht,str,str); } offset=0; } } } if (arrayfile!=NULL) { char buf[512]; char sizebuf[512]; char a; int fd=open(arrayfile,O_RDONLY); int offset=0; int readmore=1; int state=0; arrayt=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings); arraytype=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings); while(readmore) { if (read(fd,&a,1)<=0) readmore=0; if (readmore) { if (a==' ') { state=1; buf[offset]=0; offset=0; } else if (a!=13&&a!=10) { if (state==0) buf[offset++]=a; else sizebuf[offset++]=a; } } if ((state==1)&&offset>0&&(a==13||a==10||!readmore)) { state=0; sizebuf[offset]=0; { char *str=copystr(buf); char *sizestr=copystr(sizebuf); genputtable(arrayt,str,sizestr); } offset=0; } } } /* Assign names */ for (i = 0; i < dwarf_entry_array_size; i++) { cur_entry = &dwarf_entry_array[i]; if (entry_is_type(cur_entry)) { collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr); int j=0; int offset=0; int value=0; for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { value++; } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETTYPE); char *poststr=printname(type,POSTNAME); if (typestr!=NULL) value++; } } } } for (i = 0; i < dwarf_entry_array_size; i++) { cur_entry = &dwarf_entry_array[i]; if (entry_is_type(cur_entry)) { collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr); int j=0; int offset=0; int value=0; for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { value++; } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETTYPE); char *poststr=printname(type,POSTNAME); if (typestr!=NULL) value++; } } if (collection_ptr->name!=NULL) { struct valuepair *vp=NULL; if (gencontains(ght,collection_ptr->name)) vp=(struct valuepair *)gengettable(ght,collection_ptr->name); if (vp==NULL||vp->value<value) { if (vp==NULL) { vp=(struct valuepair*)calloc(1,sizeof(struct valuepair)); genputtable(ght,collection_ptr->name,vp); } vp->value=value; vp->index=i; } } } } assigntype=1; if (sht!=NULL) { int repeat=1; while(repeat) { repeat=0; for (i = 0; i < dwarf_entry_array_size; i++) { cur_entry = &dwarf_entry_array[i]; if (entry_is_type(cur_entry)) { collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr); int j=0; int offset=0; int value=0; if (!gencontains(sht,collection_ptr->name)) continue; if (gencontains(ght,collection_ptr->name)) { struct valuepair *vp=(struct valuepair*)gengettable(ght,collection_ptr->name); if (vp->index!=i) continue; } for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { inherit *in_ptr=(inherit*)collection_ptr->members[j]->entry_ptr; dwarf_entry *typeptr=in_ptr->target_ptr; collection_type* sub_ptr = (collection_type*)(typeptr->entry_ptr); if (!gencontains(sht,sub_ptr->name)) { repeat=1; genputtable(sht,sub_ptr->name,sub_ptr->name); } } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETJUSTTYPE); if (typestr!=NULL&&!gencontains(sht,typestr)) { repeat=1; genputtable(sht,typestr,typestr); } } } } } } } for (i = 0; i < dwarf_entry_array_size; i++) { cur_entry = &dwarf_entry_array[i]; if (entry_is_type(cur_entry)) { collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr); int j=0; int offset=0; if (collection_ptr->name==NULL) continue; if (sht!=NULL&&!gencontains(sht,collection_ptr->name)) continue; if (gencontains(ght,collection_ptr->name)) { struct valuepair *vp=(struct valuepair*)gengettable(ght,collection_ptr->name); if (vp->index!=i) continue; } j=0; printf("structure %s ",collection_ptr->name); while(j<collection_ptr->num_members&& collection_ptr->members[j]->tag_name==DW_TAG_inheritance) { inherit *in_ptr=(inherit*)collection_ptr->members[j]->entry_ptr; dwarf_entry *typeptr=in_ptr->target_ptr; collection_type* sub_ptr = (collection_type*)(typeptr->entry_ptr); if (j==0) printf("subclass of "); else printf(", "); printf("%s ",sub_ptr->name); j++; } printf("{ \n"); for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { inherit * inherit_ptr=(inherit *)entry->entry_ptr; if (inherit_ptr->data_member_location>offset) { printf(" reserved byte[%ld];\n",inherit_ptr->data_member_location-offset); offset=inherit_ptr->data_member_location; } { dwarf_entry *type=inherit_ptr->target_ptr; collection_type *c_ptr=(collection_type*)type->entry_ptr; offset+=printtype(c_ptr,ght); } } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETTYPE); char *poststr=printname(type,POSTNAME); char *newname=NULL; if (member_ptr->data_member_location>offset) { printf(" reserved byte[%ld];\n",member_ptr->data_member_location-offset); offset=member_ptr->data_member_location; } offset+=getsize(type); newname=escapestr(name); { char buf[512]; char *dtype; sprintf(buf, "%s.%s\0", collection_ptr->name,newname); if (arrayt!=NULL&&gencontains(arrayt, &buf)) { genputtable(arraytype, copystr(buf), typestr); dtype=deref(typestr); printf(" %s_array * %s%s;\n",dtype,newname,poststr); free(dtype); } else printf(" %s %s%s;\n",typestr,newname,poststr); } free(newname); } } if (offset<collection_ptr->byte_size) printf(" reserved byte[%ld];\n",collection_ptr->byte_size-offset); printf("}\n\n"); } } if (arrayt!=NULL) { struct geniterator * gi=gengetiterator(arrayt); while(1) { char * str=(char *)gennext(gi); char *size=NULL; char *typestr=NULL; if (str==NULL) break; size=(char *)gengettable(arrayt,str); typestr=deref((char *)gengettable(arraytype,str)); printf("structure %s_array {\n",typestr); printf(" %s elem[%s];\n",typestr,size); printf("}\n"); free(typestr); } genfreeiterator(gi); } }
void fastscan() { struct methodchain *methodstack=NULL; struct namer *namer=allocatenamer(); struct genhashtable *calltable=genallocatehashtable((int (*)(void *)) &hashmethod, (int (*)(void *,void *)) &comparemethod); struct genhashtable *statictable=genallocatehashtable((int (*)(void *)) &hashmethod, (int (*)(void *,void *)) &comparemethod); while(1) { char *line=getline(); #ifdef DEBUG printf("------------------------------------------------------\n"); #endif if (line==0) { outputinfo(namer, calltable,statictable); return; } #ifdef DEBUG printf("[%s]\n",line); #endif switch(line[0]) { case 'C': break; case 'O': break; case 'N': { /* Natively created object...may not have pointer to it*/ char buf[1000]; sscanf(line,"NI: %s",buf); getclass(namer,buf); } break; case 'U': { /* New object*/ char buf[1000]; sscanf(line,"UI: %s",buf); getclass(namer,buf); } break; case 'K': break; case 'L': /* Do Load */ { struct localvars * lv=(struct localvars *) calloc(1, sizeof(struct localvars)); long long uid, objuid; char fieldname[600], classname[600], fielddesc[600]; sscanf(line,"LF: %s %ld %s %lld %s %s %s %lld",lv->name,&lv->linenumber, lv->sourcename, &objuid, classname, fieldname, fielddesc, &uid); getfield(namer,classname, fieldname,fielddesc); } break; case 'G': /* Do Array Load */ break; case 'M': /* Mark Local*/ break; case 'I': /* Enter Method*/ { struct methodchain* methodchain=(struct methodchain *) calloc(1,sizeof(struct methodchain)); char classname[600], methodname[600],signature[600]; int isStatic; sscanf(line,"IM: %s %s %s %d", classname, methodname, signature, &isStatic); methodchain->method=getmethod(namer, classname, methodname, signature); methodchain->caller=methodstack; if (!gencontains(statictable, methodchain->method)) { int * staticflag=(int *)malloc(sizeof (int)); *staticflag=isStatic; genputtable(statictable, methodchain->method, staticflag); } if (methodstack!=NULL) { if (!gencontains(calltable, methodchain->method)) { struct methodchain *mc=(struct methodchain *) calloc(1,sizeof(struct methodchain)); mc->method=methodstack->method; genputtable(calltable, methodchain->method, mc); } else { struct methodchain *tosearch=(struct methodchain *)gengettable(calltable, methodchain->method); while(tosearch->method!=methodstack->method) { if (tosearch->caller==NULL) { struct methodchain *mc=(struct methodchain *) calloc(1,sizeof(struct methodchain)); mc->method=methodstack->method; tosearch->caller=mc; break; } tosearch=tosearch->caller; } } } methodstack=methodchain; } break; case 'R': /* Return from method */ { struct methodchain* caller=methodstack->caller; free(methodstack); methodstack=caller; } break; case 'F': /* Field Assignment */ { long long suid; long long duid; char classname[1000]; char fieldname[1000]; char descname[1000]; sscanf(line,"FA: %lld %s %s %s %lld", &suid, classname, fieldname, descname, &duid); getfield(namer, classname, fieldname, descname); } break; case 'A': /* Array Assignment */ { long long suid; long long duid; long index; sscanf(line,"AA: %lld %ld %lld", &suid, &index, &duid); } break; } free(line); } }