// Pre: disambig_fp has been initialized and disambig_writing is True void generateDisambigFile() { FuncIterator* funcIt; TypeIterator* typeIt; // Write entries for global variables: fputs(ENTRY_DELIMETER, disambig_fp); fputs("\n", disambig_fp); fputs(GLOBAL_STRING, disambig_fp); fputs("\n", disambig_fp); visitVariableGroup(GLOBAL_VAR, 0, 0, 0, 0, &printDisambigAction); fputs("\n", disambig_fp); // Write entries for function parameters and return values: funcIt = newFuncIterator(); while (hasNextFunc(funcIt)) { FunctionEntry* cur_entry = nextFunc(funcIt); tl_assert(cur_entry); // Only write .disambig entries for program points that are listed // in prog-pts-file, if we are using the --prog-pts-file option: if (!fjalar_trace_prog_pts_filename || // If fjalar_trace_prog_pts_filename is on (we are reading in // a ppt list file), then DO NOT OUTPUT entries for program // points that we are not interested in. prog_pts_tree_entry_found(cur_entry)) { fputs(ENTRY_DELIMETER, disambig_fp); fputs("\n", disambig_fp); fputs(FUNCTION_PREFIX, disambig_fp); fputs(cur_entry->fjalar_name, disambig_fp); fputs("\n", disambig_fp); // Print out all function parameter return value variable names: visitVariableGroup(FUNCTION_FORMAL_PARAM, cur_entry, 0, 0, 0, &printDisambigAction); visitVariableGroup(FUNCTION_RETURN_VAR, cur_entry, 0, 0, 0, &printDisambigAction); fputs("\n", disambig_fp); } } deleteFuncIterator(funcIt); // Write entries for every struct/class in TypesTable, with the // type's name prefixed by 'usertype.': typeIt = newTypeIterator(); while (hasNextType(typeIt)) { TypeEntry* cur_entry = nextType(typeIt); tl_assert(cur_entry && cur_entry->typeName); fputs(ENTRY_DELIMETER, disambig_fp); fputs("\n", disambig_fp); fputs(USERTYPE_PREFIX, disambig_fp); fputs(cur_entry->typeName, disambig_fp); fputs("\n", disambig_fp); visitClassMembersNoValues(cur_entry, &printDisambigAction); fputs("\n", disambig_fp); } deleteTypeIterator(typeIt); }
// 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) ); } }
// Handle a function exit statement, which contains a jump kind of // 'Ret'. It seems pretty accurate to cue off of currentAddr, a value // that is updated every time an Ist_IMark statement is translated, // which is quite often void handle_possible_exit(MCEnv* mce, IRJumpKind jk) { if (Ijk_Ret == jk) { IRDirty *di; FunctionEntry* curFuncPtr = getFunctionEntryFromAddr(currentAddr); if (curFuncPtr && // Also, if fjalar_trace_prog_pts_filename is on (we are // reading in a ppt list file), then DO NOT generate IR code // to call helper functions for functions whose names are NOT // located in prog_pts_tree. This will greatly speed up // processing because these functions are filtered out at // translation-time, not at run-time (!fjalar_trace_prog_pts_filename || prog_pts_tree_entry_found(curFuncPtr))) { FJALAR_DPRINTF("[handle_possible_exit] %s - %x\n", curFuncPtr->fjalar_name, (UInt)currentAddr); // The only argument to exit_function() is a pointer to the // FunctionEntry for the function that we are exiting di = unsafeIRDirty_0_N(1/*regparms*/, "exit_function", &exit_function, mkIRExprVec_1(IRExpr_Const(IRConst_UWord((Addr)curFuncPtr)))); // For function exit, we are interested in observing all general purpose // integer registers, FTOP, and FPREG[], so make sure that they are // updated by setting the proper annotations. di->nFxState = 11; 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; di->fxState[9].fx = Ifx_Read; di->fxState[9].offset = offsetof(VexGuestArchState, guest_FTOP); di->fxState[9].size = sizeof(UInt); /* FTOP is 4 bytes even on x64 */ di->fxState[10].fx = Ifx_Read; di->fxState[10].offset = offsetof(VexGuestArchState, guest_FPREG); di->fxState[10].size = 8 * sizeof(ULong); stmt('V', mce, IRStmt_Dirty(di) ); } } }
/* ----SECTION---- globals ----SECTION---- ..main() return ----SECTION---- Stack.cpp.Stack::getNumStacksCreated() return ----SECTION---- Stack.cpp.Stack::Link::initialize(char*, Stack::Link*) this this->data this->data[] this->next this->next[].data this->next[].data[0] */ void outputVariableNamesToFile() { FuncIterator* funcIt; g_open_fp = var_dump_fp; // Print out a section for all global variables: fputs(ENTRY_DELIMETER, var_dump_fp); fputs("\n", var_dump_fp); fputs(GLOBAL_STRING, var_dump_fp); fputs("\n", var_dump_fp); visitVariableGroup(GLOBAL_VAR, 0, 0, 0, 0, &printVarNameAction); fputs("\n", var_dump_fp); funcIt = newFuncIterator(); // Print out a section for all relevant functions: while (hasNextFunc(funcIt)) { FunctionEntry* cur_entry = nextFunc(funcIt); tl_assert(cur_entry); // Only dump variable entries for program points that are listed // in prog-pts-file, if we are using the --prog-pts-file option: if (!fjalar_trace_prog_pts_filename || // If fjalar_trace_prog_pts_filename is on (we are reading in // a ppt list file), then DO NOT OUTPUT entries for program // points that we are not interested in. prog_pts_tree_entry_found(cur_entry)) { fputs(ENTRY_DELIMETER, var_dump_fp); fputs("\n", var_dump_fp); fputs(cur_entry->fjalar_name, var_dump_fp); fputs("\n", var_dump_fp); // Print out all function parameter return value variable names: visitVariableGroup(FUNCTION_FORMAL_PARAM, cur_entry, 0, 0, 0, &printVarNameAction); visitVariableGroup(FUNCTION_RETURN_VAR, cur_entry, 0, 0, 0, &printVarNameAction); fputs("\n", var_dump_fp); } } deleteFuncIterator(funcIt); g_open_fp = 0; }