Skip to content

Commit

Permalink
1. Enables new jump table analysis for powerpc 2. Fix various inconsi…
Browse files Browse the repository at this point in the history
…stency between Dyninst powerpc register representation and ROSE powerpc register representation 3. Fix various issues in converting Dyninst powerpc instructions to ROSE powerpc instructions
  • Loading branch information
mxz297 committed Aug 15, 2017
1 parent 4880944 commit b1c8cb0
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 45 deletions.
59 changes: 59 additions & 0 deletions common/h/dyn_regs.h
Expand Up @@ -107,6 +107,7 @@ namespace Dyninst
bool isSyscallNumberReg() const;
bool isSyscallReturnValueReg() const;
bool isFlag() const;
bool isZeroFlag() const;

void getROSERegister(int &c, int &n, int &p);

Expand Down Expand Up @@ -897,6 +898,30 @@ namespace Dyninst
DEF_REGISTER(cr1g, 705 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr1e, 706 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr1s, 707 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr2l, 708 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr2g, 709 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr2e, 710 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr2s, 711 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr3l, 712 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr3g, 713 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr3e, 714 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr3s, 715 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr4l, 716 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr4g, 717 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr4e, 718 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr4s, 719 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr5l, 720 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr5g, 721 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr5e, 722 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr5s, 723 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr6l, 724 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr6g, 725 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr6e, 726 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr6s, 727 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr7l, 728 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr7g, 729 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr7e, 730 | SPR | Arch_ppc32, "ppc32");
DEF_REGISTER(cr7s, 731 | SPR | Arch_ppc32, "ppc32");


}
Expand Down Expand Up @@ -1080,6 +1105,40 @@ namespace Dyninst
DEF_REGISTER(cr, 629 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(or3, 630 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(trap, 631 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr0l, 700 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr0g, 701 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr0e, 702 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr0s, 703 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr1l, 704 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr1g, 705 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr1e, 706 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr1s, 707 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr2l, 708 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr2g, 709 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr2e, 710 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr2s, 711 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr3l, 712 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr3g, 713 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr3e, 714 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr3s, 715 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr4l, 716 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr4g, 717 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr4e, 718 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr4s, 719 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr5l, 720 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr5g, 721 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr5e, 722 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr5s, 723 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr6l, 724 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr6g, 725 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr6e, 726 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr6s, 727 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr7l, 728 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr7g, 729 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr7e, 730 | SPR | Arch_ppc64, "ppc64");
DEF_REGISTER(cr7s, 731 | SPR | Arch_ppc64, "ppc64");


}

namespace aarch64{
Expand Down
36 changes: 35 additions & 1 deletion common/src/dyn_regs.C
Expand Up @@ -432,9 +432,11 @@ MachRegister MachRegister::getZeroFlag(Dyninst::Architecture arch)
case Arch_aarch64:
return aarch64::z;
case Arch_aarch32:
assert(!"Not implemented");
case Arch_ppc32:
return ppc32::cr0e;
case Arch_ppc64:
assert(0);
return ppc64::cr0e;
case Arch_none:
return InvalidReg;
default:
Expand Down Expand Up @@ -495,6 +497,38 @@ bool MachRegister::isFlag() const
return regC == x86_64::FLAG;
case Arch_aarch64:
return regC == aarch64::FLAG;
case Arch_ppc32:
case Arch_ppc64:{
// For power, we have a different register representation.
// We do not use the subrange field for MachReigsters
// and all lower 32 bits are base ID
int baseID = reg & 0x0000FFFF;
return (baseID <= 731 && baseID >= 700) || (baseID <= 629 && baseID >= 621);
}
default:
assert(!"Not implemented!");
}
return false;
}

