diff --git a/tools/selective_cfi/color_map.cpp b/tools/selective_cfi/color_map.cpp index c012122188120c0bf25a16dbf760c615884033ae..d0a878de96cc4784e4af475bb7db44e8c68dfe9a 100644 --- a/tools/selective_cfi/color_map.cpp +++ b/tools/selective_cfi/color_map.cpp @@ -72,11 +72,14 @@ bool ColoredInstructionNonces_t::create() } // output stats - cout<<"#ATTRIBUTE slots_used="<<slots_used.size()<<endl; + cout<<"# ATTRIBUTE slots_used="<<slots_used.size()<<endl; + int total_slots = 0; for(int slot_no=0; slot_no<slots_used.size(); slot_no++) { - cout<<"#ATTRIBUTE used_slot"<<slot_no<<"="<<slots_used[slot_no].SlotsUsed()<<endl; + cout<<"# ATTRIBUTE used_slot"<<slot_no<<"="<<slots_used[slot_no].SlotsUsed()<<endl; + total_slots += slots_used[slot_no].SlotsUsed(); } + cout<<"# ATTRIBUTE total_slots="<<total_slots<<endl; return true; } diff --git a/tools/selective_cfi/scfi_instr.cpp b/tools/selective_cfi/scfi_instr.cpp index 07a5982321d9006a43545fd5362fd277c4906cf2..214c1db571b193836a0efbd9ae0d1bcc150f939e 100644 --- a/tools/selective_cfi/scfi_instr.cpp +++ b/tools/selective_cfi/scfi_instr.cpp @@ -25,6 +25,7 @@ #include "color_map.hpp" #include <stdlib.h> #include <memory> +#include <math.h> @@ -471,7 +472,7 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v) if(d.Argument1.ArgType!=NO_ARGUMENT) { unsigned int sp_adjust=d.Instruction.Immediat-firp->GetArchitectureBitWidth()/8; - cout<<"Found relateively rare ret_with_pop insn: "<<d.CompleteInstr<<endl; + cout<<"Found relatively rare ret_with_pop insn: "<<d.CompleteInstr<<endl; char buf[30]; sprintf(buf, "pop %s [%s+%d]", worddec.c_str(), rspreg.c_str(), sp_adjust); Instruction_t* newafter=insertAssemblyBefore(firp,insn,buf); @@ -562,9 +563,42 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v) #endif } +static void display_histogram(std::ostream& out, std::string attr_label, std::map<int,int> & p_map) +{ + if (p_map.size()) + { + out<<"# ATTRIBUTE " << attr_label << "="; + out<<"{ibt_size:count,"; + bool first_time=true; + for (map<int,int>::iterator it = p_map.begin(); + it != p_map.end(); ++it) + { + if (!first_time) + out << ","; + out << it->first << ":" << it->second; + first_time = false; + } + out<<"}"<<endl; + } +} + bool SCFI_Instrument::instrument_jumps() { int cfi_checks=0; + int cfi_branch_jmp_checks=0; + int cfi_branch_jmp_complete=0; + int cfi_branch_call_checks=0; + int cfi_branch_call_complete=0; + int cfi_branch_ret_checks=0; + int cfi_branch_ret_complete=0; + int ibt_complete=0; + double cfi_branch_jmp_complete_ratio = NAN; + double cfi_branch_ret_complete_ratio = NAN; + + std::map<int, int> jmps; + std::map<int, int> rets; + + // build histogram of target sizes // for each instruction for(InstructionSet_t::iterator it=firp->GetInstructions().begin(); @@ -590,6 +624,12 @@ bool SCFI_Instrument::instrument_jumps() if((d.Argument1.ArgType&MEMORY_TYPE)==MEMORY_TYPE) { cfi_checks++; + cfi_branch_jmp_checks++; + if (insn->GetIBTargets() && insn->GetIBTargets()->IsComplete()) + { + cfi_branch_jmp_complete++; + jmps[insn->GetIBTargets()->size()]++; + } AddJumpCFI(insn); } break; @@ -599,9 +639,19 @@ bool SCFI_Instrument::instrument_jumps() { // not yet implemented. assert(0); // fix calls should conver these to jumps + cfi_branch_call_checks++; + if (insn->GetIBTargets() && insn->GetIBTargets()->IsComplete()) + cfi_branch_call_complete++; + cfi_checks++; } break; case RetType: + cfi_branch_ret_checks++; + if (insn->GetIBTargets() && insn->GetIBTargets()->IsComplete()) + { + cfi_branch_ret_complete++; + rets[insn->GetIBTargets()->size()]++; + } cfi_checks++; AddReturnCFI(insn); break; @@ -611,9 +661,39 @@ bool SCFI_Instrument::instrument_jumps() } } + cout<<"# ATTRIBUTE cfi_jmp_checks="<<std::dec<<cfi_branch_jmp_checks<<endl; + cout<<"# ATTRIBUTE cfi_jmp_complete="<<std::dec<<cfi_branch_jmp_complete<<endl; + + display_histogram(cout, "cfi_jmp_complete_histogram", jmps); +/* + cout<<"# ATTRIBUTE cfi_branch_call_checks="<<std::dec<<cfi_branch_call_checks<<endl; + cout<<"# ATTRIBUTE cfi_branch_call_complete="<<std::dec<<cfi_branch_call_complete<<endl; +*/ + cout<<"# ATTRIBUTE cfi_ret_checks="<<std::dec<<cfi_branch_ret_checks<<endl; + cout<<"# ATTRIBUTE cfi_ret_complete="<<std::dec<<cfi_branch_ret_complete<<endl; + display_histogram(cout, "cfi_ret_complete_histogram", rets); cout<<"# ATTRIBUTE cfi_checks="<<std::dec<<cfi_checks<<endl; + ibt_complete = cfi_branch_jmp_complete + cfi_branch_call_complete + cfi_branch_ret_complete; + cout<<"# ATTRIBUTE ibt_complete="<<std::dec<<ibt_complete<<endl; + + if (cfi_branch_jmp_checks > 0) + cfi_branch_jmp_complete_ratio = (double)cfi_branch_jmp_complete / cfi_branch_jmp_checks; + + if (cfi_branch_ret_checks > 0) + cfi_branch_ret_complete_ratio = (double)cfi_branch_ret_complete / cfi_branch_ret_checks; + + double cfi_branch_complete_ratio = NAN; + if (ibt_complete > 0) + cfi_branch_complete_ratio = (double) cfi_checks / ibt_complete; + + + cout << "# ATTRIBUTE cfi_jmp_complete_ratio=" << cfi_branch_jmp_complete_ratio << endl; + + cout << "# ATTRIBUTE cfi_ret_complete_ratio=" << cfi_branch_ret_complete_ratio << endl; + cout << "# ATTRIBUTE cfi_complete_ratio=" << cfi_branch_ret_complete_ratio << endl; + return true; }