diff --git a/src/experiments/nanojpeg/CMakeLists.txt b/src/experiments/nanojpeg/CMakeLists.txt index c6603c35..8b2f63e2 100644 --- a/src/experiments/nanojpeg/CMakeLists.txt +++ b/src/experiments/nanojpeg/CMakeLists.txt @@ -19,6 +19,8 @@ set(MY_CAMPAIGN_SRCS campaign.cc UDIS86.hpp UDIS86.cc + udis86_helper.hpp + udis86_helper.cc ) #### PROTOBUFS #### diff --git a/src/experiments/nanojpeg/UDIS86.hpp b/src/experiments/nanojpeg/UDIS86.hpp index b2b08219..a6a08fed 100644 --- a/src/experiments/nanojpeg/UDIS86.hpp +++ b/src/experiments/nanojpeg/UDIS86.hpp @@ -42,7 +42,7 @@ public: * retrieves the private ud structure of udis86 * @returns a reference pointer to a ud_t variable */ - inline ud_t const &getCurrentState() const { return ud_obj; } + inline ud_t &getCurrentState() { return ud_obj; } /** * Tries to decode the next instruction from the given buffer. * @returns \c true if a new instruction could be retrieved, \c false if the object has expired diff --git a/src/experiments/nanojpeg/campaign.cc b/src/experiments/nanojpeg/campaign.cc index fcf7046c..f7881a9f 100644 --- a/src/experiments/nanojpeg/campaign.cc +++ b/src/experiments/nanojpeg/campaign.cc @@ -11,6 +11,7 @@ #include "util/ProtoStream.hpp" #include "UDIS86.hpp" +#include "udis86_helper.hpp" #include "../plugins/tracing/TracingPlugin.hpp" @@ -80,6 +81,8 @@ bool NanoJPEGCampaign::run() return false; } Udis86 udis(0); + Udis86Helper udis_helper; + Udis86Helper::UDRegisterSet in_regs, out_regs; // load trace ifstream tracef(NANOJPEG_TRACE); @@ -118,22 +121,25 @@ bool NanoJPEGCampaign::run() return false; } - ud_t ud = udis.getCurrentState(); + ud_t& ud = udis.getCurrentState(); + udis_helper.setUd(&ud); // for now: debug output m_log << "0x" << hex << ev.ip() << " " << ::ud_insn_asm(&ud) << endl; for (int i = 0; i < 3; ++i) { - switch (ud.operand[i].type) { - case UD_NONE: cout << "-"; break; - case UD_OP_MEM: cout << "M"; break; - case UD_OP_PTR: cout << "P"; break; - case UD_OP_IMM: cout << "I"; break; - case UD_OP_JIMM: cout << "J"; break; - case UD_OP_CONST: cout << "C"; break; - case UD_OP_REG: cout << "R"; break; - default: m_log << "WAT" << endl; - } - std::cout << " "; + cout << udis_helper.operandTypeToChar(ud.operand[i].type) << " "; + } + cout << endl; + udis_helper.inOutRegisters(in_regs, out_regs); + cout << "IN: "; + for (Udis86Helper::UDRegisterSet::const_iterator it = in_regs.begin(); + it != in_regs.end(); ++it) { + cout << udis_helper.typeToString(*it) << " "; + } + cout << "OUT: "; + for (Udis86Helper::UDRegisterSet::const_iterator it = out_regs.begin(); + it != out_regs.end(); ++it) { + cout << udis_helper.typeToString(*it) << " "; } cout << endl; } diff --git a/src/experiments/nanojpeg/udis86_helper.cc b/src/experiments/nanojpeg/udis86_helper.cc new file mode 100644 index 00000000..02dc2076 --- /dev/null +++ b/src/experiments/nanojpeg/udis86_helper.cc @@ -0,0 +1,375 @@ +#include "udis86_helper.hpp" + +#include + +char +Udis86Helper::operandTypeToChar(unsigned op) +{ + switch (op) { + case UD_NONE: return '-'; + case UD_OP_MEM: return 'M'; + case UD_OP_PTR: return 'P'; + case UD_OP_IMM: return 'I'; + case UD_OP_JIMM: return 'J'; + case UD_OP_CONST: return 'C'; + case UD_OP_REG: return 'R'; + default: return '?'; + } +} + +unsigned +Udis86Helper::operandCount() +{ + return (ud->operand[0].type != UD_NONE) + + (ud->operand[1].type != UD_NONE) + + (ud->operand[2].type != UD_NONE); +} + +#define CASE(x) case x: return #x; +char const * +Udis86Helper::mnemonicToString(unsigned mnemonic) +{ + + switch(mnemonic) { + CASE(UD_Iinvalid) CASE(UD_I3dnow) CASE(UD_Inone) CASE(UD_Idb) CASE(UD_Ipause) CASE(UD_Iaaa) + CASE(UD_Iaad) CASE(UD_Iaam) CASE(UD_Iaas) CASE(UD_Iadc) CASE(UD_Iadd) CASE(UD_Iaddpd) + CASE(UD_Iaddps) CASE(UD_Iaddsd) CASE(UD_Iaddss) CASE(UD_Iand) CASE(UD_Iandpd) CASE(UD_Iandps) + CASE(UD_Iandnpd) CASE(UD_Iandnps) CASE(UD_Iarpl) CASE(UD_Imovsxd) CASE(UD_Ibound) CASE(UD_Ibsf) + CASE(UD_Ibsr) CASE(UD_Ibswap) CASE(UD_Ibt) CASE(UD_Ibtc) CASE(UD_Ibtr) CASE(UD_Ibts) + CASE(UD_Icall) CASE(UD_Icbw) CASE(UD_Icwde) CASE(UD_Icdqe) CASE(UD_Iclc) CASE(UD_Icld) + CASE(UD_Iclflush) CASE(UD_Iclgi) CASE(UD_Icli) CASE(UD_Iclts) CASE(UD_Icmc) CASE(UD_Icmovo) + CASE(UD_Icmovno) CASE(UD_Icmovb) CASE(UD_Icmovae) CASE(UD_Icmovz) CASE(UD_Icmovnz) CASE(UD_Icmovbe) + CASE(UD_Icmova) CASE(UD_Icmovs) CASE(UD_Icmovns) CASE(UD_Icmovp) CASE(UD_Icmovnp) CASE(UD_Icmovl) + CASE(UD_Icmovge) CASE(UD_Icmovle) CASE(UD_Icmovg) CASE(UD_Icmp) CASE(UD_Icmppd) CASE(UD_Icmpps) + CASE(UD_Icmpsb) CASE(UD_Icmpsw) CASE(UD_Icmpsd) CASE(UD_Icmpsq) CASE(UD_Icmpss) CASE(UD_Icmpxchg) + CASE(UD_Icmpxchg8b) CASE(UD_Icomisd) CASE(UD_Icomiss) CASE(UD_Icpuid) CASE(UD_Icvtdq2pd) CASE(UD_Icvtdq2ps) + CASE(UD_Icvtpd2dq) CASE(UD_Icvtpd2pi) CASE(UD_Icvtpd2ps) CASE(UD_Icvtpi2ps) CASE(UD_Icvtpi2pd) CASE(UD_Icvtps2dq) + CASE(UD_Icvtps2pi) CASE(UD_Icvtps2pd) CASE(UD_Icvtsd2si) CASE(UD_Icvtsd2ss) CASE(UD_Icvtsi2ss) CASE(UD_Icvtss2si) + CASE(UD_Icvtss2sd) CASE(UD_Icvttpd2pi) CASE(UD_Icvttpd2dq) CASE(UD_Icvttps2dq) CASE(UD_Icvttps2pi) CASE(UD_Icvttsd2si) + CASE(UD_Icvtsi2sd) CASE(UD_Icvttss2si) CASE(UD_Icwd) CASE(UD_Icdq) CASE(UD_Icqo) CASE(UD_Idaa) + CASE(UD_Idas) CASE(UD_Idec) CASE(UD_Idiv) CASE(UD_Idivpd) CASE(UD_Idivps) CASE(UD_Idivsd) + CASE(UD_Idivss) CASE(UD_Iemms) CASE(UD_Ienter) CASE(UD_If2xm1) CASE(UD_Ifabs) CASE(UD_Ifadd) + CASE(UD_Ifaddp) CASE(UD_Ifbld) CASE(UD_Ifbstp) CASE(UD_Ifchs) CASE(UD_Ifclex) CASE(UD_Ifcmovb) + CASE(UD_Ifcmove) CASE(UD_Ifcmovbe) CASE(UD_Ifcmovu) CASE(UD_Ifcmovnb) CASE(UD_Ifcmovne) CASE(UD_Ifcmovnbe) + CASE(UD_Ifcmovnu) CASE(UD_Ifucomi) CASE(UD_Ifcom) CASE(UD_Ifcom2) CASE(UD_Ifcomp3) CASE(UD_Ifcomi) + CASE(UD_Ifucomip) CASE(UD_Ifcomip) CASE(UD_Ifcomp) CASE(UD_Ifcomp5) CASE(UD_Ifcompp) CASE(UD_Ifcos) + CASE(UD_Ifdecstp) CASE(UD_Ifdiv) CASE(UD_Ifdivp) CASE(UD_Ifdivr) CASE(UD_Ifdivrp) CASE(UD_Ifemms) + CASE(UD_Iffree) CASE(UD_Iffreep) CASE(UD_Ificom) CASE(UD_Ificomp) CASE(UD_Ifild) CASE(UD_Ifncstp) + CASE(UD_Ifninit) CASE(UD_Ifiadd) CASE(UD_Ifidivr) CASE(UD_Ifidiv) CASE(UD_Ifisub) CASE(UD_Ifisubr) + CASE(UD_Ifist) CASE(UD_Ifistp) CASE(UD_Ifisttp) CASE(UD_Ifld) CASE(UD_Ifld1) CASE(UD_Ifldl2t) + CASE(UD_Ifldl2e) CASE(UD_Ifldlpi) CASE(UD_Ifldlg2) CASE(UD_Ifldln2) CASE(UD_Ifldz) CASE(UD_Ifldcw) + CASE(UD_Ifldenv) CASE(UD_Ifmul) CASE(UD_Ifmulp) CASE(UD_Ifimul) CASE(UD_Ifnop) CASE(UD_Ifpatan) + CASE(UD_Ifprem) CASE(UD_Ifprem1) CASE(UD_Ifptan) CASE(UD_Ifrndint) CASE(UD_Ifrstor) CASE(UD_Ifnsave) + CASE(UD_Ifscale) CASE(UD_Ifsin) CASE(UD_Ifsincos) CASE(UD_Ifsqrt) CASE(UD_Ifstp) CASE(UD_Ifstp1) + CASE(UD_Ifstp8) CASE(UD_Ifstp9) CASE(UD_Ifst) CASE(UD_Ifnstcw) CASE(UD_Ifnstenv) CASE(UD_Ifnstsw) + CASE(UD_Ifsub) CASE(UD_Ifsubp) CASE(UD_Ifsubr) CASE(UD_Ifsubrp) CASE(UD_Iftst) CASE(UD_Ifucom) + CASE(UD_Ifucomp) CASE(UD_Ifucompp) CASE(UD_Ifxam) CASE(UD_Ifxch) CASE(UD_Ifxch4) CASE(UD_Ifxch7) + CASE(UD_Ifxrstor) CASE(UD_Ifxsave) CASE(UD_Ifpxtract) CASE(UD_Ifyl2x) CASE(UD_Ifyl2xp1) CASE(UD_Ihlt) + CASE(UD_Iidiv) CASE(UD_Iin) CASE(UD_Iimul) CASE(UD_Iinc) CASE(UD_Iinsb) CASE(UD_Iinsw) + CASE(UD_Iinsd) CASE(UD_Iint1) CASE(UD_Iint3) CASE(UD_Iint) CASE(UD_Iinto) CASE(UD_Iinvd) + CASE(UD_Iinvept) CASE(UD_Iinvlpg) CASE(UD_Iinvlpga) CASE(UD_Iinvvpid) CASE(UD_Iiretw) CASE(UD_Iiretd) + CASE(UD_Iiretq) CASE(UD_Ijo) CASE(UD_Ijno) CASE(UD_Ijb) CASE(UD_Ijae) CASE(UD_Ijz) + CASE(UD_Ijnz) CASE(UD_Ijbe) CASE(UD_Ija) CASE(UD_Ijs) CASE(UD_Ijns) CASE(UD_Ijp) + CASE(UD_Ijnp) CASE(UD_Ijl) CASE(UD_Ijge) CASE(UD_Ijle) CASE(UD_Ijg) CASE(UD_Ijcxz) + CASE(UD_Ijecxz) CASE(UD_Ijrcxz) CASE(UD_Ijmp) CASE(UD_Ilahf) CASE(UD_Ilar) CASE(UD_Ilddqu) + CASE(UD_Ildmxcsr) CASE(UD_Ilds) CASE(UD_Ilea) CASE(UD_Iles) CASE(UD_Ilfs) CASE(UD_Ilgs) + CASE(UD_Ilidt) CASE(UD_Ilss) CASE(UD_Ileave) CASE(UD_Ilfence) CASE(UD_Ilgdt) CASE(UD_Illdt) + CASE(UD_Ilmsw) CASE(UD_Ilock) CASE(UD_Ilodsb) CASE(UD_Ilodsw) CASE(UD_Ilodsd) CASE(UD_Ilodsq) + CASE(UD_Iloopnz) CASE(UD_Iloope) CASE(UD_Iloop) CASE(UD_Ilsl) CASE(UD_Iltr) CASE(UD_Imaskmovq) + CASE(UD_Imaxpd) CASE(UD_Imaxps) CASE(UD_Imaxsd) CASE(UD_Imaxss) CASE(UD_Imfence) CASE(UD_Iminpd) + CASE(UD_Iminps) CASE(UD_Iminsd) CASE(UD_Iminss) CASE(UD_Imonitor) CASE(UD_Imontmul) CASE(UD_Imov) + CASE(UD_Imovapd) CASE(UD_Imovaps) CASE(UD_Imovd) CASE(UD_Imovhpd) CASE(UD_Imovhps) CASE(UD_Imovlhps) + CASE(UD_Imovlpd) CASE(UD_Imovlps) CASE(UD_Imovhlps) CASE(UD_Imovmskpd) CASE(UD_Imovmskps) CASE(UD_Imovntdq) + CASE(UD_Imovnti) CASE(UD_Imovntpd) CASE(UD_Imovntps) CASE(UD_Imovntq) CASE(UD_Imovq) CASE(UD_Imovsb) + CASE(UD_Imovsw) CASE(UD_Imovsd) CASE(UD_Imovsq) CASE(UD_Imovss) CASE(UD_Imovsx) CASE(UD_Imovupd) + CASE(UD_Imovups) CASE(UD_Imovzx) CASE(UD_Imul) CASE(UD_Imulpd) CASE(UD_Imulps) CASE(UD_Imulsd) + CASE(UD_Imulss) CASE(UD_Imwait) CASE(UD_Ineg) CASE(UD_Inop) CASE(UD_Inot) CASE(UD_Ior) + CASE(UD_Iorpd) CASE(UD_Iorps) CASE(UD_Iout) CASE(UD_Ioutsb) CASE(UD_Ioutsw) CASE(UD_Ioutsd) + CASE(UD_Ioutsq) CASE(UD_Ipacksswb) CASE(UD_Ipackssdw) CASE(UD_Ipackuswb) CASE(UD_Ipaddb) CASE(UD_Ipaddw) + CASE(UD_Ipaddd) CASE(UD_Ipaddsb) CASE(UD_Ipaddsw) CASE(UD_Ipaddusb) CASE(UD_Ipaddusw) CASE(UD_Ipand) + CASE(UD_Ipandn) CASE(UD_Ipavgb) CASE(UD_Ipavgw) CASE(UD_Ipcmpeqb) CASE(UD_Ipcmpeqw) CASE(UD_Ipcmpeqd) + CASE(UD_Ipcmpgtb) CASE(UD_Ipcmpgtw) CASE(UD_Ipcmpgtd) CASE(UD_Ipextrb) CASE(UD_Ipextrd) CASE(UD_Ipextrq) + CASE(UD_Ipextrw) CASE(UD_Ipinsrw) CASE(UD_Ipmaddwd) CASE(UD_Ipmaxsw) CASE(UD_Ipmaxub) CASE(UD_Ipminsw) + CASE(UD_Ipminub) CASE(UD_Ipmovmskb) CASE(UD_Ipmulhuw) CASE(UD_Ipmulhw) CASE(UD_Ipmullw) CASE(UD_Ipop) + CASE(UD_Ipopa) CASE(UD_Ipopad) CASE(UD_Ipopfw) CASE(UD_Ipopfd) CASE(UD_Ipopfq) CASE(UD_Ipor) + CASE(UD_Iprefetch) CASE(UD_Iprefetchnta) CASE(UD_Iprefetcht0) CASE(UD_Iprefetcht1) CASE(UD_Iprefetcht2) CASE(UD_Ipsadbw) + CASE(UD_Ipshufw) CASE(UD_Ipsllw) CASE(UD_Ipslld) CASE(UD_Ipsllq) CASE(UD_Ipsraw) CASE(UD_Ipsrad) + CASE(UD_Ipsrlw) CASE(UD_Ipsrld) CASE(UD_Ipsrlq) CASE(UD_Ipsubb) CASE(UD_Ipsubw) CASE(UD_Ipsubd) + CASE(UD_Ipsubsb) CASE(UD_Ipsubsw) CASE(UD_Ipsubusb) CASE(UD_Ipsubusw) CASE(UD_Ipunpckhbw) CASE(UD_Ipunpckhwd) + CASE(UD_Ipunpckhdq) CASE(UD_Ipunpcklbw) CASE(UD_Ipunpcklwd) CASE(UD_Ipunpckldq) CASE(UD_Ipi2fw) CASE(UD_Ipi2fd) + CASE(UD_Ipf2iw) CASE(UD_Ipf2id) CASE(UD_Ipfnacc) CASE(UD_Ipfpnacc) CASE(UD_Ipfcmpge) CASE(UD_Ipfmin) + CASE(UD_Ipfrcp) CASE(UD_Ipfrsqrt) CASE(UD_Ipfsub) CASE(UD_Ipfadd) CASE(UD_Ipfcmpgt) CASE(UD_Ipfmax) + CASE(UD_Ipfrcpit1) CASE(UD_Ipfrsqit1) CASE(UD_Ipfsubr) CASE(UD_Ipfacc) CASE(UD_Ipfcmpeq) CASE(UD_Ipfmul) + CASE(UD_Ipfrcpit2) CASE(UD_Ipmulhrw) CASE(UD_Ipswapd) CASE(UD_Ipavgusb) CASE(UD_Ipush) CASE(UD_Ipusha) + CASE(UD_Ipushad) CASE(UD_Ipushfw) CASE(UD_Ipushfd) CASE(UD_Ipushfq) CASE(UD_Ipxor) CASE(UD_Ircl) + CASE(UD_Ircr) CASE(UD_Irol) CASE(UD_Iror) CASE(UD_Ircpps) CASE(UD_Ircpss) CASE(UD_Irdmsr) + CASE(UD_Irdpmc) CASE(UD_Irdtsc) CASE(UD_Irdtscp) CASE(UD_Irepne) CASE(UD_Irep) CASE(UD_Iret) + CASE(UD_Iretf) CASE(UD_Irsm) CASE(UD_Irsqrtps) CASE(UD_Irsqrtss) CASE(UD_Isahf) CASE(UD_Isalc) + CASE(UD_Isar) CASE(UD_Ishl) CASE(UD_Ishr) CASE(UD_Isbb) CASE(UD_Iscasb) CASE(UD_Iscasw) + CASE(UD_Iscasd) CASE(UD_Iscasq) CASE(UD_Iseto) CASE(UD_Isetno) CASE(UD_Isetb) CASE(UD_Isetnb) + CASE(UD_Isetz) CASE(UD_Isetnz) CASE(UD_Isetbe) CASE(UD_Iseta) CASE(UD_Isets) CASE(UD_Isetns) + CASE(UD_Isetp) CASE(UD_Isetnp) CASE(UD_Isetl) CASE(UD_Isetge) CASE(UD_Isetle) CASE(UD_Isetg) + CASE(UD_Isfence) CASE(UD_Isgdt) CASE(UD_Ishld) CASE(UD_Ishrd) CASE(UD_Ishufpd) CASE(UD_Ishufps) + CASE(UD_Isidt) CASE(UD_Isldt) CASE(UD_Ismsw) CASE(UD_Isqrtps) CASE(UD_Isqrtpd) CASE(UD_Isqrtsd) + CASE(UD_Isqrtss) CASE(UD_Istc) CASE(UD_Istd) CASE(UD_Istgi) CASE(UD_Isti) CASE(UD_Iskinit) + CASE(UD_Istmxcsr) CASE(UD_Istosb) CASE(UD_Istosw) CASE(UD_Istosd) CASE(UD_Istosq) CASE(UD_Istr) + CASE(UD_Isub) CASE(UD_Isubpd) CASE(UD_Isubps) CASE(UD_Isubsd) CASE(UD_Isubss) CASE(UD_Iswapgs) + CASE(UD_Isyscall) CASE(UD_Isysenter) CASE(UD_Isysexit) CASE(UD_Isysret) CASE(UD_Itest) CASE(UD_Iucomisd) + CASE(UD_Iucomiss) CASE(UD_Iud2) CASE(UD_Iunpckhpd) CASE(UD_Iunpckhps) CASE(UD_Iunpcklps) CASE(UD_Iunpcklpd) + CASE(UD_Iverr) CASE(UD_Iverw) CASE(UD_Ivmcall) CASE(UD_Ivmclear) CASE(UD_Ivmxon) CASE(UD_Ivmptrld) + CASE(UD_Ivmptrst) CASE(UD_Ivmlaunch) CASE(UD_Ivmresume) CASE(UD_Ivmxoff) CASE(UD_Ivmread) CASE(UD_Ivmwrite) + CASE(UD_Ivmrun) CASE(UD_Ivmmcall) CASE(UD_Ivmload) CASE(UD_Ivmsave) CASE(UD_Iwait) CASE(UD_Iwbinvd) + CASE(UD_Iwrmsr) CASE(UD_Ixadd) CASE(UD_Ixchg) CASE(UD_Ixlatb) CASE(UD_Ixor) CASE(UD_Ixorpd) + CASE(UD_Ixorps) CASE(UD_Ixcryptecb) CASE(UD_Ixcryptcbc) CASE(UD_Ixcryptctr) CASE(UD_Ixcryptcfb) CASE(UD_Ixcryptofb) + CASE(UD_Ixsha1) CASE(UD_Ixsha256) CASE(UD_Ixstore) CASE(UD_Imovdqa) CASE(UD_Imovdq2q) CASE(UD_Imovdqu) + CASE(UD_Imovq2dq) CASE(UD_Ipaddq) CASE(UD_Ipsubq) CASE(UD_Ipmuludq) CASE(UD_Ipshufhw) CASE(UD_Ipshuflw) + CASE(UD_Ipshufd) CASE(UD_Ipslldq) CASE(UD_Ipsrldq) CASE(UD_Ipunpckhqdq) CASE(UD_Ipunpcklqdq) CASE(UD_Iaddsubpd) + CASE(UD_Iaddsubps) CASE(UD_Ihaddpd) CASE(UD_Ihaddps) CASE(UD_Ihsubpd) CASE(UD_Ihsubps) CASE(UD_Imovddup) + CASE(UD_Imovshdup) CASE(UD_Imovsldup) CASE(UD_Ipabsb) CASE(UD_Ipabsw) CASE(UD_Ipabsd) CASE(UD_Ipsignb) + CASE(UD_Iphaddw) CASE(UD_Iphaddd) CASE(UD_Iphaddsw) CASE(UD_Ipmaddubsw) CASE(UD_Iphsubw) CASE(UD_Iphsubd) + CASE(UD_Iphsubsw) CASE(UD_Ipsignd) CASE(UD_Ipsignw) CASE(UD_Ipmulhrsw) CASE(UD_Ipalignr) CASE(UD_Ipblendvb) + CASE(UD_Ipmuldq) CASE(UD_Ipminsb) CASE(UD_Ipminsd) CASE(UD_Ipminuw) CASE(UD_Ipminud) CASE(UD_Ipmaxsb) + CASE(UD_Ipmaxsd) CASE(UD_Ipmaxud) CASE(UD_Ipmulld) CASE(UD_Iphminposuw) CASE(UD_Iroundps) CASE(UD_Iroundpd) + CASE(UD_Iroundss) CASE(UD_Iroundsd) CASE(UD_Iblendpd) CASE(UD_Ipblendw) CASE(UD_Iblendps) CASE(UD_Iblendvpd) + CASE(UD_Iblendvps) CASE(UD_Idpps) CASE(UD_Idppd) CASE(UD_Impsadbw) CASE(UD_Iextractps) + default: + return "???"; + } +} + +char const * +Udis86Helper::typeToString(ud_type type) +{ + switch (type) { + CASE(UD_NONE) + + /* 8 bit GPRs */ + CASE(UD_R_AL) CASE(UD_R_CL) CASE(UD_R_DL) CASE(UD_R_BL) + CASE(UD_R_AH) CASE(UD_R_CH) CASE(UD_R_DH) CASE(UD_R_BH) + CASE(UD_R_SPL) CASE(UD_R_BPL) CASE(UD_R_SIL) CASE(UD_R_DIL) + CASE(UD_R_R8B) CASE(UD_R_R9B) CASE(UD_R_R10B) CASE(UD_R_R11B) + CASE(UD_R_R12B) CASE(UD_R_R13B) CASE(UD_R_R14B) CASE(UD_R_R15B) + + /* 16 bit GPRs */ + CASE(UD_R_AX) CASE(UD_R_CX) CASE(UD_R_DX) CASE(UD_R_BX) + CASE(UD_R_SP) CASE(UD_R_BP) CASE(UD_R_SI) CASE(UD_R_DI) + CASE(UD_R_R8W) CASE(UD_R_R9W) CASE(UD_R_R10W) CASE(UD_R_R11W) + CASE(UD_R_R12W) CASE(UD_R_R13W) CASE(UD_R_R14W) CASE(UD_R_R15W) + + /* 32 bit GPRs */ + CASE(UD_R_EAX) CASE(UD_R_ECX) CASE(UD_R_EDX) CASE(UD_R_EBX) + CASE(UD_R_ESP) CASE(UD_R_EBP) CASE(UD_R_ESI) CASE(UD_R_EDI) + CASE(UD_R_R8D) CASE(UD_R_R9D) CASE(UD_R_R10D) CASE(UD_R_R11D) + CASE(UD_R_R12D) CASE(UD_R_R13D) CASE(UD_R_R14D) CASE(UD_R_R15D) + + /* 64 bit GPRs */ + CASE(UD_R_RAX) CASE(UD_R_RCX) CASE(UD_R_RDX) CASE(UD_R_RBX) + CASE(UD_R_RSP) CASE(UD_R_RBP) CASE(UD_R_RSI) CASE(UD_R_RDI) + CASE(UD_R_R8) CASE(UD_R_R9) CASE(UD_R_R10) CASE(UD_R_R11) + CASE(UD_R_R12) CASE(UD_R_R13) CASE(UD_R_R14) CASE(UD_R_R15) + + /* segment registers */ + CASE(UD_R_ES) CASE(UD_R_CS) CASE(UD_R_SS) CASE(UD_R_DS) + CASE(UD_R_FS) CASE(UD_R_GS) + + /* control registers*/ + CASE(UD_R_CR0) CASE(UD_R_CR1) CASE(UD_R_CR2) CASE(UD_R_CR3) + CASE(UD_R_CR4) CASE(UD_R_CR5) CASE(UD_R_CR6) CASE(UD_R_CR7) + CASE(UD_R_CR8) CASE(UD_R_CR9) CASE(UD_R_CR10) CASE(UD_R_CR11) + CASE(UD_R_CR12) CASE(UD_R_CR13) CASE(UD_R_CR14) CASE(UD_R_CR15) + + /* debug registers */ + CASE(UD_R_DR0) CASE(UD_R_DR1) CASE(UD_R_DR2) CASE(UD_R_DR3) + CASE(UD_R_DR4) CASE(UD_R_DR5) CASE(UD_R_DR6) CASE(UD_R_DR7) + CASE(UD_R_DR8) CASE(UD_R_DR9) CASE(UD_R_DR10) CASE(UD_R_DR11) + CASE(UD_R_DR12) CASE(UD_R_DR13) CASE(UD_R_DR14) CASE(UD_R_DR15) + + /* mmx registers */ + CASE(UD_R_MM0) CASE(UD_R_MM1) CASE(UD_R_MM2) CASE(UD_R_MM3) + CASE(UD_R_MM4) CASE(UD_R_MM5) CASE(UD_R_MM6) CASE(UD_R_MM7) + + /* x87 registers */ + CASE(UD_R_ST0) CASE(UD_R_ST1) CASE(UD_R_ST2) CASE(UD_R_ST3) + CASE(UD_R_ST4) CASE(UD_R_ST5) CASE(UD_R_ST6) CASE(UD_R_ST7) + + /* extended multimedia registers */ + CASE(UD_R_XMM0) CASE(UD_R_XMM1) CASE(UD_R_XMM2) CASE(UD_R_XMM3) + CASE(UD_R_XMM4) CASE(UD_R_XMM5) CASE(UD_R_XMM6) CASE(UD_R_XMM7) + CASE(UD_R_XMM8) CASE(UD_R_XMM9) CASE(UD_R_XMM10) CASE(UD_R_XMM11) + CASE(UD_R_XMM12) CASE(UD_R_XMM13) CASE(UD_R_XMM14) CASE(UD_R_XMM15) + + CASE(UD_R_RIP) + + /* Operand Types */ + CASE(UD_OP_REG) CASE(UD_OP_MEM) CASE(UD_OP_PTR) CASE(UD_OP_IMM) + CASE(UD_OP_JIMM) CASE(UD_OP_CONST) + default: + return "???"; + } +} +#undef CASE + +void Udis86Helper::initOpcodeModMap() +{ + // The mentioned operands only include general-purpose registers. + // Operand order in Intel style (destinations, then sources) + m[UD_Iadd].push_back(ModificationInfo(INOUT, IN)); + m[UD_Iadc].push_back(ModificationInfo(INOUT, IN)); + m[UD_Iand].push_back(ModificationInfo(INOUT, IN)); + m[UD_Icall].push_back(ModificationInfo(IN)); + m[UD_Icall].back().addImplicit(UD_R_ESP, INOUT); // reads/modifies ESP + m[UD_Icmp].push_back(ModificationInfo(IN, IN)); + m[UD_Iidiv].push_back(ModificationInfo(IN)); + m[UD_Iidiv].back().addImplicit(UD_R_EAX, INOUT); // FIXME implicit op size depends on explicit op size + m[UD_Iidiv].back().addImplicit(UD_R_EDX, INOUT); // FIXME implicit op size depends on explicit op size + m[UD_Idec].push_back(ModificationInfo(INOUT)); + m[UD_Iimul].push_back(ModificationInfo(INOUT, IN)); // two-operand version + m[UD_Iimul].push_back(ModificationInfo(OUT, IN, IN)); // three-operand version + m[UD_Iinc].push_back(ModificationInfo(INOUT)); + m[UD_Ija].push_back(ModificationInfo(IN)); + m[UD_Ijae].push_back(ModificationInfo(IN)); + m[UD_Ijb].push_back(ModificationInfo(IN)); + m[UD_Ijbe].push_back(ModificationInfo(IN)); + m[UD_Ijg].push_back(ModificationInfo(IN)); + m[UD_Ijge].push_back(ModificationInfo(IN)); + m[UD_Ijl].push_back(ModificationInfo(IN)); + m[UD_Ijle].push_back(ModificationInfo(IN)); + m[UD_Ijmp].push_back(ModificationInfo(IN)); + m[UD_Ijno].push_back(ModificationInfo(IN)); + m[UD_Ijnp].push_back(ModificationInfo(IN)); + m[UD_Ijns].push_back(ModificationInfo(IN)); + m[UD_Ijnz].push_back(ModificationInfo(IN)); + m[UD_Ijs].push_back(ModificationInfo(IN)); + m[UD_Ijz].push_back(ModificationInfo(IN)); + m[UD_Ilea].push_back(ModificationInfo(OUT, IN)); + m[UD_Ileave].push_back(ModificationInfo()); // MOV %ebp, %esp; POP %ebp + m[UD_Ileave].back().addImplicit(UD_R_EBP, INOUT); + m[UD_Ileave].back().addImplicit(UD_R_ESP, OUT); // INOUT, if not considered atomic + m[UD_Imov].push_back(ModificationInfo(OUT, IN)); + m[UD_Imovsx].push_back(ModificationInfo(OUT, IN)); + m[UD_Imovzx].push_back(ModificationInfo(OUT, IN)); + m[UD_Ineg].push_back(ModificationInfo(INOUT)); + m[UD_Inop].push_back(ModificationInfo()); + m[UD_Inot].push_back(ModificationInfo(INOUT)); + m[UD_Ior].push_back(ModificationInfo(INOUT, IN)); + m[UD_Iout].push_back(ModificationInfo(IN, IN)); + m[UD_Ipop].push_back(ModificationInfo(OUT)); + m[UD_Ipop].back().addImplicit(UD_R_ESP, INOUT); // reads/modifies ESP + m[UD_Ipush].push_back(ModificationInfo(IN)); + m[UD_Ipush].back().addImplicit(UD_R_ESP, INOUT); // reads/modifies ESP + m[UD_Iret].push_back(ModificationInfo()); + m[UD_Iret].back().addImplicit(UD_R_ESP, INOUT); // reads/modifies ESP + //m[UD_Isalc].push_back(ModificationInfo(INOUT, IN)); untested + m[UD_Isar].push_back(ModificationInfo(INOUT, IN)); + m[UD_Isetnz].push_back(ModificationInfo(OUT)); + m[UD_Ishl].push_back(ModificationInfo(INOUT, IN)); + m[UD_Ishr].push_back(ModificationInfo(INOUT, IN)); + m[UD_Isub].push_back(ModificationInfo(INOUT, IN)); + m[UD_Itest].push_back(ModificationInfo(IN, IN)); + m[UD_Ixor].push_back(ModificationInfo(INOUT, IN)); +} + +void Udis86Helper::inOutRegisters(UDRegisterSet& in, UDRegisterSet& out) +{ + unsigned nops = operandCount(); + + in.clear(); + out.clear(); + + OpcodeModificationMap::const_iterator it = m.find(ud->mnemonic); + if (it == m.end()) { + std::cerr << __func__ << ": Unknown mnemonic " + << mnemonicToString(ud->mnemonic) + << " (0x" << std::hex << ((int) ud->mnemonic) << ") :: " + << ud_insn_asm(ud); + // continue to fallback solution below + } else { + std::vector const &v = it->second; + for (std::vector::const_iterator it = v.begin(); + it != v.end(); ++it) { + if (it->dir.size() != nops) { + continue; + } + // found a match, transfer information + for (unsigned i = 0; i < nops; ++i) { + if (it->dir[i] == IN || it->dir[i] == INOUT) { + transferRegisters(in, in, i); + } + if (it->dir[i] == OUT || it->dir[i] == INOUT) { + transferRegisters(out, in, i); + } + } + // handle implicit registers, if any + for (std::vector >::const_iterator impl_it = it->implicitOperands.begin(); + impl_it != it->implicitOperands.end(); ++impl_it) { + if (impl_it->second == IN || impl_it->second == INOUT) { + in.insert(impl_it->first); + } + if (impl_it->second == OUT || impl_it->second == INOUT) { + out.insert(impl_it->first); + } + } + // handle special cases + handleSpecialCases(in, out); + return; + } + // if none found, continue to fallback solution below + } + + // Let's do our best and simply include *all* registers udis86 mentions. + // This is most certainly wrong, but (implicit registers aside) a + // conservative, safe fallback. + for (unsigned i = 0; i < nops; ++i) { + transferRegisters(in, in, i); + transferRegisters(out, in, i); + } +} + +void +Udis86Helper::transferRegisters(UDRegisterSet& target_set, UDRegisterSet& in_set, int idx) +{ + if (ud->mnemonic == UD_Isub) { +// std::cerr << "found SUB"; + } + switch (ud->operand[idx].type) { + case UD_OP_REG: + target_set.insert(ud->operand[idx].base); + /* ud->operand[opno].size? */ + break; + + case UD_OP_MEM: + /* + * Address may be calculated from a base and an index register (plus a + * scale, but this * is a constant, which we don't care about. + */ + if (ud->operand[idx].base != UD_NONE) { + in_set.insert(ud->operand[idx].base); + } + if (ud->operand[idx].index != UD_NONE) { + in_set.insert(ud->operand[idx].index); + } + break; + + case UD_OP_IMM: + case UD_OP_CONST: + case UD_NONE: + case UD_OP_JIMM: + /* + * Nothing to do here. + */ + break; + + default: + std::cerr << __func__ << ": unhandled type " << ud->operand[idx].type << std::endl; + break; + } +} + +void Udis86Helper::handleSpecialCases(UDRegisterSet& in, UDRegisterSet& out) +{ + if ((ud->mnemonic == UD_Ixor) && + (ud->operand[0].type == UD_OP_REG) && (ud->operand[1].type == UD_OP_REG) && + (ud->operand[0].base == ud->operand[1].base)) { + in.clear(); // Hard-coded. We only have 2 operands here. Simply remove the read. + } +} diff --git a/src/experiments/nanojpeg/udis86_helper.hpp b/src/experiments/nanojpeg/udis86_helper.hpp new file mode 100644 index 00000000..810202b9 --- /dev/null +++ b/src/experiments/nanojpeg/udis86_helper.hpp @@ -0,0 +1,55 @@ +#ifndef __UDIS86_HELPER_HPP__ +#define __UDIS86_HELPER_HPP__ + +#include +#include +#include +#include +#include + +class Udis86Helper { +public: + // types + enum OperandDirection { IN, OUT, INOUT, NONE }; + struct ModificationInfo { + std::vector dir; + // FIXME typedef for registerID/direction pair? + std::vector > implicitOperands; + + // order in Intel style (destinations, then sources) + ModificationInfo(OperandDirection d0 = NONE, OperandDirection d1 = NONE, OperandDirection d2 = NONE) + { + int i = (d0 != NONE) + (d1 != NONE) + (d2 != NONE); + if (i--) { dir.push_back(d0); + if (i--) { dir.push_back(d1); + if (i) dir.push_back(d2); } } + } + void addImplicit(ud_type register_id, OperandDirection dir) + { + implicitOperands.push_back(std::pair(register_id, dir)); + } + }; + // mnemonic -> vector of ModificationInfo (some instructions exist in multiple variants) + typedef std::map > OpcodeModificationMap; + typedef std::set UDRegisterSet; +private: + ud_t *ud; + OpcodeModificationMap m; + void initOpcodeModMap(); + // target_set: target set + // in_set: set of IN registers (an OUT memory operand may implicitly use IN regs) + // idx: operand index + void transferRegisters(UDRegisterSet& target_set, UDRegisterSet& in_set, int idx); + void handleSpecialCases(UDRegisterSet& in, UDRegisterSet& out); +public: + Udis86Helper() : ud(0) { initOpcodeModMap(); } + Udis86Helper(ud_t *ud) : ud(ud) { initOpcodeModMap(); } + void setUd(ud_t *newud) { ud = newud; } + void inOutRegisters(UDRegisterSet& in, UDRegisterSet& out); + char operandTypeToChar(unsigned op); + unsigned operandCount(); + static char const * mnemonicToString(unsigned mnemonic); + static char const * typeToString(ud_type type); +}; + +#endif