diff --git a/SMPStaticAnalyzer b/SMPStaticAnalyzer index 8c405f65d2a77cb76d9239e8829594a71ffeb8ac..e19950c437bf4d0d39be94d9d9c5346060cff3ea 160000 --- a/SMPStaticAnalyzer +++ b/SMPStaticAnalyzer @@ -1 +1 @@ -Subproject commit 8c405f65d2a77cb76d9239e8829594a71ffeb8ac +Subproject commit e19950c437bf4d0d39be94d9d9c5346060cff3ea diff --git a/irdb-libs/ir_builders/fill_in_cfg.cpp b/irdb-libs/ir_builders/fill_in_cfg.cpp index 8e131c6b5b1dc0e84669bb9755ba2cdd9518fa83..010b2fdf2737af49d7498ef37626d489dbd1bae9 100644 --- a/irdb-libs/ir_builders/fill_in_cfg.cpp +++ b/irdb-libs/ir_builders/fill_in_cfg.cpp @@ -45,21 +45,19 @@ static inline std::string to_hex_string( const T& n ) void PopulateCFG::populate_instruction_map ( - map< pair<DatabaseID_t,VirtualOffset_t>, Instruction_t*> &insnMap, + InstructionMap_t &insnMap, FileIR_t *firp ) { /* start from scratch each time */ insnMap.clear(); - /* for each instruction in the IR */ for(auto insn : firp->getInstructions()) { - auto fileID=insn->getAddress()->getFileID(); - auto vo=insn->getAddress()->getVirtualOffset(); - - auto p=pair<DatabaseID_t,VirtualOffset_t>(fileID,vo); + const auto fileID= insn->getAddress()->getFileID(); + const auto vo = insn->getAddress()->getVirtualOffset(); + const auto p = pair<DatabaseID_t,VirtualOffset_t>(fileID,vo); assert(insnMap[p]==NULL); insnMap[p]=insn; @@ -69,8 +67,10 @@ void PopulateCFG::populate_instruction_map void PopulateCFG::set_fallthrough ( - map< pair<DatabaseID_t,VirtualOffset_t>, Instruction_t*> &insnMap, - DecodedInstruction_t *disasm, Instruction_t *insn, FileIR_t *firp + InstructionMap_t &insnMap, + DecodedInstruction_t *disasm, + Instruction_t *insn, + FileIR_t *firp ) { assert(disasm); @@ -79,14 +79,20 @@ void PopulateCFG::set_fallthrough if(insn->getFallthrough()) return; - // check for branches with targets - if( - (disasm->isUnconditionalBranch() ) || // it is a unconditional branch - (disasm->isReturn()) // or a return - ) + const auto is_mips = firp->getArchitecture()->getMachineType() == admtMips32; + // always set fallthrough for mips + // other platforms can end fallthroughs ofr uncond branches and returns + if(!is_mips) { - // this is a branch with no fallthrough instruction - return; + // check for branches with targets + if( + (disasm->isUnconditionalBranch() ) || // it is a unconditional branch + (disasm->isReturn()) // or a return + ) + { + // this is a branch with no fallthrough instruction + return; + } } /* get the address of the next instrution */ @@ -117,11 +123,37 @@ void PopulateCFG::set_fallthrough missed_instructions.insert(pair<DatabaseID_t,VirtualOffset_t>(insn->getAddress()->getFileID(),virtual_offset)); } +void PopulateCFG::set_delay_slots + ( + InstructionMap_t &insnMap, + DecodedInstruction_t *disasm, + Instruction_t *insn, + FileIR_t *firp + ) +{ + const auto is_mips = firp->getArchitecture()->getMachineType() == admtMips32; + if(!is_mips) + return; + + // using df=DecodedInstruction_t::factory; + const auto d=DecodedInstruction_t::factory(insn); + if(d->isBranch()) + { + const auto branch_addr = insn->getAddress(); + const auto delay_slot_insn = insnMap[ {branch_addr->getFileID(), branch_addr->getVirtualOffset() + 4}]; + assert(delay_slot_insn); + (void)firp->addNewRelocation(insn,0,"delay_slot1", delay_slot_insn, 0); + } + +} + void PopulateCFG::set_target ( - map< pair<DatabaseID_t,VirtualOffset_t>, Instruction_t*> &insnMap, - DecodedInstruction_t *disasm, Instruction_t *insn, FileIR_t *firp + InstructionMap_t &insnMap, + DecodedInstruction_t *disasm, + Instruction_t *insn, + FileIR_t *firp ) { @@ -316,7 +348,7 @@ void PopulateCFG::fill_in_cfg(FileIR_t *firp) failed_target_count=0; missed_instructions.clear(); - map< pair<DatabaseID_t,VirtualOffset_t>, Instruction_t*> insnMap; + auto insnMap = InstructionMap_t(); populate_instruction_map(insnMap, firp); cout << "Found "<<firp->getInstructions().size()<<" instructions." <<endl; @@ -332,6 +364,7 @@ void PopulateCFG::fill_in_cfg(FileIR_t *firp) set_fallthrough(insnMap, disasm.get(), insn, firp); set_target(insnMap, disasm.get(), insn, firp); + set_delay_slots(insnMap, disasm.get(), insn, firp); } if(bad_target_count>0) diff --git a/irdb-libs/ir_builders/fill_in_cfg.hpp b/irdb-libs/ir_builders/fill_in_cfg.hpp index b093d166f408d7740c56f24cfb1c7dc4efdd963a..360961aa431b7f716b7cbf28a75b7875efddcb4a 100644 --- a/irdb-libs/ir_builders/fill_in_cfg.hpp +++ b/irdb-libs/ir_builders/fill_in_cfg.hpp @@ -15,6 +15,7 @@ namespace PopCFG class PopulateCFG : public TransformStep_t { using extra_scoop_set_t = set<pair<VirtualOffset_t,VirtualOffset_t> >; + using InstructionMap_t = map< pair<DatabaseID_t,VirtualOffset_t>, Instruction_t*> ; extra_scoop_set_t extra_scoops; public: @@ -61,30 +62,10 @@ namespace PopCFG // helpers - void populate_instruction_map - ( - map< pair<DatabaseID_t,VirtualOffset_t>, - Instruction_t*>&, - FileIR_t * - ); - - void set_fallthrough - ( - map< pair<DatabaseID_t,VirtualOffset_t>, - Instruction_t*>&, - DecodedInstruction_t *, - Instruction_t *, - FileIR_t * - ); - - void set_target - ( - map< pair<DatabaseID_t,VirtualOffset_t>, - Instruction_t*>&, - DecodedInstruction_t *, - Instruction_t *, - FileIR_t * - ); + void populate_instruction_map ( InstructionMap_t&, FileIR_t *); + void set_fallthrough ( InstructionMap_t&, DecodedInstruction_t *, Instruction_t *, FileIR_t *); + void set_target ( InstructionMap_t&, DecodedInstruction_t *, Instruction_t *, FileIR_t *); + void set_delay_slots ( InstructionMap_t&, DecodedInstruction_t *, Instruction_t *, FileIR_t *); File_t* find_file(FileIR_t *, DatabaseID_t); void add_new_instructions(FileIR_t *); diff --git a/irdb-libs/ir_builders/fill_in_indtargs.cpp b/irdb-libs/ir_builders/fill_in_indtargs.cpp index 41421a71ce8e3a6303869ca94547e4986e3f07e5..8b1d93053e90e7cd7574d26084477847269ca68c 100644 --- a/irdb-libs/ir_builders/fill_in_indtargs.cpp +++ b/irdb-libs/ir_builders/fill_in_indtargs.cpp @@ -58,6 +58,56 @@ using namespace MEDS_Annotation; extern void read_ehframe(FileIR_t* firp, EXEIO::exeio* ); +template<typename T> +static inline T cptrtoh(FileIR_t* firp, const uint8_t* cptr) +{ + const auto ptrsize = firp->getArchitectureBitWidth() / 8 ; + const auto mt = firp->getArchitecture()->getMachineType(); + + switch(ptrsize) + { + case 4: + { + const auto raw_const = *reinterpret_cast<const uint64_t*>(cptr); + switch(mt) + { + case admtI386: + case admtArm32: + return le32toh(raw_const); + case admtMips32: + return be32toh(raw_const); + + default: + throw invalid_argument("Cannot detect machine type"); + } + assert(0); + } + case 8: + { + const auto raw_const = *reinterpret_cast<const uint32_t*>(cptr); + switch(mt) + { + case admtX86_64: + case admtAarch64: + return le64toh(raw_const); + case admtMips64: + return be64toh(raw_const); + + default: + throw invalid_argument("Cannot detect machine type"); + } + assert(0); + break; + } + default: + { + throw invalid_argument("Cannot detect pointer size"); + } + } + + +} + class PopulateIndTargs_t : public TransformStep_t @@ -362,7 +412,9 @@ void get_instruction_targets(FileIR_t *firp, EXEIO::exeio* exeiop, const set<Vir } else if(mt==admtMips32) { - // empty for now + /* no reason to look for pc-rel constants in mips */ + if(firp->getArchitecture()->getFileType() == adftELFSO) + continue;; } else throw invalid_argument("Cannot determine machine type"); @@ -448,32 +500,24 @@ void infer_targets(FileIR_t *firp, section* shdr) // even on 64-bit, pointers might be stored as 32-bit, as a // elf object has the 32-bit limitations. // there's no real reason to look for 64-bit pointers - uintptr_t p=0; - if(arch_ptr_bytes()==4) - p=*(int*)&data[i]; - else - p=*(VirtualOffset_t*)&data[i]; // 64 or 32-bit depending on sizeof uintptr_t, may need porting for cross platform analysis. - - - - auto prov = ibt_provenance_t(); - if(shdr->get_name()==".init_array") - prov=ibt_provenance_t::ibtp_initarray; - else if(shdr->get_name()==".fini_array") - prov=ibt_provenance_t::ibtp_finiarray; - else if(shdr->get_name()==".got.plt") - prov=ibt_provenance_t::ibtp_gotplt; - else if(shdr->get_name()==".got") - prov=ibt_provenance_t::ibtp_got; - else if(shdr->get_name()==".symtab") - prov=ibt_provenance_t::ibtp_symtab; - else if(shdr->isWriteable()) - prov=ibt_provenance_t::ibtp_data; - else - prov=ibt_provenance_t::ibtp_rodata; - - possible_target(p, i+shdr->get_address(), prov); - + const auto ptr_val = uint64_t( + (arch_ptr_bytes()==4) ? cptrtoh<uint32_t>(firp, reinterpret_cast<const uint8_t*>(&data[i])) : + (arch_ptr_bytes()==8) ? cptrtoh<uint64_t>(firp, reinterpret_cast<const uint8_t*>(&data[i])) : + throw invalid_argument("Cannot map architecture size to bit width") + ); + + const auto ptr_addr = i+shdr->get_address(); + + const auto ptr_prov = + (shdr->get_name()==".init_array") ? ibt_provenance_t::ibtp_initarray : + (shdr->get_name()==".fini_array") ? ibt_provenance_t::ibtp_finiarray : + (shdr->get_name()==".got.plt") ? ibt_provenance_t::ibtp_gotplt : + (shdr->get_name()==".got") ? ibt_provenance_t::ibtp_got : + (shdr->get_name()==".symtab") ? ibt_provenance_t::ibtp_symtab : + (shdr->isWriteable()) ? ibt_provenance_t::ibtp_data : + ibt_provenance_t::ibtp_rodata; + + possible_target(ptr_val, ptr_addr, ptr_prov); } } @@ -485,14 +529,11 @@ void handle_scoop_scanning(FileIR_t* firp) { if(scoop->getName() == ".ctor" || scoop->getName() == ".dtor" ) { - const auto ptrsize = firp->getArchitectureBitWidth() / 8 ; const auto &scoop_contents = scoop->getContents(); + const auto ptrsize = firp->getArchitectureBitWidth() / 8 ; for(auto i = 0u; i + ptrsize < scoop_contents.size(); i += ptrsize) { - const auto ptr = - ptrsize == 8 ? *reinterpret_cast<const uint64_t*>(scoop_contents.c_str() + i) : - ptrsize == 4 ? *reinterpret_cast<const uint32_t*>(scoop_contents.c_str() + i) : - throw invalid_argument("Cannot map ptrsize to deref type"); + const auto ptr = cptrtoh<uint64_t>(firp, reinterpret_cast<const uint8_t*>(scoop_contents.c_str() + i)); possible_target(ptr, scoop->getStart()->getVirtualOffset() + i, ibt_provenance_t::ibtp_data); } @@ -3363,14 +3404,6 @@ void unpin_elf_tables(FileIR_t *firp, int64_t do_unpin_opt) if(insn->getIndirectBranchTargetAddress()==nullptr) { - /* - auto newaddr = new AddressID_t; - assert(newaddr); - newaddr->SetFileID(insn->getAddress()->getFileID()); - newaddr->setVirtualOffset(0); // unpinne - - firp->getAddresses().insert(newaddr); - */ auto newaddr=firp->addNewAddress(insn->getAddress()->getFileID(),0); insn->setIndirectBranchTargetAddress(newaddr); } @@ -3514,30 +3547,15 @@ void unpin_type3_switchtable(FileIR_t* firp,Instruction_t* insn,DataScoop_t* sco already_unpinned.insert(ibt); // add reloc to IR. - /* - auto nr=new Relocation_t(BaseObj_t::NOT_IN_DATABASE, scoop_off, "data_to_insn_ptr", ibt); - assert(nr); - firp->getRelocations().insert(nr); - scoop->getRelocations().insert(nr); - */ auto nr=firp->addNewRelocation(scoop,scoop_off, "data_to_insn_ptr", ibt); (void)nr; - // remove rodata reference for hell nodes. targets[table_entry]=newprov; switch_targs.insert(ibt); if(ibt->getIndirectBranchTargetAddress()==nullptr) { - /* - auto newaddr = new AddressID_t; - assert(newaddr); - newaddr->SetFileID(ibt->getAddress()->getFileID()); - newaddr->setVirtualOffset(0); // unpinne - - firp->getAddresses().insert(newaddr); - */ auto newaddr=firp->addNewAddress(ibt->getAddress()->getFileID(),0); ibt->setIndirectBranchTargetAddress(newaddr); } diff --git a/irdb-libs/ir_builders/split_eh_frame.cpp b/irdb-libs/ir_builders/split_eh_frame.cpp index 4f7493f400cb637bd16bca841dfa6fa6c0f65d63..a10e786a4a9f7235f871ffd70a1ef79eec30f604 100644 --- a/irdb-libs/ir_builders/split_eh_frame.cpp +++ b/irdb-libs/ir_builders/split_eh_frame.cpp @@ -572,9 +572,15 @@ split_eh_frame_impl_t<ptrsize>::split_eh_frame_impl_t(FileIR_t* p_firp) eh_frame_hdr_scoop=lookup_scoop_by_name(".eh_frame_hdr"); gcc_except_table_scoop=lookup_scoop_by_name(".gcc_except_table"); + + const auto endian_type = + firp->getArchitecture()->getMachineType() == admtMips32 ? EHP::BIG : + EHP::LITTLE; + eh_frame_parser=EHFrameParser_t::factory ( ptrsize, + endian_type, scoop_contents(eh_frame_scoop), scoop_address(eh_frame_scoop), scoop_contents(eh_frame_hdr_scoop), scoop_address(eh_frame_hdr_scoop), scoop_contents(gcc_except_table_scoop), scoop_address(gcc_except_table_scoop) diff --git a/irdb-libs/libIRDB-core/src/decode_csmips32.cpp b/irdb-libs/libIRDB-core/src/decode_csmips32.cpp index 2f03959084060d47896d50a5da050a7a7f2f9d25..5bcdb9710ff0473befe2f7a194970f49d69e58ff 100644 --- a/irdb-libs/libIRDB-core/src/decode_csmips32.cpp +++ b/irdb-libs/libIRDB-core/src/decode_csmips32.cpp @@ -146,7 +146,18 @@ bool DecodedInstructionCapstoneMIPS32_t::isCall() const if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); assert(the_insn); - return isPartOfGroup(the_insn, MIPS_GRP_CALL); + + const auto marked_call = isPartOfGroup(the_insn, MIPS_GRP_CALL); + + const auto unmarked_call = isPartOfGroup(the_insn, MIPS_GRP_BRANCH_RELATIVE) && + ( + getMnemonic() == "bal" || + getMnemonic() == "balr" || + getMnemonic() == "jal" || + getMnemonic() == "jalr" + ); + + return marked_call || unmarked_call; } diff --git a/irdb-libs/libehp b/irdb-libs/libehp index 07cb40654219555d6ac7bd1fe6c67e6e8df162b4..2b640f5e65afd7c41df59ef6416fae46f46a929e 160000 --- a/irdb-libs/libehp +++ b/irdb-libs/libehp @@ -1 +1 @@ -Subproject commit 07cb40654219555d6ac7bd1fe6c67e6e8df162b4 +Subproject commit 2b640f5e65afd7c41df59ef6416fae46f46a929e diff --git a/irdb-libs/rida/rida.cpp b/irdb-libs/rida/rida.cpp index f2349e4dcd726a341c2b1dbc87db68b111d01b54..41458862dc461af7fe940f18fd02b2dcab52260a 100644 --- a/irdb-libs/rida/rida.cpp +++ b/irdb-libs/rida/rida.cpp @@ -73,11 +73,12 @@ class CreateFunctions_t exit(1); } - const auto cs_mode= - machine_type == mtArm32 ? CS_MODE_LITTLE_ENDIAN : - machine_type == mtAarch64 ? CS_MODE_LITTLE_ENDIAN : - file_class == ELF64 ? CS_MODE_64 : - file_class == ELF32 ? CS_MODE_32 : + const auto my_cs_mode = + machine_type == mtArm32 ? cs_mode(CS_MODE_LITTLE_ENDIAN) : + machine_type == mtAarch64 ? cs_mode(CS_MODE_LITTLE_ENDIAN) : + machine_type == mtMips32 ? cs_mode(CS_MODE_MIPS32 | CS_MODE_BIG_ENDIAN) : + file_class == ELF64 ? cs_mode(CS_MODE_64) : + file_class == ELF32 ? cs_mode(CS_MODE_32) : throw std::runtime_error("Cannot handle ELF class"); const auto my_cs_arch = @@ -85,9 +86,10 @@ class CreateFunctions_t machine_type == mtI386 ? CS_ARCH_X86 : machine_type == mtArm32 ? CS_ARCH_ARM : machine_type == mtAarch64 ? CS_ARCH_ARM64 : + machine_type == mtMips32 ? CS_ARCH_MIPS : throw std::runtime_error("Cannot handle architecture"); - if (cs_open(my_cs_arch, cs_mode , &cshandle) != CS_ERR_OK) + if (cs_open(my_cs_arch, my_cs_mode , &cshandle) != CS_ERR_OK) { cerr<<"Cannot initialize capstone"<<endl; exit(1); diff --git a/zipr b/zipr index d6183960755dae9d809642f2e2a54d7b6c9634f4..f4b53cafcec8f91627010689a318cb9e302f3f1f 160000 --- a/zipr +++ b/zipr @@ -1 +1 @@ -Subproject commit d6183960755dae9d809642f2e2a54d7b6c9634f4 +Subproject commit f4b53cafcec8f91627010689a318cb9e302f3f1f