From f3ab753677478d4bc8d58d805740f913a4ef251d Mon Sep 17 00:00:00 2001 From: jdh8d <jdh8d@git.zephyr-software.com> Date: Mon, 5 Feb 2018 19:45:35 +0000 Subject: [PATCH] libIRDB IR-builder separation from BEA Former-commit-id: 563a2ec0a5c1b14cc52d54caf74058e60e8513aa --- .gitattributes | 6 + libIRDB/include/decode/decode.hpp | 52 +++++ libIRDB/include/decode/operand.hpp | 46 ++++ libIRDB/include/libIRDB-decode.hpp | 8 + libIRDB/src/SConscript | 1 + libIRDB/src/decode/SConscript | 28 +++ libIRDB/src/decode/decode.cpp | 154 +++++++++++++ libIRDB/src/decode/operand.cpp | 168 ++++++++++++++ libIRDB/test/SConscript | 2 +- libIRDB/test/fill_in_cfg.cpp | 71 +++--- libIRDB/test/fill_in_indtargs.cpp | 345 ++++++++++++++++------------- libIRDB/test/split_eh_frame.cpp | 19 +- 12 files changed, 704 insertions(+), 196 deletions(-) create mode 100644 libIRDB/include/decode/decode.hpp create mode 100644 libIRDB/include/decode/operand.hpp create mode 100644 libIRDB/include/libIRDB-decode.hpp create mode 100644 libIRDB/src/decode/SConscript create mode 100644 libIRDB/src/decode/decode.cpp create mode 100644 libIRDB/src/decode/operand.cpp diff --git a/.gitattributes b/.gitattributes index 9e2ff2e43..37d9e0189 100644 --- a/.gitattributes +++ b/.gitattributes @@ -223,8 +223,11 @@ libIRDB/include/core/reloc.hpp -text libIRDB/include/core/scoop.hpp -text libIRDB/include/core/type.hpp -text libIRDB/include/core/variantid.hpp -text +libIRDB/include/decode/decode.hpp -text +libIRDB/include/decode/operand.hpp -text libIRDB/include/libIRDB-cfg.hpp -text libIRDB/include/libIRDB-core.hpp -text +libIRDB/include/libIRDB-decode.hpp -text libIRDB/include/libIRDB-syscall.hpp -text libIRDB/include/libIRDB-util.hpp -text libIRDB/include/syscall/syscall.hpp -text @@ -260,6 +263,9 @@ libIRDB/src/core/reloc.cpp -text libIRDB/src/core/scoop.cpp -text libIRDB/src/core/type.cpp -text libIRDB/src/core/variantid.cpp -text +libIRDB/src/decode/SConscript -text +libIRDB/src/decode/decode.cpp -text +libIRDB/src/decode/operand.cpp -text libIRDB/src/syscall/Makefile.in -text libIRDB/src/syscall/SConscript -text libIRDB/src/syscall/SConstruct -text diff --git a/libIRDB/include/decode/decode.hpp b/libIRDB/include/decode/decode.hpp new file mode 100644 index 000000000..8dd3ff32f --- /dev/null +++ b/libIRDB/include/decode/decode.hpp @@ -0,0 +1,52 @@ +#ifndef libirdb_decode_hpp +#define libirdb_decode_hpp + +#include <stdint.h> + +namespace libIRDB +{ + +using namespace libIRDB; +using namespace std; + +class DecodedOperand_t; + +class DecodedInstruction_t +{ + public: + DecodedInstruction_t()=delete; + DecodedInstruction_t(const Instruction_t*); + DecodedInstruction_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len); + DecodedInstruction_t(const virtual_offset_t start_addr, const void *data, const void* endptr); + DecodedInstruction_t(const DecodedInstruction_t& copy); + DecodedInstruction_t& operator=(const DecodedInstruction_t& copy); + + virtual ~DecodedInstruction_t(); + + string getDisassembly() const; + bool valid() const; + uint32_t length() const; + bool isBranch() const; + bool isUnconditionalBranch() const; + bool isConditionalBranch() const; + bool isReturn() const; + string getMnemonic() const; + virtual_offset_t getImmediate() const; + virtual_offset_t getAddress() const; + + + + + // 0-based. first operand is numbered 0. + DecodedOperand_t getOperand(const int op_num) const; + + private: + + void Disassemble(const virtual_offset_t start_addr, const void *, uint32_t max_len); + void *disasm_data; + uint32_t disasm_length; +}; + +} + +#endif diff --git a/libIRDB/include/decode/operand.hpp b/libIRDB/include/decode/operand.hpp new file mode 100644 index 000000000..797c0e087 --- /dev/null +++ b/libIRDB/include/decode/operand.hpp @@ -0,0 +1,46 @@ +#ifndef libRIDB_decodedoperand_hpp +#define libRIDB_decodedoperand_hpp + +namespace libIRDB +{ + +using namespace std; +using namespace libIRDB; + + +class DecodedOperand_t +{ + public: + DecodedOperand_t() =delete; + DecodedOperand_t& operator=(const DecodedOperand_t& copy); + DecodedOperand_t(const DecodedOperand_t& copy); + virtual ~DecodedOperand_t(); + + bool isConstant() const; + string getString() const; + bool isWrite() const; + bool isRegister() const; + uint32_t getRegNumber() const; + bool isMemory() const; + bool hasBaseRegister() const; + bool hasIndexRegister() const; + uint32_t getBaseRegister() const; + uint32_t getIndexRegister() const; + virtual_offset_t getMemoryDisplacement() const; + bool isPcrel() const; + uint32_t getScaleValue() const; + + + + private: + + + void* arg_data; + DecodedOperand_t(void* arg_p); + + friend class DecodedInstruction_t; + +}; + +} +#endif diff --git a/libIRDB/include/libIRDB-decode.hpp b/libIRDB/include/libIRDB-decode.hpp new file mode 100644 index 000000000..f05189c36 --- /dev/null +++ b/libIRDB/include/libIRDB-decode.hpp @@ -0,0 +1,8 @@ +#ifndef libIRDB_core_hpp +#define libIRDB_core_hpp + +#include <libIRDB-core.hpp> +#include <decode/operand.hpp> +#include <decode/decode.hpp> + +#endif diff --git a/libIRDB/src/SConscript b/libIRDB/src/SConscript index 83fb1fa65..ded23c7cb 100644 --- a/libIRDB/src/SConscript +++ b/libIRDB/src/SConscript @@ -7,6 +7,7 @@ dirs=''' core syscall util + decode ''' for i in Split(dirs): diff --git a/libIRDB/src/decode/SConscript b/libIRDB/src/decode/SConscript new file mode 100644 index 000000000..b2dab0b2a --- /dev/null +++ b/libIRDB/src/decode/SConscript @@ -0,0 +1,28 @@ +import os + +Import('env') +myenv=env +myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) + + +libname="IRDB-decode" +files= ''' + decode.cpp + operand.cpp + ''' +cpppath=''' + $SECURITY_TRANSFORMS_HOME/include/ + $SECURITY_TRANSFORMS_HOME/libIRDB/include/ + $SECURITY_TRANSFORMS_HOME/beaengine/include + $SECURITY_TRANSFORMS_HOME/beaengine/beaengineSources/Includes/ + ''' + +#myenv.Append(CCFLAGS=" -Wall -W -Wextra -Wconversion ") + +myenv=myenv.Clone(CPPPATH=Split(cpppath)) +myenv.Append(CXXFLAGS = " -std=c++11 ") +lib=myenv.Library(libname, Split(files)) + +install=env.Install("$SECURITY_TRANSFORMS_HOME/lib/", lib) +Default(install) + diff --git a/libIRDB/src/decode/decode.cpp b/libIRDB/src/decode/decode.cpp new file mode 100644 index 000000000..a21f2d647 --- /dev/null +++ b/libIRDB/src/decode/decode.cpp @@ -0,0 +1,154 @@ + +#include <libIRDB-decode.hpp> + +#include <bea_deprecated.hpp> + +using namespace libIRDB; +using namespace std; + + +DecodedInstruction_t::DecodedInstruction_t(const Instruction_t* i) +{ + disasm_data=static_cast<void*>(new DISASM({})); + DISASM* d=(DISASM*)disasm_data; + disasm_length=::Disassemble(i,*d); +} + +DecodedInstruction_t::DecodedInstruction_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len) +{ + disasm_data=static_cast<void*>(new DISASM({})); + const auto endptr=data+max_len; + Disassemble(start_addr, data, max_len); +} + +DecodedInstruction_t::DecodedInstruction_t(const virtual_offset_t start_addr, const void *data, const void* endptr) +{ + disasm_data=static_cast<void*>(new DISASM({})); + const auto length=(char*)endptr-(char*)data; + Disassemble(start_addr,data,length); +} + +DecodedInstruction_t::DecodedInstruction_t(const DecodedInstruction_t& copy) +{ + DISASM* d=static_cast<DISASM*>(copy.disasm_data); + disasm_data=static_cast<void*>(new DISASM(*d)); + disasm_length=copy.disasm_length; +} + +DecodedInstruction_t::~DecodedInstruction_t() +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + delete d; + disasm_data=NULL; +} + +DecodedInstruction_t& DecodedInstruction_t::operator=(const DecodedInstruction_t& copy) +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + delete d; + disasm_data=NULL; + + d=static_cast<DISASM*>(copy.disasm_data); + disasm_data=static_cast<void*>(new DISASM(*d)); + disasm_length=copy.disasm_length; + return *this; +} + +void DecodedInstruction_t::Disassemble(const virtual_offset_t start_addr, const void *data, uint32_t max_len) +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + memset(d, 0, sizeof(DISASM)); + d->Options = NasmSyntax + PrefixedNumeral; + d->Archi = FileIR_t::GetArchitectureBitWidth(); + d->EIP = (UIntPtr)data; + d->SecurityBlock=max_len; + d->VirtualAddr = start_addr; + disasm_length=Disasm(d); + +} + +string DecodedInstruction_t::getDisassembly() const +{ + assert(valid()); + DISASM* d=static_cast<DISASM*>(disasm_data); + return string(d->CompleteInstr); +} + +bool DecodedInstruction_t::valid() const +{ + return disasm_length>=0; +} + +uint32_t DecodedInstruction_t::length() const +{ + assert(valid()); + return disasm_length; +} + + +bool DecodedInstruction_t::isBranch() const +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + return d->Instruction.BranchType!=0; +} + +bool DecodedInstruction_t::isUnconditionalBranch() const +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + return d->Instruction.BranchType==JmpType; +} + +bool DecodedInstruction_t::isConditionalBranch() const +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + assert(0); +} + +bool DecodedInstruction_t::isReturn() const +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + return d->Instruction.BranchType==RetType; +} + + +// 0-based. first operand is numbered 0. +DecodedOperand_t DecodedInstruction_t::getOperand(const int op_num) const +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + switch(op_num+1) + { + case 1: + return DecodedOperand_t(&d->Argument1); + case 2: + return DecodedOperand_t(&d->Argument2); + case 3: + return DecodedOperand_t(&d->Argument3); + case 4: + return DecodedOperand_t(&d->Argument4); + default: + throw std::out_of_range("op_num"); + } +} + + +string DecodedInstruction_t::getMnemonic() const +{ + DISASM* d=static_cast<DISASM*>(disasm_data); + const auto mnemonic=string(d->Instruction.Mnemonic); + return mnemonic.substr(0,mnemonic.size()-1); +} + +virtual_offset_t DecodedInstruction_t::getImmediate() const +{ + // find and return an immediate operand from this instruction + DISASM* d=static_cast<DISASM*>(disasm_data); + return d->Instruction.Immediat; +} + + +virtual_offset_t DecodedInstruction_t::getAddress() const +{ + // return anything that's explicitly an address, like a jmp/call target + DISASM* d=static_cast<DISASM*>(disasm_data); + return d->Instruction.AddrValue; +} diff --git a/libIRDB/src/decode/operand.cpp b/libIRDB/src/decode/operand.cpp new file mode 100644 index 000000000..b2d3c8125 --- /dev/null +++ b/libIRDB/src/decode/operand.cpp @@ -0,0 +1,168 @@ + +#include <libIRDB-decode.hpp> +#include <bea_deprecated.hpp> + +using namespace std; +using namespace libIRDB; + +// static functions +static uint32_t beaRegNoToIRDBRegNo(uint32_t regno) +{ + switch(regno) + { + case 0: return -1; // no reg -> -1 + case REG0: return 0; + case REG1: return 1; + case REG2: return 2; + case REG3: return 3; + case REG4: return 4; + case REG5: return 5; + case REG6: return 6; + case REG7: return 7; + case REG8: return 8; + case REG9: return 9; + case REG10: return 10; + case REG11: return 11; + case REG12: return 12; + case REG13: return 13; + case REG14: return 14; + case REG15: return 15; + default: assert(0); // odd number from BEA? + }; +} + + +// methods +DecodedOperand_t::DecodedOperand_t(void* arg_voidptr) +{ + ARGTYPE *arg_ptr=static_cast<ARGTYPE*>(arg_voidptr); + arg_data=(void*)new ARGTYPE(*arg_ptr); +} + +DecodedOperand_t::DecodedOperand_t(const DecodedOperand_t& copy) +{ + ARGTYPE *arg_ptr=static_cast<ARGTYPE*>(copy.arg_data); + arg_data=(void*)new ARGTYPE(*arg_ptr); +} + +DecodedOperand_t::~DecodedOperand_t() +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + delete t; + arg_data=NULL; +} + +DecodedOperand_t& DecodedOperand_t::operator=(const DecodedOperand_t& copy) +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + delete t; + arg_data=NULL; + ARGTYPE *arg_ptr=static_cast<ARGTYPE*>(copy.arg_data); + arg_data=(void*)new ARGTYPE(*arg_ptr); + + return *this; +} + +bool DecodedOperand_t::isConstant() const +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + assert(t); + return (t->ArgType & CONSTANT_TYPE)!=0; +} + +string DecodedOperand_t::getString() const +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + assert(t); + return t->ArgMnemonic; +} + + +bool DecodedOperand_t::isWrite() const +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return t->AccessMode==WRITE; +} + +bool DecodedOperand_t::isRegister() const +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return (t->ArgType®ISTER_TYPE)==REGISTER_TYPE; +} + + + +uint32_t DecodedOperand_t::getRegNumber() const +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + if(!isRegister()) + throw std::logic_error("getRegNumber called on not register"); + const auto regno=(t->ArgType)&0xFFFF; + + return beaRegNoToIRDBRegNo(regno); +} + +bool DecodedOperand_t::isMemory() const +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return (t->ArgType&MEMORY_TYPE)==MEMORY_TYPE; +} + +bool DecodedOperand_t::hasBaseRegister() const +{ + if(!isMemory()) + throw std::logic_error("hasBaseRegister called on not memory operand"); + + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return t->Memory.BaseRegister!=0; +} + +bool DecodedOperand_t::hasIndexRegister() const +{ + if(!isMemory()) + throw std::logic_error("hasIndexRegister called on not memory operand"); + + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return t->Memory.IndexRegister!=0; +} + +uint32_t DecodedOperand_t::getBaseRegister() const +{ + if(!isMemory() || !hasBaseRegister()) + throw std::logic_error("getBaseRegister called on not memory operand"); + + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return beaRegNoToIRDBRegNo(t->Memory.BaseRegister); +} + +uint32_t DecodedOperand_t::getIndexRegister() const +{ + if(!isMemory() || !hasIndexRegister()) + throw std::logic_error("getIndexRegister called on not memory operand"); + + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return beaRegNoToIRDBRegNo(t->Memory.IndexRegister); +} + +uint32_t DecodedOperand_t::getScaleValue() const +{ + if(!isMemory()) + throw std::logic_error("getScaleValue called on not memory operand"); + + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return t->Memory.Scale; /* 0 indicates no scale */ +} + +virtual_offset_t DecodedOperand_t::getMemoryDisplacement() const +{ + if(!isMemory()) + throw std::logic_error("GetBaseRegister called on not memory operand"); + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return (virtual_offset_t)t->Memory.Displacement; +} + +bool DecodedOperand_t::isPcrel() const +{ + ARGTYPE *t=static_cast<ARGTYPE*>(arg_data); + return (t->ArgType&RELATIVE_)==RELATIVE_; +} diff --git a/libIRDB/test/SConscript b/libIRDB/test/SConscript index 01ec9b4d8..0670b8c24 100644 --- a/libIRDB/test/SConscript +++ b/libIRDB/test/SConscript @@ -18,7 +18,7 @@ if 'build_tools' not in myenv or myenv['build_tools'] is None or int(myenv['buil ''' LIBPATH="$SECURITY_TRANSFORMS_HOME/lib" - LIBS=Split( env.subst('$BASE_IRDB_LIBS')+ " IRDB-cfg IRDB-util MEDSannotation") + LIBS=Split( env.subst('$BASE_IRDB_LIBS')+ " IRDB-cfg IRDB-util IRDB-decode MEDSannotation") print "The libs for libIRDB/tests are:" print LIBS diff --git a/libIRDB/test/fill_in_cfg.cpp b/libIRDB/test/fill_in_cfg.cpp index 9326b23fd..a93f559bd 100644 --- a/libIRDB/test/fill_in_cfg.cpp +++ b/libIRDB/test/fill_in_cfg.cpp @@ -30,9 +30,9 @@ #include <exeio.h> #include "elfio/elfio.hpp" #include "elfio/elfio_dump.hpp" -#include "beaengine/BeaEngine.h" #include "eh_frame.hpp" -#include <bea_deprecated.hpp> +// #include <bea_deprecated.hpp> +#include <libIRDB-decode.hpp> int odd_target_count=0; int bad_target_count=0; @@ -80,7 +80,7 @@ void populate_instruction_map void set_fallthrough ( map< pair<db_id_t,virtual_offset_t>, Instruction_t*> &insnMap, - DISASM *disasm, Instruction_t *insn, FileIR_t *firp + DecodedInstruction_t *disasm, Instruction_t *insn, FileIR_t *firp ) { assert(disasm); @@ -91,8 +91,11 @@ void set_fallthrough // check for branches with targets if( - (disasm->Instruction.BranchType==JmpType) || // it is a unconditional branch - (disasm->Instruction.BranchType==RetType) // or a return + //(disasm->Instruction.BranchType==JmpType) || // it is a unconditional branch + //(disasm->Instruction.BranchType==RetType) // or a return + + (disasm->isUnconditionalBranch() ) || // it is a unconditional branch + (disasm->isReturn()) // or a return ) { // this is a branch with no fallthrough instruction @@ -128,7 +131,7 @@ void set_fallthrough void set_target ( map< pair<db_id_t,virtual_offset_t>, Instruction_t*> &insnMap, - DISASM *disasm, Instruction_t *insn, FileIR_t *firp + DecodedInstruction_t *disasm, Instruction_t *insn, FileIR_t *firp ) { @@ -140,9 +143,12 @@ void set_target // check for branches with targets if( - (disasm->Instruction.BranchType!=0) && // it is a branch - (disasm->Instruction.BranchType!=RetType) && // and not a return - (disasm->Argument1.ArgType & CONSTANT_TYPE)!=0 // and has a constant argument type 1 + //(disasm->Instruction.BranchType!=0) && // it is a branch + //(disasm->Instruction.BranchType!=RetType) && // and not a return + //(disasm->Argument1.ArgType & CONSTANT_TYPE)!=0 // and has a constant argument type 1 + (disasm->isBranch()) && // it is a branch + (!disasm->isReturn()) && // and not a return + (disasm->getOperand(0).isConstant()) // and has a constant argument type 1 ) { // cout<<"Found direct jump with addr=" << insn->GetAddress()->GetVirtualOffset() << @@ -150,7 +156,8 @@ void set_target // disasm->Argument1.ArgMnemonic<<"."<<endl; /* get the offset */ - virtual_offset_t virtual_offset=strtoul(disasm->Argument1.ArgMnemonic, NULL, 16); + // virtual_offset_t virtual_offset=strtoul(disasm->Argument1.ArgMnemonic, NULL, 16); + virtual_offset_t virtual_offset=strtoul(disasm->getOperand(0).getString().c_str(), NULL, 16); /* create a pair of offset/file */ pair<db_id_t,virtual_offset_t> p(insn->GetAddress()->GetFileID(),virtual_offset); @@ -267,30 +274,37 @@ void add_new_instructions(FileIR_t *firp) virtual_offset_t offset_into_section=missed_address-elfiop->sections[secndx]->get_address(); /* disassemble the instruction */ - DISASM disasm; - memset(&disasm, 0, sizeof(DISASM)); + DecodedInstruction_t disasm(missed_address, (void*)&data[offset_into_section], elfiop->sections[secndx]->get_size()-offset_into_section ); + + /* + memset(&disasm, 0, sizeof(DecodeInstruction_t)); disasm.Options = NasmSyntax + PrefixedNumeral; disasm.Archi = firp->GetArchitectureBitWidth(); disasm.EIP = (UIntPtr) &data[offset_into_section]; disasm.SecurityBlock=elfiop->sections[secndx]->get_size()-offset_into_section; disasm.VirtualAddr = missed_address; - int instr_len = Disasm(&disasm); + */ + + + + + const auto instr_len = disasm.length(); /* bea docs say OUT_OF_RANGE and UNKNOWN_OPCODE are defined, but they aren't */ -#define OUT_OF_RANGE (0) -#define UNKNOWN_OPCODE (-1) +// #define OUT_OF_RANGE (0) +// #define UNKNOWN_OPCODE (-1) /* if we found the instruction, but can't disassemble it, then we skip out for now */ - if(instr_len==OUT_OF_RANGE || instr_len==UNKNOWN_OPCODE) + if(!disasm.valid()) // instr_len==OUT_OF_RANGE || instr_len==UNKNOWN_OPCODE) { if(getenv("VERBOSE_CFG")) cout<<"Found invalid insn at "<<missed_address<<endl; break; } else if(getenv("VERBOSE_CFG")) - cout<<"Found valid insn at "<<missed_address<<": "<<disasm.CompleteInstr<<endl; + cout<<"Found valid insn at "<<missed_address<<": "<<disasm.getDisassembly()<<endl; /* intel instructions have a max size of 16 */ assert(1<=instr_len && instr_len<=16); @@ -316,7 +330,7 @@ void add_new_instructions(FileIR_t *firp) assert(newinsn); newinsn->SetAddress(newaddr); newinsn->SetDataBits(newinsnbits); - newinsn->SetComment(string(disasm.CompleteInstr)+string(" from fill_in_cfg ")); + newinsn->SetComment(disasm.getDisassembly()+string(" from fill_in_cfg ")); newinsn->SetAddress(newaddr); /* fallthrough/target/is indirect will be set later */ @@ -365,10 +379,10 @@ void fill_in_cfg(FileIR_t *firp) ) { Instruction_t *insn=*it; - DISASM disasm; - memset(&disasm, 0, sizeof(DISASM)); + DecodedInstruction_t disasm(insn); + //memset(&disasm, 0, sizeof(DISASM)); - int instr_len = Disassemble(insn,disasm); + const auto instr_len = disasm.length(); assert(instr_len==insn->GetDataBits().size()); @@ -494,21 +508,6 @@ void fill_in_scoops(FileIR_t *firp) cout<<"Skipping scoop for section (executable) "<<elfiop->sections[secndx]->get_name()<<endl; continue; } -#if 0 - // we decided to skip BSS for a bad reason. trying again. - if(elfiop->sections[secndx]->isBSS()) - { - cout<<"Skipping bss section: "<<elfiop->sections[secndx]->get_name()<<endl; - continue; - } - // we decided to skip tls for a bad reason. trying again. - if(elfiop->sections[secndx]->isThreadLocal()) - { - cout<<"Skipping tls section (executable) "<<elfiop->sections[secndx]->get_name()<<endl; - continue; - } -#endif - /* name */ string name=elfiop->sections[secndx]->get_name(); diff --git a/libIRDB/test/fill_in_indtargs.cpp b/libIRDB/test/fill_in_indtargs.cpp index cbc8aa6f4..869a9b0a6 100644 --- a/libIRDB/test/fill_in_indtargs.cpp +++ b/libIRDB/test/fill_in_indtargs.cpp @@ -38,11 +38,10 @@ #include <elf.h> #include <exeio.h> -#include "beaengine/BeaEngine.h" #include "check_thunks.hpp" #include "fill_in_indtargs.hpp" #include "libMEDSAnnotation.h" -#include <bea_deprecated.hpp> +#include <libIRDB-decode.hpp> using namespace libIRDB; using namespace std; @@ -89,12 +88,12 @@ static long total_unpins=0; */ -static void check_for_PIC_switch_table32_type2(Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases); -static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases); -static void check_for_PIC_switch_table32(FileIR_t*, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases); -static void check_for_PIC_switch_table64(FileIR_t*, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop); -static void check_for_nonPIC_switch_table(FileIR_t*, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop); -static void check_for_nonPIC_switch_table_pattern2(FileIR_t*, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop); +static void check_for_PIC_switch_table32_type2(Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases); +static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases); +static void check_for_PIC_switch_table32(FileIR_t*, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases); +static void check_for_PIC_switch_table64(FileIR_t*, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop); +static void check_for_nonPIC_switch_table(FileIR_t*, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop); +static void check_for_nonPIC_switch_table_pattern2(FileIR_t*, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop); extern void read_ehframe(FileIR_t* firp, EXEIO::exeio* ); @@ -205,20 +204,20 @@ EXEIO::section* find_section(virtual_offset_t addr, EXEIO::exeio *elfiop) return NULL; } -void handle_argument(ARGTYPE *arg, Instruction_t* insn, ibt_provenance_t::provtype_t pt = ibt_provenance_t::ibtp_text) +void handle_argument(const DecodedOperand_t *arg, Instruction_t* insn, ibt_provenance_t::provtype_t pt = ibt_provenance_t::ibtp_text) { - if( (arg->ArgType&MEMORY_TYPE) == MEMORY_TYPE ) + if(arg->isMemory()) // (arg->ArgType&MEMORY_TYPE) == MEMORY_TYPE ) { - if((arg->ArgType&RELATIVE_)==RELATIVE_) + if(arg->isPcrel()) // (arg->ArgType&RELATIVE_)==RELATIVE_) { assert(insn); assert(insn->GetAddress()); - possible_target(arg->Memory.Displacement+insn->GetAddress()->GetVirtualOffset()+ + possible_target(arg->getMemoryDisplacement() /*arg->Memory.Displacement*/+insn->GetAddress()->GetVirtualOffset()+ insn->GetDataBits().length(), insn->GetAddress()->GetVirtualOffset(), pt); } else { - possible_target(arg->Memory.Displacement, insn->GetAddress()->GetVirtualOffset(), pt); + possible_target(arg->getMemoryDisplacement() /* arg->Memory.Displacement*/, insn->GetAddress()->GetVirtualOffset(), pt); } } } @@ -286,9 +285,9 @@ void mark_targets(FileIR_t *firp) #ifdef MOMVED bool IsParameterWrite(FileIR_t *firp,Instruction_t* insn, string& output_dst) { - DISASM d; - Disassemble(insn,d); - if(d.Argument1.AccessMode!=WRITE) + DecodedInstruction_t d(insn); + (void)WRITE; // makes ure bea header isn't included. + if(!d.getOperand(0).IsWrite()) // d.Argument1.AccessMode!=WRITE) { return false; } @@ -297,17 +296,18 @@ bool IsParameterWrite(FileIR_t *firp,Instruction_t* insn, string& output_dst) if(firp->GetArchitectureBitWidth()==64) { // if it's a register - if((d.Argument1.ArgType®ISTER_TYPE)==REGISTER_TYPE) + if(d.getOperand(0).isRegister()) // (d.Argument1.ArgType®ISTER_TYPE)==REGISTER_TYPE) { - int regno=(d.Argument1.ArgType)&0xFFFF; + // int regno=(d.Argument1.ArgType)&0xFFFF + const auto regno=d.getOperand(0).getRegNumber(); switch(regno) { - case REG7: // rdi - case REG6: // rsi - case REG2: // rdx - case REG1: // rcx - case REG8: // r8 - case REG9: // r9 + case 7 /*REG7*/: // rdi + case 6 /*REG6*/: // rsi + case 2 /*REG2*/: // rdx + case 1 /*REG1*/: // rcx + case 8 /*REG8*/: // r8 + case 9 /*REG9*/: // r9 output_dst=d.Argument1.ArgMnemonic; return true; @@ -323,19 +323,19 @@ bool IsParameterWrite(FileIR_t *firp,Instruction_t* insn, string& output_dst) // check for memory type - if((d.Argument1.ArgType&MEMORY_TYPE)!=MEMORY_TYPE) + if(!d.isMemory()) // (d.Argument1.ArgType&MEMORY_TYPE)!=MEMORY_TYPE) return false; // check that base reg is esp. - if(d.Argument1.Memory.BaseRegister != REG4) + if(d->getOperand(0)->hasBaseRegister() && d->getOperand(0)->getBaseRegister() != 4) // d.Argument1.Memory.BaseRegister != REG4) return false; // check that there's no index reg - if(d.Argument1.Memory.IndexRegister != 0) + if(! d->getOperand(0).hasIndexRegister()) // d.Argument1.Memory.IndexRegister != 0) return false; // get k out of [esp + k ] - unsigned int k=d.Argument1.Memory.Displacement; + unsigned int k=d->getOperand(0).getMemoryDisplacement(); // d.Argument1.Memory.Displacement; // check that we know the frame layout. if(insn->GetFunction() == NULL) @@ -343,7 +343,7 @@ bool IsParameterWrite(FileIR_t *firp,Instruction_t* insn, string& output_dst) if(k < insn->GetFunction()->GetOutArgsRegionSize()) { - output_dst=string("[")+d.Argument1.ArgMnemonic+string("]"); + output_dst=string("[")+d->getOperand(0).getString() /* d.Argument1.ArgMnemonic*/ +string("]"); return true; } @@ -357,9 +357,9 @@ bool CallToPrintfFollows(FileIR_t *firp, Instruction_t* insn, const string& arg_ { for(Instruction_t* ptr=insn->GetFallthrough(); ptr!=NULL; ptr=ptr->GetFallthrough()) { - DISASM d; - Disassemble(ptr,d); - if(d.Instruction.Mnemonic == string("call ")) + DecodedInstruction_t d(ptr); + // Disassemble(ptr,d); + if(d.getMnemonic() == string("call")) { // check we have a target if(ptr->GetTarget()==NULL) @@ -378,7 +378,7 @@ bool CallToPrintfFollows(FileIR_t *firp, Instruction_t* insn, const string& arg_ } // found reference to argstring, assume it's a write and exit - if(string(d.CompleteInstr).find(arg_str)!= string::npos) + if(d.getDisassembly()/*string(d.CompleteInstr)*/.find(arg_str)!= string::npos) return false; } @@ -406,8 +406,9 @@ void get_instruction_targets(FileIR_t *firp, EXEIO::exeio* elfiop, const set<vir ) { Instruction_t *insn=*it; - DISASM disasm; - virtual_offset_t instr_len = Disassemble(insn,disasm); + // DISASM disasm; + DecodedInstruction_t disasm(insn); + virtual_offset_t instr_len = disasm.length(); // Disassemble(insn,disasm); assert(instr_len==insn->GetDataBits().size()); @@ -426,7 +427,7 @@ void get_instruction_targets(FileIR_t *firp, EXEIO::exeio* elfiop, const set<vir check_for_nonPIC_switch_table_pattern2(firp, insn,disasm, elfiop); /* other branches can't indicate an indirect branch target */ - if(disasm.Instruction.BranchType) + if(disasm.isBranch()) // disasm.Instruction.BranchType) continue; ibt_provenance_t::provtype_t prov=0; @@ -436,15 +437,19 @@ void get_instruction_targets(FileIR_t *firp, EXEIO::exeio* elfiop, const set<vir } else { - cout<<"TextToPrintf analysis of '"<<disasm.CompleteInstr<<"' successful at " <<hex<<insn->GetAddress()->GetVirtualOffset()<<endl; + cout<<"TextToPrintf analysis of '"<<disasm.getDisassembly()<<"' successful at " <<hex<<insn->GetAddress()->GetVirtualOffset()<<endl; prov=ibt_provenance_t::ibtp_texttoprintf; } /* otherwise, any immediate is a possible branch target */ - possible_target(disasm.Instruction.Immediat,0, prov); - handle_argument(&disasm.Argument1, insn, prov); - handle_argument(&disasm.Argument2, insn, prov); - handle_argument(&disasm.Argument3, insn, prov); - handle_argument(&disasm.Argument4, insn, prov); + possible_target(disasm.getImmediate() /* Instruction.Immediat*/ ,0, prov); + const auto op0=disasm.getOperand(0); + const auto op1=disasm.getOperand(1); + const auto op2=disasm.getOperand(2); + const auto op3=disasm.getOperand(3); + handle_argument(&op0, insn, prov); + handle_argument(&op1, insn, prov); + handle_argument(&op2, insn, prov); + handle_argument(&op3, insn, prov); } } @@ -566,7 +571,6 @@ void print_targets_oneline() set<Instruction_t*> find_in_function(string needle, Function_t *haystack) { - DISASM disasm; regex_t preg; set<Instruction_t*>::const_iterator fit; set<Instruction_t*> found_instructions; @@ -577,10 +581,12 @@ set<Instruction_t*> find_in_function(string needle, Function_t *haystack) for (fit; fit != haystack->GetInstructions().end(); fit++) { Instruction_t *candidate = *fit; - Disassemble(candidate,disasm); + //DISASM disasm; + //Disassemble(candidate,disasm); + DecodedInstruction_t disasm(candidate); // check it's the requested type - if(regexec(&preg, disasm.CompleteInstr, 0, NULL, 0) == 0) + if(regexec(&preg, disasm.getDisassembly().c_str() /*CompleteInstr*/, 0, NULL, 0) == 0) { found_instructions.insert(candidate); } @@ -591,7 +597,6 @@ set<Instruction_t*> find_in_function(string needle, Function_t *haystack) bool backup_until(const char* insn_type_regex, Instruction_t *& prev, Instruction_t* orig, bool recursive=false) { - DISASM disasm; prev=orig; regex_t preg; @@ -606,10 +611,12 @@ bool backup_until(const char* insn_type_regex, Instruction_t *& prev, Instructio // get I7's disassembly - Disassemble(prev,disasm); + //DISASM disasm; + //Disassemble(prev,disasm); + DecodedInstruction_t disasm(prev); // check it's the requested type - if(regexec(&preg, disasm.CompleteInstr, 0, NULL, 0) == 0) + if(regexec(&preg, disasm.getDisassembly().c_str() /*CompleteInstr*/, 0, NULL, 0) == 0) { regfree(&preg); return true; @@ -625,10 +632,10 @@ bool backup_until(const char* insn_type_regex, Instruction_t *& prev, Instructio it!=preds[myprev].end(); ++it) { Instruction_t* pred=*it; - - Disassemble(pred,disasm); + //Disassemble(pred,disasm); + DecodedInstruction_t disasm(pred); // check it's the requested type - if(regexec(&preg, disasm.CompleteInstr, 0, NULL, 0) == 0) + if(regexec(&preg, disasm.getDisassembly().c_str()/*CompleteInstr*/, 0, NULL, 0) == 0) { regfree(&preg); return true; @@ -650,7 +657,7 @@ bool backup_until(const char* insn_type_regex, Instruction_t *& prev, Instructio /* * check_for_PIC_switch_table32 - look for switch tables in PIC code for 32-bit code. */ -static void check_for_PIC_switch_table32(FileIR_t *firp, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t> &thunk_bases) +static void check_for_PIC_switch_table32(FileIR_t *firp, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t> &thunk_bases) { ibt_provenance_t prov=ibt_provenance_t::ibtp_switchtable_type1; @@ -683,15 +690,15 @@ I7: 08069391 <_gedit_app_ready+0x91> ret Instruction_t* I4=NULL; Instruction_t* I3=NULL; // check if I5 is a jump - if(strstr(disasm.Instruction.Mnemonic, "jmp")==NULL) + if(strstr(disasm.getMnemonic().c_str() /*Instruction.Mnemonic*/, "jmp")==NULL) return; // return if it's a jump to a constant address, these are common - if(disasm.Argument1.ArgType&CONSTANT_TYPE) + if(disasm.getOperand(0).isConstant() /*disasm.Argument1.ArgType&CONSTANT_TYPE*/) return; // return if it's a jump to a memory address - if(disasm.Argument1.ArgType&MEMORY_TYPE) + if(disasm.getOperand(0).isMemory() /*disasm.Argument1.ArgType&MEMORY_TYPE*/) return; // has to be a jump to a register now @@ -713,23 +720,26 @@ I7: 08069391 <_gedit_app_ready+0x91> ret } else { - DISASM dcmp; - Disassemble(Icmp,dcmp); - table_size = dcmp.Instruction.Immediat; + //DISASM dcmp; + //Disassemble(Icmp,dcmp); + DecodedInstruction_t dcmp(Icmp); + table_size = dcmp.getImmediate(); //Instruction.Immediat; if(table_size<=0) table_size=std::numeric_limits<int>::max(); } // grab the offset out of the lea. - DISASM d2; - Disassemble(I3,d2); + //DISASM d2; + //Disassemble(I3,d2); + DecodedInstruction_t d2(I3); // get the offset from the thunk - virtual_offset_t table_offset=d2.Instruction.AddrValue; + virtual_offset_t table_offset=d2.getAddress(); // d2.Instruction.AddrValue; if(table_offset==0) return; -cout<<hex<<"Found switch dispatch at "<<I3->GetAddress()->GetVirtualOffset()<< " with table_offset="<<table_offset<<" and table_size="<<table_size<<endl; + cout<<hex<<"Found switch dispatch at "<<I3->GetAddress()->GetVirtualOffset()<< " with table_offset="<<table_offset + <<" and table_size="<<table_size<<endl; /* iterate over all thunk_bases/module_starts */ for(set<virtual_offset_t>::iterator it=thunk_bases.begin(); it!=thunk_bases.end(); ++it) @@ -813,7 +823,7 @@ cout<<hex<<"Found switch dispatch at "<<I3->GetAddress()->GetVirtualOffset()<< " } -static void check_for_PIC_switch_table32_type2(Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t> &thunk_bases) +static void check_for_PIC_switch_table32_type2(Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t> &thunk_bases) { ibt_provenance_t prov=ibt_provenance_t::ibtp_switchtable_type2; #if 0 @@ -830,15 +840,16 @@ I5: 0x809900e <text_handler+51>: jmp ecx Instruction_t* I4=NULL; Instruction_t* I3=NULL; // check if I5 is a jump - if(strstr(disasm.Instruction.Mnemonic, "jmp")==NULL) + if(strstr(disasm.getMnemonic().c_str() /*disasm.Instruction.Mnemonic*/, "jmp")==NULL) return; // return if it's a jump to a constant address, these are common - if(disasm.Argument1.ArgType&CONSTANT_TYPE) + if(disasm.getOperand(0).isConstant() /*disasm.Argument1.ArgType&CONSTANT_TYPE*/) return; // return if it's a jump to a memory address - if(disasm.Argument1.ArgType&MEMORY_TYPE) + //if(disasm.Argument1.ArgType&MEMORY_TYPE) + if(disasm.getOperand(0).isMemory()) return; // has to be a jump to a register now @@ -852,11 +863,12 @@ I5: 0x809900e <text_handler+51>: jmp ecx return; // grab the offset out of the lea. - DISASM d2; - Disassemble(I3,d2); + //DISASM d2; + //Disassemble(I3,d2); + DecodedInstruction_t d2(I3); // get the offset from the thunk - virtual_offset_t table_offset=d2.Instruction.AddrValue; + virtual_offset_t table_offset=d2.getAddress(); // d2.Instruction.AddrValue; if(table_offset==0) return; @@ -933,30 +945,36 @@ cout<<hex<<"Found (type2) switch dispatch at "<<I3->GetAddress()->GetVirtualOffs * * nb: also works for 64-bit. */ -static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t> &thunk_bases) +static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t> &thunk_bases) { int ptrsize=firp->GetArchitectureBitWidth()/8; ibt_provenance_t prov=ibt_provenance_t::ibtp_switchtable_type3; Instruction_t* I5=insn; // check if I5 is a jump - if(strstr(disasm.Instruction.Mnemonic, "jmp")==NULL) + //if(strstr(disasm.Instruction.Mnemonic, "jmp")==NULL) + if(strstr(disasm.getMnemonic().c_str()/*Instruction.Mnemonic*/, "jmp")==NULL) return; // return if it's not a jump to a memory address - if(!(disasm.Argument1.ArgType&MEMORY_TYPE)) + //if(!(disasm.Argument1.ArgType&MEMORY_TYPE)) + if(!(disasm.getOperand(0).isMemory())) return; /* return if there's no displacement */ - if(disasm.Argument1.Memory.Displacement==0) + //if(disasm.Argument1.Memory.Displacement==0) + if(disasm.getOperand(0).getMemoryDisplacement()==0) return; - if(disasm.Argument1.Memory.Scale!=ptrsize) + //if(disasm.Argument1.Memory.Scale!=ptrsize) + // if(disasm.getOperand(0).getScaleValue()!=ptrsize) + if(!disasm.getOperand(0).hasIndexRegister() || disasm.getOperand(0).getScaleValue()!=ptrsize) return; // grab the table base out of the jmp. - virtual_offset_t table_base=disasm.Argument1.Memory.Displacement; - if((disasm.Argument1.ArgType&RELATIVE_)) + virtual_offset_t table_base=disasm.getOperand(0).getMemoryDisplacement();//disasm.Argument1.Memory.Displacement; + //if((disasm.Argument1.ArgType&RELATIVE_)) + if(disasm.getOperand(0).isPcrel()) table_base+=insn->GetDataBits().size()+insn->GetAddress()->GetVirtualOffset(); if(table_base==0) @@ -1049,13 +1067,12 @@ static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* in /* if there's no base register and no index reg, */ /* then this jmp can't have more than one valid table entry */ - if( disasm.Argument1.Memory.BaseRegister==0 && disasm.Argument1.Memory.IndexRegister==0 ) + //if( disasm.Argument1.Memory.BaseRegister==0 && disasm.Argument1.Memory.IndexRegister==0 ) + if( !disasm.getOperand(0).hasBaseRegister() && !disasm.getOperand(0).hasIndexRegister()) { /* but the table can have 1 valid entry. */ if(pSec->get_name()==".got.plt") { - - Instruction_t *ibtarget = lookupInstruction(firp, table_entry); if(ibtarget) { @@ -1067,7 +1084,7 @@ static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* in #endif possible_target(table_entry,table_base+0*ptrsize, ibt_provenance_t::ibtp_gotplt); if(getenv("IB_VERBOSE")!=0) - cout<<hex<<"Found plt dispatch ("<<disasm.CompleteInstr<<"') at "<<I5->GetAddress()->GetVirtualOffset()<< endl; + cout<<hex<<"Found plt dispatch ("<<disasm.getDisassembly()<<"') at "<<I5->GetAddress()->GetVirtualOffset()<< endl; return; } } @@ -1076,14 +1093,16 @@ static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* in else possible_target(table_entry,table_base+0*ptrsize, ibt_provenance_t::ibtp_rodata); if(getenv("IB_VERBOSE")!=0) - cout<<hex<<"Found constant-memory dispatch from non- .got.plt location ("<<disasm.CompleteInstr<<"') at "<<I5->GetAddress()->GetVirtualOffset()<< endl; + cout<<hex<<"Found constant-memory dispatch from non- .got.plt location ("<<disasm.getDisassembly()<<"') at " + <<I5->GetAddress()->GetVirtualOffset()<< endl; return; } if(!is_possible_target(table_entry,table_base+i*ptrsize)) { if(getenv("IB_VERBOSE")!=0) { - cout<<hex<<"Found (type3) candidate for switch dispatch for '"<<disasm.CompleteInstr<<"' at "<<I5->GetAddress()->GetVirtualOffset()<< " with table_base="<<table_base<<endl; + cout<<hex<<"Found (type3) candidate for switch dispatch for '"<<disasm.getDisassembly()<<"' at " + <<I5->GetAddress()->GetVirtualOffset()<< " with table_base="<<table_base<<endl; cout<<"Found table_entry "<<hex<<table_entry<<" is not valid\n"<<endl; } return; @@ -1146,7 +1165,7 @@ static void check_for_PIC_switch_table32_type3(FileIR_t* firp, Instruction_t* in * if so, see if we can trace back a few instructions to find a * the start of the table. */ -static void check_for_PIC_switch_table64(FileIR_t* firp, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop) +static void check_for_PIC_switch_table64(FileIR_t* firp, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop) { ibt_provenance_t prov=ibt_provenance_t::ibtp_switchtable_type4; /* here's the pattern we're looking for */ @@ -1219,14 +1238,14 @@ Note: Here the operands of the add are reversed, so lookup code was not finding Instruction_t* I5=NULL; Instruction_t* I1=NULL; // check if I8 is a jump - if(strstr(disasm.Instruction.Mnemonic, "jmp")==NULL) + if(strstr(disasm.getMnemonic().c_str()/*Instruction.Mnemonic*/, "jmp")==NULL) return; // return if it's a jump to a constant address, these are common - if(disasm.Argument1.ArgType&CONSTANT_TYPE) + if(disasm.getOperand(0).isConstant()) //disasm.Argument1.ArgType&CONSTANT_TYPE) return; // return if it's a jump to a memory address - if(disasm.Argument1.ArgType&MEMORY_TYPE) + if(disasm.getOperand(0).isMemory()) // Argument1.ArgType&MEMORY_TYPE) return; // has to be a jump to a register now @@ -1239,25 +1258,26 @@ Note: Here the operands of the add are reversed, so lookup code was not finding * Backup and find the instruction that's an add or lea before I8. */ table_index_str = "(add "; - table_index_str += disasm.Argument1.ArgMnemonic; + table_index_str += disasm.getOperand(0).getString(); //Argument1.ArgMnemonic; table_index_str += "|lea "; - table_index_str += disasm.Argument1.ArgMnemonic; + table_index_str += disasm.getOperand(0).getString(); //Argument1.ArgMnemonic; table_index_str += ")"; - const auto cmp_str = string("cmp ") + disasm.Argument1.ArgMnemonic; - const auto cmp_str2 = string("cmp ") + disasm.Argument2.ArgMnemonic; + const auto cmp_str = string("cmp ") + disasm.getOperand(0).getString(); //Argument1.ArgMnemonic; + const auto cmp_str2 = string("cmp ") + disasm.getOperand(1).getString(); //Argument2.ArgMnemonic; if(!backup_until(table_index_str.c_str(), I7, I8)) return; - Disassemble(I7,disasm); + // Disassemble(I7,disasm); + disasm=DecodedInstruction_t(I7); // Check if lea instruction is being used as add (scale=1, disp=0) - if(strstr(disasm.Instruction.Mnemonic, "lea")) + if(strstr(disasm.getMnemonic().c_str() /* Instruction.Mnemonic*/, "lea")) { - if(!(disasm.Argument2.ArgType&MEMORY_TYPE)) + if(!(disasm.getOperand(1).isMemory() /*disasm.Argument2.ArgType&MEMORY_TYPE)*/)) return; - if(!(disasm.Argument2.Memory.Scale == 1 && disasm.Argument2.Memory.Displacement == 0)) + if(!(disasm.getOperand(1).getScaleValue() /* .Argument2.Memory.Scale */ == 1 && disasm.getOperand(1).getMemoryDisplacement() /*Argument2.Memory.Displacement*/ == 0)) return; } // backup and find the instruction that's an movsxd before I7 @@ -1270,8 +1290,9 @@ Note: Here the operands of the add are reversed, so lookup code was not finding string lea_string="lea "; - Disassemble(I6,disasm); - if( (disasm.Argument2.ArgType&MEMORY_TYPE) == MEMORY_TYPE) + // Disassemble(I6,disasm); + disasm=DecodedInstruction_t(I6); + if( disasm.getOperand(1).isMemory() /* (disasm.Argument2.ArgType&MEMORY_TYPE) == MEMORY_TYPE*/) { // try to be smarter for memory types. @@ -1281,24 +1302,26 @@ Note: Here the operands of the add are reversed, so lookup code was not finding * for the base of the jump table. */ string base_reg=""; - switch(disasm.Argument2.Memory.BaseRegister) - { - case REG0: base_reg="rax"; break; - case REG1: base_reg="rcx"; break; - case REG2: base_reg="rdx"; break; - case REG3: base_reg="rbx"; break; - case REG4: base_reg="rsp"; break; - case REG5: base_reg="rbp"; break; - case REG6: base_reg="rsi"; break; - case REG7: base_reg="rdi"; break; - case REG8: base_reg="r8"; break; - case REG9: base_reg="r9"; break; - case REG10: base_reg="r10"; break; - case REG11: base_reg="r11"; break; - case REG12: base_reg="r12"; break; - case REG13: base_reg="r13"; break; - case REG14: base_reg="r14"; break; - case REG15: base_reg="r15"; break; + if(!disasm.getOperand(1).hasBaseRegister() /*Argument2.Memory.BaseRegister*/) + return; + switch(disasm.getOperand(1).getBaseRegister() /*Argument2.Memory.BaseRegister*/) + { + case 0/*REG0*/: base_reg="rax"; break; + case 1/*REG1*/: base_reg="rcx"; break; + case 2/*REG2*/: base_reg="rdx"; break; + case 3/*REG3*/: base_reg="rbx"; break; + case 4/*REG4*/: base_reg="rsp"; break; + case 5/*REG5*/: base_reg="rbp"; break; + case 6/*REG6*/: base_reg="rsi"; break; + case 7/*REG7*/: base_reg="rdi"; break; + case 8/*REG8*/: base_reg="r8"; break; + case 9/*REG9*/: base_reg="r9"; break; + case 10/*REG10*/: base_reg="r10"; break; + case 11/*REG11*/: base_reg="r11"; break; + case 12/*REG12*/: base_reg="r12"; break; + case 13/*REG13*/: base_reg="r13"; break; + case 14/*REG14*/: base_reg="r14"; break; + case 15/*REG15*/: base_reg="r15"; break; default: // no base register; return; @@ -1352,12 +1375,13 @@ Note: Here the operands of the add are reversed, so lookup code was not finding for (found_leas_it; found_leas_it != found_leas.end(); found_leas_it++) { Instruction_t *I5_cur = *found_leas_it; - Disassemble(I5_cur,disasm); + //Disassemble(I5_cur,disasm); + disasm=DecodedInstruction_t(I5_cur); - if(!(disasm.Argument2.ArgType&MEMORY_TYPE)) + if(!(disasm.getOperand(1).isMemory() /*Argument2.ArgType&MEMORY_TYPE*/)) //return; continue; - if(!(disasm.Argument2.ArgType&RELATIVE_)) + if(!(disasm.getOperand(1).isPcrel() /*Argument2.ArgType&RELATIVE_*/)) //return; continue; @@ -1365,7 +1389,7 @@ Note: Here the operands of the add are reversed, so lookup code was not finding // instruction address (and include the instruction's size, etc. // but, fix_calls has already removed this oddity so we can relocate // the instruction. - virtual_offset_t D1=strtol(disasm.Argument2.ArgMnemonic, NULL, 16); + virtual_offset_t D1=strtol(disasm.getOperand(1).getString().c_str()/*Argument2.ArgMnemonic*/, NULL, 16); // find the section with the data table EXEIO::section *pSec=find_section(D1,elfiop); @@ -1385,25 +1409,27 @@ Note: Here the operands of the add are reversed, so lookup code was not finding int table_size = 0; if(backup_until(cmp_str.c_str(), I1, I8)) { - DISASM d1; - Disassemble(I1,d1); - table_size = d1.Instruction.Immediat; + //DISASM d1; + //Disassemble(I1,d1); + DecodedInstruction_t d1(I1); + table_size = d1.getImmediate(); // Instruction.Immediat; if (table_size <= 0) { - cout<<"pic64: found I1 ('"<<d1.CompleteInstr<<"'), but could not find size of switch table"<<endl; + cout<<"pic64: found I1 ('"<<d1.getDisassembly()/*CompleteInstr*/<<"'), but could not find size of switch table"<<endl; // set table_size to be very large, so we can still do pinning appropriately table_size=std::numeric_limits<int>::max(); } } else if(backup_until(cmp_str2.c_str(), I1, I8)) { - DISASM d1; - Disassemble(I1,d1); - table_size = d1.Instruction.Immediat; + //DISASM d1; + //Disassemble(I1,d1); + DecodedInstruction_t d1(I1); + table_size = d1.getImmediate()/*Instruction.Immediat*/; if (table_size <= 0) { // set table_size to be very large, so we can still do pinning appropriately - cout<<"pic64: found I1 ('"<<d1.CompleteInstr<<"'), but could not find size of switch table"<<endl; + cout<<"pic64: found I1 ('"<<d1.getDisassembly()/*CompleteInstr*/<<"'), but could not find size of switch table"<<endl; table_size=std::numeric_limits<int>::max(); } } @@ -1441,7 +1467,7 @@ Note: Here the operands of the add are reversed, so lookup code was not finding if(getenv("IB_VERBOSE")) { cout<<"Found possible table entry, at: "<< std::hex << I8->GetAddress()->GetVirtualOffset() - << " insn: " << disasm.CompleteInstr<< " d1: " + << " insn: " << disasm.getDisassembly()/*CompleteInstr*/<< " d1: " << D1 << " table_entry:" << table_entry << " target: "<< D1+table_entry << std::dec << endl; } @@ -1497,7 +1523,7 @@ Note: Here the operands of the add are reversed, so lookup code was not finding nb: handles both 32 and 64 bit */ -static void check_for_nonPIC_switch_table_pattern2(FileIR_t* firp, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop) +static void check_for_nonPIC_switch_table_pattern2(FileIR_t* firp, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop) { ibt_provenance_t prov=ibt_provenance_t::ibtp_switchtable_type5; Instruction_t *I1 = NULL; @@ -1506,19 +1532,23 @@ static void check_for_nonPIC_switch_table_pattern2(FileIR_t* firp, Instruction_t assert(IJ); // check if IJ is a jump - if(strstr(disasm.Instruction.Mnemonic, "jmp")==NULL) + //if(strstr(disasm.Instruction.Mnemonic, "jmp")==NULL) + if(strstr(disasm.getMnemonic().c_str(), "jmp")==NULL) return; // look for a memory type - if(!(disasm.Argument1.ArgType&MEMORY_TYPE)) + //if(!(disasm.Argument1.ArgType&MEMORY_TYPE)) + if(!(disasm.getOperand(0).isMemory())) return; // make sure there's a scaling factor - if (disasm.Argument1.Memory.Scale < 4) + //if (disasm.Argument1.Memory.Scale < 4) + //if (disasm.getOperand(0).getScaleValue() < 4) assumes scale is meaningful here? + if (!disasm.getOperand(0).hasIndexRegister() || disasm.getOperand(0).getScaleValue() < 4) return; // extract start of jmp table - virtual_offset_t table_offset = disasm.Instruction.AddrValue; + virtual_offset_t table_offset = disasm.getAddress(); // disasm.Instruction.AddrValue; if(table_offset==0) return; @@ -1532,9 +1562,10 @@ static void check_for_nonPIC_switch_table_pattern2(FileIR_t* firp, Instruction_t // extract size off the comparison // make sure not off by one - DISASM d1; - Disassemble(I1,d1); - virtual_offset_t table_size = d1.Instruction.Immediat; + //DISASM d1; + //Disassemble(I1,d1); + DecodedInstruction_t d1(I1); + virtual_offset_t table_size = d1.getImmediate()/*d1.Instruction.Immediat*/; if (table_size <= 0) return; @@ -1601,7 +1632,7 @@ static void check_for_nonPIC_switch_table_pattern2(FileIR_t* firp, Instruction_t nb: handles both 32 and 64 bit */ -static void check_for_nonPIC_switch_table(FileIR_t* firp, Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop) +static void check_for_nonPIC_switch_table(FileIR_t* firp, Instruction_t* insn, DecodedInstruction_t disasm, EXEIO::exeio* elfiop) { ibt_provenance_t prov=ibt_provenance_t::ibtp_switchtable_type6; Instruction_t *I1 = NULL; @@ -1612,15 +1643,15 @@ static void check_for_nonPIC_switch_table(FileIR_t* firp, Instruction_t* insn, D if (!IJ) return; // check if IJ is a jump - if(strstr(disasm.Instruction.Mnemonic, "jmp")==NULL) + if(strstr(disasm.getMnemonic().c_str()/*disasm.Instruction.Mnemonic*/, "jmp")==NULL) return; // return if it's a jump to a constant address, these are common - if(disasm.Argument1.ArgType&CONSTANT_TYPE) + if(disasm.getOperand(0).isConstant() /*disasm.Argument1.ArgType&CONSTANT_TYPE*/) return; // return if it's a jump to a memory address - if(disasm.Argument1.ArgType&MEMORY_TYPE) + if(disasm.getOperand(0).isMemory() /*disasm.Argument1.ArgType&MEMORY_TYPE*/) return; // has to be a jump to a register now @@ -1630,14 +1661,15 @@ static void check_for_nonPIC_switch_table(FileIR_t* firp, Instruction_t* insn, D return; // extract start of jmp table - DISASM d4; - Disassemble(I4,d4); + // DISASM d4; + // Disassemble(I4,d4); + DecodedInstruction_t d4(I4); // make sure there's a scaling factor - if (d4.Argument2.Memory.Scale < 4) + if (d4.getOperand(1).isMemory() && d4.getOperand(1).getScaleValue() /*d4.Argument2.Memory.Scale*/ < 4) return; - virtual_offset_t table_offset=d4.Instruction.AddrValue; + virtual_offset_t table_offset=d4.getAddress(); // d4.Instruction.AddrValue; if(table_offset==0) return; @@ -1652,9 +1684,10 @@ static void check_for_nonPIC_switch_table(FileIR_t* firp, Instruction_t* insn, D // extract size off the comparison // make sure not off by one - DISASM d1; - Disassemble(I1,d1); - virtual_offset_t table_size = d1.Instruction.Immediat; + //DISASM d1; + //Disassemble(I1,d1); + DecodedInstruction_t d1(I1); + virtual_offset_t table_size = d1.getImmediate(); // d1.Instruction.Immediat; if (table_size <= 0) return; if(getenv("IB_VERBOSE")) @@ -2114,9 +2147,10 @@ void mark_return_points(FileIR_t* firp) ) { Instruction_t* insn=*it; - DISASM d; - Disassemble(insn,d); - if(string("call ")==d.Instruction.Mnemonic && insn->GetFallthrough()) + //DISASM d; + //Disassemble(insn,d); + DecodedInstruction_t d(insn); + if(string("call")==d.getMnemonic() /*.Instruction.Mnemonic*/ && insn->GetFallthrough()) { targets[insn->GetFallthrough()->GetAddress()->GetVirtualOffset()].add(ibt_provenance_t::ibtp_ret); } @@ -2226,22 +2260,25 @@ void setup_icfs(FileIR_t* firp, EXEIO::exeio* elfiop) } // disassemble the instruction, and figure out which type of hell node we need. - DISASM d; - Disassemble(insn,d); - if(string("ret ")==d.Instruction.Mnemonic || string("retn ")==d.Instruction.Mnemonic) + //DISASM d; + //Disassemble(insn,d); + DecodedInstruction_t d(insn); + if(string("ret")==d.getMnemonic() /*Instruction.Mnemonic*/ || string("retn")==d.getMnemonic() /*d.Instruction.Mnemonic*/) { if(getenv("IB_VERBOSE")!=0) cout<<"using ret hell node for "<<hex<<insn->GetAddress()->GetVirtualOffset()<<endl; insn->SetIBTargets(ret_hell); } - else if ( (string("call ")==d.Instruction.Mnemonic) && ((d.Argument1.ArgType&0xffff0000&CONSTANT_TYPE)!=CONSTANT_TYPE)) + //else if ( (string("call ")==d.Instruction.Mnemonic) && ((d.Argument1.ArgType&0xffff0000&CONSTANT_TYPE)!=CONSTANT_TYPE)) + else if ( (string("call")==d.getMnemonic()) && (!d.getOperand(0).isConstant())) { if(getenv("IB_VERBOSE")!=0) cout<<"using call hell node for "<<hex<<insn->GetAddress()->GetVirtualOffset()<<endl; // indirect call insn->SetIBTargets(call_hell); } - else if ( (string("jmp ")==d.Instruction.Mnemonic) && ((d.Argument1.ArgType&0xffff0000&CONSTANT_TYPE)!=CONSTANT_TYPE)) + //else if ( (string("jmp ")==d.Instruction.Mnemonic) && ((d.Argument1.ArgType&0xffff0000&CONSTANT_TYPE)!=CONSTANT_TYPE)) + else if ( (string("jmp")==d.getMnemonic()) && (!d.getOperand(0).isConstant())) { if(getenv("IB_VERBOSE")!=0) cout<<"using jmp hell node for "<<hex<<insn->GetAddress()->GetVirtualOffset()<<endl; diff --git a/libIRDB/test/split_eh_frame.cpp b/libIRDB/test/split_eh_frame.cpp index 22a6b55c0..559ec1e99 100644 --- a/libIRDB/test/split_eh_frame.cpp +++ b/libIRDB/test/split_eh_frame.cpp @@ -1939,13 +1939,22 @@ void split_eh_frame_impl_t<ptrsize>::build_ir() const assert(newreloc); if(personality_obj==NULL) - cout<<"Null personality obj: 0x"<<hex<<personality<<endl; + { + if(getenv("EHIR_VERBOSE")!=NULL) + cout<<"Null personality obj: 0x"<<hex<<personality<<endl; + } else if(personality_scoop) - cout<<"Found personality scoop: 0x"<<hex<<personality<<" -> " - <<personality_scoop->GetName()<<"+0x"<<hex<<addend<<endl; + { + if(getenv("EHIR_VERBOSE")!=NULL) + cout<<"Found personality scoop: 0x"<<hex<<personality<<" -> " + <<personality_scoop->GetName()<<"+0x"<<hex<<addend<<endl; + } else if(personality_insn) - cout<<"Found personality insn: 0x"<<hex<<personality<<" -> " - <<personality_insn->GetBaseID()<<":"<<personality_insn->getDisassembly()<<endl; + { + if(getenv("EHIR_VERBOSE")!=NULL) + cout<<"Found personality insn: 0x"<<hex<<personality<<" -> " + <<personality_insn->GetBaseID()<<":"<<personality_insn->getDisassembly()<<endl; + } else assert(0); -- GitLab