From 47a311a62cdaf771f5fe7f46f8952e962c14c570 Mon Sep 17 00:00:00 2001 From: an7s <an7s@git.zephyr-software.com> Date: Thu, 26 May 2016 14:46:10 +0000 Subject: [PATCH] Add option to not fix indirect calls Former-commit-id: 3ea8f36c2821c19bf3135dd7263d1f41db4454b9 --- libIRDB/test/fix_calls.cpp | 135 ++++++++++++++++++++++++++------ tools/simple_cdi/scdi_instr.cpp | 1 + 2 files changed, 112 insertions(+), 24 deletions(-) diff --git a/libIRDB/test/fix_calls.cpp b/libIRDB/test/fix_calls.cpp index 88f5b36ee..61d356a55 100644 --- a/libIRDB/test/fix_calls.cpp +++ b/libIRDB/test/fix_calls.cpp @@ -77,9 +77,11 @@ long long call_to_not_entry=0; long long thunk_check=0; long long found_pattern=0; long long in_ehframe=0; +long long no_fix_for_ib=0; pqxxDB_t pqxx_interface; +bool opt_fix_icalls = true; void fix_other_pcrel(FileIR_t* firp, Instruction_t *insn, UIntPtr offset); @@ -103,16 +105,37 @@ bool check_entry(bool &found, ControlFlowGraph_t* cfg) DISASM disasm; Instruction_t* insn=*it; insn->Disassemble(disasm); - if(Instruction_t::SetsStackPointer(&disasm)) + if(getenv("VERBOSE_FIX_CALLS")) + if(Instruction_t::SetsStackPointer(&disasm)) { return false; + } else { + if(getenv("VERBOSE_FIX_CALLS")) + { + virtual_offset_t addr = 0; + if (insn->GetAddress()) + addr = insn->GetAddress()->GetVirtualOffset(); + cout<<"check_entry: does not set stack pointer?"<< " address=" + <<hex<<addr<<": "<<insn->getDisassembly()<<endl; + } + } if(strstr(disasm.CompleteInstr, "[esp]")) { found=true; + if(getenv("VERBOSE_FIX_CALLS")) + { + virtual_offset_t addr = 0; + if (insn->GetAddress()) + addr = insn->GetAddress()->GetVirtualOffset(); + cout<<"Needs fix (check_entry): [esp]"<< " address=" + <<hex<<addr<<": "<<insn->getDisassembly()<<endl; + } return true; } } + + return false; } @@ -134,36 +157,28 @@ bool call_needs_fix(Instruction_t* insn) Instruction_t *fallthru=insn->GetFallthrough(); DISASM disasm; - string pattern;; + string pattern; - /* if the target isn't in the IR */ - if(!target) - { - /* call 0's aren't to real locations */ - insn->Disassemble(disasm); - if(strcmp(disasm.CompleteInstr, "call 0x00000000")==0) - { - return false; - } - no_target_insn++; - /* then we need to fix it */ - return true; - } +// this used to work because fill_in_indirects would mark IBTs +// while reading the ehframe, which perfectly corresponds to when +// we need to fix calls due to eh_frame. However, now STARS also marks +// return points as IBTs, so we need to re-parse the ehframe and use that instead. /* no fallthrough instruction, something is odd here */ if(!fallthru) { + if(getenv("VERBOSE_FIX_CALLS")) + { + virtual_offset_t addr = 0; + if (insn->GetAddress()) + addr = insn->GetAddress()->GetVirtualOffset(); + cout<<"Needs fix: No fallthrough"<< " address=" + <<hex<<addr<<": "<<insn->getDisassembly()<<endl; + } no_fallthrough_insn++; return true; } - /* if the location after the call is marked as an IBT, then - * this location might be used for walking the stack - */ -// this used to work because fill_in_indirects would mark IBTs -// while reading the ehframe, which perfectly corresponds to when -// we need to fix calls due to eh_frame. However, now STARS also marks -// return points as IBTs, so we need to re-parse the ehframe and use that instead. #if 0 if(fallthru->GetIndirectBranchTargetAddress()!=NULL) return true; @@ -177,12 +192,54 @@ bool call_needs_fix(Instruction_t* insn) } #endif + if (!opt_fix_icalls && insn->GetIBTargets() && insn->GetIBTargets()->size() > 0) + { + no_fix_for_ib++; + return false; + } + + /* if the target isn't in the IR */ + if(!target) + { + /* call 0's aren't to real locations */ + insn->Disassemble(disasm); + if(strcmp(disasm.CompleteInstr, "call 0x00000000")==0) + { + return false; + } + no_target_insn++; + + if(getenv("VERBOSE_FIX_CALLS")) + { + virtual_offset_t addr = 0; + if (insn->GetAddress()) + addr = insn->GetAddress()->GetVirtualOffset(); + cout<<"Needs fix: No target instruction"<< " address=" + <<hex<<addr<<": "<<insn->getDisassembly()<<endl; + } + /* then we need to fix it */ + return true; + } + + + /* if the location after the call is marked as an IBT, then + * this location might be used for walking the stack + */ + Function_t* func=target->GetFunction(); /* if there's no function for this instruction */ if(!func) { + if(getenv("VERBOSE_FIX_CALLS")) + { + virtual_offset_t addr = 0; + if (insn->GetAddress()) + addr = insn->GetAddress()->GetVirtualOffset(); + cout<<"Needs fix: Target not in a function"<< " address=" + <<hex<<addr<<": "<<insn->getDisassembly()<<endl; + } target_not_in_function++; /* we need to fix it */ return true; @@ -210,7 +267,18 @@ bool call_needs_fix(Instruction_t* insn) if(found) { if(ret) + { + if(getenv("VERBOSE_FIX_CALLS")) + { + virtual_offset_t addr = 0; + if (insn->GetAddress()) + addr = insn->GetAddress()->GetVirtualOffset(); + cout<<"Needs fix: (via check_entry) Thunk detected"<< " address=" + <<hex<<addr<<": "<<insn->getDisassembly()<<endl; + } thunk_check++; + } + return ret; } @@ -242,6 +310,14 @@ bool call_needs_fix(Instruction_t* insn) if(strstr(disasm.CompleteInstr, pattern.c_str())!=NULL) { found_pattern++; + if(getenv("VERBOSE_FIX_CALLS")) + { + virtual_offset_t addr = 0; + if (insn->GetAddress()) + addr = insn->GetAddress()->GetVirtualOffset(); + cout<<"Needs fix: Found pattern"<< " address=" + <<hex<<addr<<": "<<insn->getDisassembly()<<endl; + } /* then we need to fix this callsite */ return true; } @@ -730,6 +806,7 @@ void fix_all_calls(FileIR_t* firp, bool print_stats, bool fix_all) cout << "# ATTRIBUTE thunk_check="<<std::dec<< thunk_check << endl; cout << "# ATTRIBUTE found_pattern="<<std::dec<< found_pattern << endl; cout << "# ATTRIBUTE in_ehframe="<<std::dec<< in_ehframe << endl; + cout << "# ATTRIBUTE no_fix_for_ib="<<std::dec<< no_fix_for_ib << endl; no_target_insn=0; no_fallthrough_insn=0; target_not_in_function=0; @@ -737,7 +814,7 @@ void fix_all_calls(FileIR_t* firp, bool print_stats, bool fix_all) thunk_check=0; found_pattern=0; in_ehframe=0; - + no_fix_for_ib=0; } } @@ -835,7 +912,7 @@ void fix_other_pcrel(FileIR_t* firp, Instruction_t *insn, UIntPtr virt_offset) insn->Disassemble(disasm); if(getenv("VERBOSE_FIX_CALLS")) - cout<<" Coverted to: "<<disasm.CompleteInstr<<endl; + cout<<" Converted to: "<<disasm.CompleteInstr<<endl; } } @@ -893,6 +970,8 @@ main(int argc, char* argv[]) cerr<<" --no-eh-frame Use (or dont) the eh-frame section to be compatible with exception handling." << endl; cerr<<" --fix-all " << endl; cerr<<" --no-fix-all Convert (or don't) all calls to push/jmp pairs."<<endl; + cerr<<" --fix-icalls Convert (or don't) indirect calls."<<endl; + cerr<<" --no-fix-icalls Convert (or don't) indirect calls."<<endl; exit(-1); } @@ -914,6 +993,14 @@ main(int argc, char* argv[]) { do_eh_frame=false; } + else if(strcmp("--fix-icalls", argv[argc_iter])==0) + { + opt_fix_icalls = true; + } + else if(strcmp("--no-fix-icalls", argv[argc_iter])==0) + { + opt_fix_icalls = false; + } else { cerr<<"Unrecognized option: "<<argv[argc_iter]<<endl; diff --git a/tools/simple_cdi/scdi_instr.cpp b/tools/simple_cdi/scdi_instr.cpp index a6a6329c5..cc64ecc18 100644 --- a/tools/simple_cdi/scdi_instr.cpp +++ b/tools/simple_cdi/scdi_instr.cpp @@ -252,6 +252,7 @@ bool SimpleCDI_Instrument::add_scdi_instrumentation(Instruction_t* insn) ret->Assemble("jmp 0"); ret->SetFallthrough(NULL); ret->SetTarget(return_site); + ret->SetIBTargets(NULL); cout<<hex<<insn->GetAddress()->GetVirtualOffset(); cout<<": Converted ret into a direct jmp: "<<insn->getDisassembly(); -- GitLab