bool MachRegister::isZeroFlag() const
{
switch (getArchitecture())
{
case Arch_x86:
return *this == x86::zf;
case Arch_x86_64:
return *this == x86_64::zf;
case Arch_aarch64:
return *this == aarch64::z;
case Arch_ppc32:
case Arch_ppc64:{
// For power, we have a different register representation.
// We do not use the subrange field for MachReigsters
// and all lower 32 bits are base ID
int baseID = reg & 0x0000FFFF;
return baseID <= 731 && baseID >= 700 && baseID % 4 == 2;
}
default:
assert(!"Not implemented!");
}
Expand Down
2 changes: 1 addition & 1 deletion dataflowAPI/rose/semantics/DispatcherPowerpc.h
Expand Up @@ -27,7 +27,7 @@ class DispatcherPowerpc: public BaseSemantics::Dispatcher {

DispatcherPowerpc(const BaseSemantics::RiscOperatorsPtr &ops, size_t addrWidth, const RegisterDictionary *regs)
: BaseSemantics::Dispatcher(ops, addrWidth, regs ? regs : RegisterDictionary::dictionary_powerpc()) {
ASSERT_require(32==addrWidth);
// ASSERT_require(32==addrWidth);
regcache_init();
iproc_init();
memory_init();
Expand Down
135 changes: 120 additions & 15 deletions dataflowAPI/rose/semantics/SymEvalSemantics.C
Expand Up @@ -47,6 +47,18 @@ void SymEvalSemantics::StateAST::writeMemory(const BaseSemantics::SValuePtr &add
memory->writeMemory(addr, value, res, aaMap, writeSize);
}

void SymEvalSemantics::StateAST::writeMemory(const BaseSemantics::SValuePtr &addr,
const BaseSemantics::SValuePtr &value,
BaseSemantics::RiscOperators *addrOps,
BaseSemantics::RiscOperators *valOps) {
ASSERT_not_null(addr);
ASSERT_not_null(value);
SymEvalSemantics::MemoryStateASTPtr memory = SymEvalSemantics::MemoryStateAST::promote(memoryState());
memory->writeMemory(addr, value, res, aaMap, value->get_width());
}



///////////////////////////////////////////////////////
// RegisterStateAST
///////////////////////////////////////////////////////
Expand Down Expand Up @@ -185,19 +197,14 @@ Dyninst::Absloc SymEvalSemantics::RegisterStateASTPPC32::convert(const RegisterD

case powerpc_regclass_cr: {
unsigned int offset = reg.get_offset();
if (size == 4) {
if (size == 32) {
mreg = Dyninst::ppc32::cr;
}if (size == 4) {
Dyninst::MachRegister base = Dyninst::ppc32::cr0;
mreg = Dyninst::MachRegister(base.val() + offset / 4);
} else if (size == 1) {
Dyninst::MachRegister base;
if (offset < 4) {
base = Dyninst::ppc32::cr0l;
} else if (offset < 8) {
base = Dyninst::ppc32::cr1l;
} else {
assert(!"not implemented cr fields");
}
mreg = Dyninst::MachRegister(base.val() + offset % 4);
Dyninst::MachRegister base = Dyninst::ppc32::cr0l;
mreg = Dyninst::MachRegister(base.val() + offset);
} else {
assert(!"bad cr register size");
}
Expand Down Expand Up @@ -260,6 +267,100 @@ Dyninst::Absloc SymEvalSemantics::RegisterStateASTPPC32::convert(const RegisterD
return Dyninst::Absloc(mreg);
}

Dyninst::Absloc SymEvalSemantics::RegisterStateASTPPC64::convert(const RegisterDescriptor &reg) {
Dyninst::MachRegister mreg;

unsigned int major = reg.get_major();
unsigned int size = reg.get_nbits();

switch (major) {
case powerpc_regclass_gpr: {
unsigned int minor = reg.get_minor();
Dyninst::MachRegister base = Dyninst::ppc64::r0;

// For some reason, ROSE does not provide a enum representation for power registers
mreg = Dyninst::MachRegister(base.val() + minor);
}
break;
case powerpc_regclass_fpr: {
Dyninst::MachRegister base = Dyninst::ppc64::fpr0;
unsigned int minor = reg.get_minor();
mreg = Dyninst::MachRegister(base.val() + minor);
}
break;

case powerpc_regclass_cr: {
unsigned int offset = reg.get_offset();
if (size == 32) {
mreg = Dyninst::ppc64::cr;
} else if (size == 4) {
Dyninst::MachRegister base = Dyninst::ppc64::cr0;
mreg = Dyninst::MachRegister(base.val() + offset / 4);
} else if (size == 1) {
Dyninst::MachRegister base = Dyninst::ppc64::cr0l;
mreg = Dyninst::MachRegister(base.val() + offset);
} else {
assert(!"bad cr register size");
}
}
break;

case powerpc_regclass_fpscr:
assert(!"not implemented register class fpscr");
break;

case powerpc_regclass_spr: {
unsigned int minor = reg.get_minor();
switch (minor) {
case powerpc_spr_xer:
mreg = Dyninst::ppc64::xer;
break;
case powerpc_spr_lr:
mreg = Dyninst::ppc64::lr;
break;
case powerpc_spr_ctr:
mreg = Dyninst::ppc64::ctr;
break;
case powerpc_spr_dsisr:
mreg = Dyninst::ppc64::dsisr;
break;
case powerpc_spr_dar:
mreg = Dyninst::ppc64::dar;
break;
case powerpc_spr_dec:
mreg = Dyninst::ppc64::dec;
break;
default:
assert(!"not implemented special register");
}
}
break;
case powerpc_regclass_tbr:
assert(!"not implemented regclass tbr");
break;

case powerpc_regclass_msr:
mreg = Dyninst::ppc64::msr;
break;

case powerpc_regclass_sr:
assert(!"not implemented regclass sr");
break;

case powerpc_regclass_iar:
mreg = Dyninst::ppc64::pc;
break;

case powerpc_regclass_pvr:
mreg = Dyninst::ppc64::pvr;
break;
default:
ASSERT_always_forbid("Unexpected register major type.");
}

return Dyninst::Absloc(mreg);
}


///////////////////////////////////////////////////////
// MemoryStateAST
Expand All @@ -276,10 +377,14 @@ BaseSemantics::SValuePtr SymEvalSemantics::MemoryStateAST::readMemory(const Base
}

BaseSemantics::SValuePtr SymEvalSemantics::MemoryStateAST::readMemory(const BaseSemantics::SValuePtr &address,
const BaseSemantics::SValuePtr &/*dflt*/,
const BaseSemantics::SValuePtr &dflt,
BaseSemantics::RiscOperators */*addrOps*/,
BaseSemantics::RiscOperators */*valOps*/) {
ASSERT_always_forbid("overridden MemoryState::readMemory() should never be called for AST, always use the non-virtual readMemory that also takes additional parameters.");
SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
return SymEvalSemantics::SValue::instance(Dyninst::DataflowAPI::RoseAST::create(Dyninst::DataflowAPI::ROSEOperation(Dyninst::DataflowAPI::ROSEOperation::derefOp, dflt->get_number()),
addr->get_expression(),
Dyninst::DataflowAPI::ConstantAST::create(Dyninst::DataflowAPI::Constant(1, 1))));

}

void SymEvalSemantics::MemoryStateAST::writeMemory(const BaseSemantics::SValuePtr &address,
Expand All @@ -299,11 +404,11 @@ void SymEvalSemantics::MemoryStateAST::writeMemory(const BaseSemantics::SValuePt
}
}

void SymEvalSemantics::MemoryStateAST::writeMemory(const BaseSemantics::SValuePtr &/*addr*/,
const BaseSemantics::SValuePtr &/*value*/,
void SymEvalSemantics::MemoryStateAST::writeMemory(const BaseSemantics::SValuePtr &addr,
const BaseSemantics::SValuePtr &value,
BaseSemantics::RiscOperators */*addrOps*/,
BaseSemantics::RiscOperators */*valOps*/) {
ASSERT_always_forbid("overridden MemoryState::writeMemory() should never be called for AST, always use the non-virtual writeMemory that also takes additional parameters.");
ASSERT_always_forbid("overridden MemoryState::writeMemory() should never be called for AST, always use the non-virtual writeMemory that also takes additional parameters.");
}

///////////////////////////////////////////////////////
Expand Down
25 changes: 23 additions & 2 deletions dataflowAPI/rose/semantics/SymEvalSemantics.h
Expand Up @@ -52,7 +52,7 @@ namespace rose {

public:
virtual BaseSemantics::SValuePtr undefined_(size_t nbits) const {
return SValuePtr(new SValue(Dyninst::DataflowAPI::BottomAST::create(false)));
return SValuePtr(new SValue(32, nbits));
}

virtual BaseSemantics::SValuePtr unspecified_(size_t nbits) const {
Expand Down Expand Up @@ -123,6 +123,7 @@ namespace rose {
typedef boost::shared_ptr<class RegisterStateAST> RegisterStateASTPtr;
typedef boost::shared_ptr<class RegisterStateASTARM64> RegisterStateASTARM64Ptr;
typedef boost::shared_ptr<class RegisterStateASTPPC32> RegisterStateASTPPC32Ptr;
typedef boost::shared_ptr<class RegisterStateASTPPC64> RegisterStateASTPPC64Ptr;

class RegisterStateAST : public BaseSemantics::RegisterState {
public:
Expand Down Expand Up @@ -216,7 +217,25 @@ namespace rose {
ASSERT_not_null(retval);
return retval;
}
private:
virtual Dyninst::Absloc convert(const RegisterDescriptor &reg);

};
class RegisterStateASTPPC64 : public RegisterStateAST {
public:
RegisterStateASTPPC64(const BaseSemantics::SValuePtr &protoval,
const RegisterDictionary *regdict) : RegisterStateAST(protoval, regdict) { }

static RegisterStateASTPPC64Ptr instance(const BaseSemantics::SValuePtr &protoval,
const RegisterDictionary *regdict) {
return RegisterStateASTPPC64Ptr(new RegisterStateASTPPC64(protoval, regdict));
}

static RegisterStateASTPPC64Ptr promote(const BaseSemantics::RegisterStatePtr &from) {
RegisterStateASTPPC64Ptr retval = boost::dynamic_pointer_cast<RegisterStateASTPPC64>(from);
ASSERT_not_null(retval);
return retval;
}

private:
virtual Dyninst::Absloc convert(const RegisterDescriptor &reg);
Expand Down Expand Up @@ -346,7 +365,9 @@ namespace rose {
virtual BaseSemantics::SValuePtr readMemory(const BaseSemantics::SValuePtr &address, const BaseSemantics::SValuePtr &dflt,
BaseSemantics::RiscOperators *addrOps, BaseSemantics::RiscOperators *valOps, size_t readSize = 0);
virtual void writeMemory(const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &value, BaseSemantics::RiscOperators *addrOps,
BaseSemantics::RiscOperators *valOps, size_t writeSize = 0);
BaseSemantics::RiscOperators *valOps, size_t writeSize);
virtual void writeMemory(const BaseSemantics::SValuePtr &addr, const BaseSemantics::SValuePtr &value, BaseSemantics::RiscOperators *addrOps,
BaseSemantics::RiscOperators *valOps);

protected:
Dyninst::DataflowAPI::Result_t &res;
Expand Down

0 comments on commit b1c8cb0

Please sign in to comment.