static void list_assembly(const SqlDatabase::TransactionPtr &tx, int func_id) { Events events; gather_events(tx, func_id); load_events(tx, func_id, events); SqlDatabase::StatementPtr stmt = tx->statement("select address, assembly from semantic_instructions where func_id = ?" " order by position")->bind(0, func_id); for (SqlDatabase::Statement::iterator insn=stmt->begin(); insn!=stmt->end(); ++insn) { rose_addr_t addr = insn.get<rose_addr_t>(0); std::string assembly = insn.get<std::string>(1); Events::const_iterator ei=events.find(addr); // Assembly line prefix if (ei!=events.end() && ei->second.nexecuted>0) { std::cout <<std::setw(9) <<std::right <<ei->second.nexecuted <<"x "; } else { std::cout <<std::string(11, ' '); } // Assembly instruction std::cout <<"| " <<StringUtility::addrToString(addr) <<": " <<assembly <<"\n"; if (ei!=events.end()) show_events(ei->second); } }
static void list_combined(const SqlDatabase::TransactionPtr &tx, int func_id, bool show_assembly) { CloneDetection::FilesTable files(tx); Events events; gather_events(tx, func_id); load_events(tx, func_id, events/*out*/); gather_instructions(tx, func_id, events); Listing listing; gather_source_code(tx); load_source_code(tx, listing/*out*/); // Get lines of assembly code and insert them into the correct place in the Listing. if (show_assembly) { SqlDatabase::StatementPtr stmt = tx->statement("select" // 0 1 2 3 " insn.src_file_id, insn.src_line, insn.position, insn.address," // 4 5 6 " insn.assembly, func.id, func.name" " from tmp_insns as insn" " join semantic_functions as func on insn.func_id = func.id" " order by position"); for (SqlDatabase::Statement::iterator row=stmt->begin(); row!=stmt->end(); ++row) { int src_file_id = row.get<int>(0); int src_line_num = row.get<int>(1); SourcePosition srcpos(src_file_id, src_line_num); int pos = row.get<int>(2); rose_addr_t addr = row.get<rose_addr_t>(3); std::string assembly = row.get<std::string>(4); int func_id = row.get<int>(5); std::string func_name = row.get<std::string>(6); listing[srcpos].assembly_code.insert(std::make_pair(addr, AssemblyCode(pos, addr, assembly, func_id, func_name))); } // Listing header std::cout <<"WARNING: This listing should be read cautiously. It is ordered according to the\n" <<" source code with assembly lines following the source code line from which\n" <<" they came. However, the compiler does not always generate machine\n" <<" instructions in the same order as source code. When a discontinuity\n" <<" occurs in the assembly instruction listing, it will be marked by a \"#\"\n" <<" character. The assembly instructions are also numbered according to\n" <<" their relative positions in the binary function.\n" <<"\n" <<" The prefix area contains either source location information or test trace\n" <<" information. Note that trace information might be incomplete because\n" <<" tracing was disabled or only partially enabled, or the trace includes\n" <<" instructions that are not present in this function listing (e.g., when\n" <<" execution follows a CALL instruction). The following notes are possible:\n" <<" * \"Nx\" where N is an integer indicates that this instruction\n" <<" was reached N times during testing. These notes are typically\n" <<" only attached to the first instruction of a basic block and only\n" <<" if the trace contains EV_REACHED events. Lack of an Nx notation\n" <<" doesn't necessarily mean that the basic block was not reached, it\n" <<" only means that there is no EV_REACHED event for that block.\n" <<" * \"N<\" where N is an integer indicates that the instruction\n" <<" on the previous line consumed N inputs. Information about the\n" <<" inputs is listed on the right side of this line.\n" <<" * \"N>\" where N is an integer indicates that the instruction\n" <<" on the previous line produced N memory outputs. Information about the\n" <<" outputs is listed on the right side of this line. Only the final\n" <<" write to a memory address is considered a true output, and such\n" <<" writes will be marked with the string \"final\".\n" <<" * \"BR\" indicates that the instruction on the previous line is a\n" <<" control flow branch point. The right side of the line shows more\n" <<" detailed information about how many times the branch was taken.\n" <<" * \"FAULT\" indicates that the test was terminated at the previous\n" <<" instruction. The right side of the line shows the distribution of\n" <<" faults that occurred here.\n" <<"\n" <<" /------------- Prefix area\n" <<" /-------------/-------------- Source file ID or assembly function ID\n" <<" | /------/--------------- Source line number or assembly instruction index\n" <<" | | /-/---------------- Instruction out-of-order indicator\n" <<" | | |/ /----------- Instruction virtual address\n" <<" | | | |\n" <<"vvvv vvvvv/| |\n" <<"vvvvvvvvvv v vvvvvvvvvv\n"; } // Show the listing int prev_func_id = -1, prev_position = -1; std::set<int> seen_files; for (Listing::iterator li=listing.begin(); li!=listing.end(); ++li) { int file_id = li->first.file_id; if (seen_files.insert(file_id).second) { if (file_id>=0) { std::cout <<"\n" <<std::setw(4) <<std::right <<file_id <<".file |" <<(opt.colorize?"\033[33;4m":"") <<files.name(file_id) <<(opt.colorize?"\033[m":"") <<"\n"; } else { std::cout <<"\n" <<std::string(11, ' ') <<"|" <<(opt.colorize?"\033[33;4m":"") <<"instructions not associated with a source file" <<(opt.colorize?"\033[m":"") <<"\n"; } } if (file_id>=0) { std::cout <<std::setw(4) <<std::right <<file_id <<"." <<std::setw(6) <<std::left <<li->first.line_num <<"|" <<(opt.colorize?"\033[34m":"") <<StringUtility::untab(li->second.source_code) <<(opt.colorize?"\033[m":"") <<"\n"; } for (Instructions::iterator ii=li->second.assembly_code.begin(); ii!=li->second.assembly_code.end(); ++ii) { const AssemblyCode assm = ii->second; if (assm.func_id!=prev_func_id) { std::cout <<std::string(11, ' ') <<"# " <<(opt.colorize?"\033[33;4m":"") <<"function " <<StringUtility::numberToString(assm.func_id); if (!assm.func_name.empty()) std::cout <<" <" <<assm.func_name <<">"; std::cout <<(opt.colorize?"\033[m":"") <<"\n"; } Events::const_iterator ei=events.find(assm.addr); std::cout <<std::setw(4) <<std::right <<assm.func_id <<"." <<std::setw(6) <<std::left <<assm.pos <<(prev_func_id==assm.func_id && prev_position+1==assm.pos ? "|" : "#"); if (ei!=events.end() && ei->second.nexecuted>0) { std::cout <<std::setw(9) <<std::right <<ei->second.nexecuted <<"x "; } else { std::cout <<std::string(11, ' '); } std::cout <<StringUtility::addrToString(assm.addr) <<": " <<(opt.colorize?"\033[32m":"") <<assm.assembly <<(opt.colorize?"\033[m":"") <<"\n"; if (ei!=events.end()) show_events(ei->second); prev_func_id = assm.func_id; prev_position = assm.pos; } } }