_DLLEXPORT_ _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) #endif { if (usedInstructionsCount == NULL) { return DECRES_SUCCESS; } /* DECRES_SUCCESS still may indicate we may have something in the result, so zero it first thing. */ *usedInstructionsCount = 0; if ((ci == NULL) || (ci->codeLen < 0) || ((ci->dt != Decode16Bits) && (ci->dt != Decode32Bits) && (ci->dt != Decode64Bits)) || (ci->code == NULL) || (result == NULL) || ((ci->features & (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32)) == (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32))) { return DECRES_INPUTERR; } /* Assume length=0 is success. */ if (ci->codeLen == 0) { return DECRES_SUCCESS; } return decode_internal(ci, FALSE, result, maxInstructions, usedInstructionsCount); }
_DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) #endif { _DecodeResult res; _DInst di; _CodeInfo ci; unsigned int instsCount = 0, i; *usedInstructionsCount = 0; /* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */ if (codeLen < 0) { return DECRES_INPUTERR; } if ((dt != Decode16Bits) && (dt != Decode32Bits) && (dt != Decode64Bits)) { return DECRES_INPUTERR; } if (code == NULL || result == NULL) { return DECRES_INPUTERR; } /* Assume length=0 is success. */ if (codeLen == 0) { return DECRES_SUCCESS; } /* * We have to format the result into text. But the interal decoder works with the new structure of _DInst. * Therefore, we will pass the result array(!) from the caller and the interal decoder will fill it in with _DInst's. * Then we will copy each result to a temporary structure, and use it to reformat that specific result. * * This is all done to save memory allocation and to work on the same result array in-place!!! * It's a bit ugly, I have to admit, but worth it. */ ci.codeOffset = codeOffset; ci.code = code; ci.codeLen = codeLen; ci.dt = dt; ci.features = DF_NONE; res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, &instsCount); for (i = 0; i < instsCount; i++) { if ((*usedInstructionsCount + i) >= maxInstructions) return DECRES_MEMORYERR; /* Copy the current decomposed result to a temp structure, so we can override the result with text. */ memcpy(&di, (char*)result + (i * sizeof(_DecodedInst)), sizeof(_DInst)); #ifdef SUPPORT_64BIT_OFFSET distorm_format64(&ci, &di, &result[i]); #else distorm_format32(&ci, &di, &result[i]); #endif } *usedInstructionsCount = instsCount; return res; }
xed_uint_t disas_decode_binary(const xed_state_t* dstate, const xed_uint8_t* hex_decode_text, const unsigned int bytes, xed_decoded_inst_t* xedd, xed_uint64_t runtime_address) { xed_uint64_t t1, t2; xed_error_enum_t xed_error; xed_bool_t okay; if(CLIENT_VERBOSE) { print_hex_line(hex_decode_text, bytes); } t1 = xed_get_time(); xed_error = decode_internal(xedd, hex_decode_text, bytes); t2 = xed_get_time(); okay = (xed_error == XED_ERROR_NONE); #if defined(PTI_XED_TEST) if(okay) pti_xed_test(xedd, hex_decode_text, bytes, runtime_address); #endif if(CLIENT_VERBOSE3) { xed_uint64_t delta = t2 - t1; printf("Decode time = " XED_FMT_LU "\n", delta); } if(okay) { if(CLIENT_VERBOSE1) { char tbuf[XED_TMP_BUF_LEN]; xed_decoded_inst_dump(xedd, tbuf, XED_TMP_BUF_LEN); printf("%s\n", tbuf); } if(CLIENT_VERBOSE) { char buf[XED_TMP_BUF_LEN]; if(xed_decoded_inst_valid(xedd)) { printf("ICLASS: %s CATEGORY: %s EXTENSION: %s IFORM: %s" " ISA_SET: %s\n", xed_iclass_enum_t2str(xed_decoded_inst_get_iclass(xedd)), xed_category_enum_t2str(xed_decoded_inst_get_category(xedd)), xed_extension_enum_t2str(xed_decoded_inst_get_extension(xedd)), xed_iform_enum_t2str(xed_decoded_inst_get_iform_enum(xedd)), xed_isa_set_enum_t2str(xed_decoded_inst_get_isa_set(xedd))); } memset(buf, 0, XED_TMP_BUF_LEN); disassemble(buf, XED_TMP_BUF_LEN, xedd, runtime_address, 0); printf("SHORT: %s\n", buf); } return 1; } else { xed_decode_error(0, 0, hex_decode_text, xed_error); return 0; } (void) dstate; // pacify compiler }
PyObject* distorm_Decompose(PyObject* pSelf, PyObject* pArgs) { _CodeInfo ci; _DecodeResult res = DECRES_NONE; _DInst decodedInstructions[MAX_INSTRUCTIONS]; unsigned int decodedInstructionsCount = 0, i = 0, j = 0, next = 0; PyObject *ret = NULL, *pyObj = NULL, *dtObj = NULL, *featObj = NULL, *opsObj = NULL, *o = NULL; pSelf = pSelf; /* UNREFERENCED_PARAMETER */ /* Decode(int32/64 offset, string code, int type=Decode32Bits) */ if (!PyArg_ParseTuple(pArgs, _PY_OFF_INT_SIZE_ "s#|OO", &ci.codeOffset, &ci.code, &ci.codeLen, &dtObj, &featObj)) return NULL; if (ci.code == NULL) { PyErr_SetString(PyExc_IOError, "Error while reading code buffer."); return NULL; } if (ci.codeLen < 0) { PyErr_SetString(PyExc_OverflowError, "Code length is too big."); return NULL; } /* Default parameter. */ if (dtObj == NULL) ci.dt = Decode32Bits; else if (!PyInt_Check(dtObj)) { PyErr_SetString(PyExc_IndexError, "Third parameter must be either Decode16Bits, Decode32Bits or Decode64Bits (integer type)."); return NULL; } else ci.dt = (_DecodeType)PyInt_AsUnsignedLongMask(dtObj); if ((ci.dt != Decode16Bits) && (ci.dt != Decode32Bits) && (ci.dt != Decode64Bits)) { PyErr_SetString(PyExc_IndexError, "Decoding-type must be either Decode16Bits, Decode32Bits or Decode64Bits."); return NULL; } /* Default parameter. */ if (featObj == NULL) ci.features = 0; else if (!PyInt_Check(dtObj)) { PyErr_SetString(PyExc_IndexError, "Fourth parameter must be either features flags (integer type)."); return NULL; } else ci.features = (_DecodeType)PyInt_AsUnsignedLongMask(featObj); /* Construct an empty list, which later will be filled with tuples of (offset, size, mnemonic, hex). */ ret = PyList_New(0); if (ret == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to initialize a list."); return NULL; } while (res != DECRES_SUCCESS) { res = decode_internal(&ci, FALSE, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); if ((res == DECRES_MEMORYERR) && (decodedInstructionsCount == 0)) break; for (i = 0; i < decodedInstructionsCount; i++) { opsObj = NULL; for (j = 0; j < OPERANDS_NO && decodedInstructions[i].flags != FLAG_NOT_DECODABLE; j++) { if (decodedInstructions[i].ops[j].type != O_NONE) { if (opsObj == NULL) { opsObj = PyList_New(0); if (opsObj == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate operands list."); Py_DECREF(ret); return NULL; } } pyObj = Py_BuildValue("{s:Bs:Hs:B}", "type", decodedInstructions[i].ops[j].type, "size", decodedInstructions[i].ops[j].size, "index", decodedInstructions[i].ops[j].index); if ((pyObj == NULL) || (PyList_Append(opsObj, pyObj) == -1)) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to append an operand into the list."); Py_DECREF(ret); Py_DECREF(opsObj); return NULL; } Py_DECREF(pyObj); } else break; } pyObj = Py_BuildValue("{s:" _PY_OFF_INT_SIZE_ "s:Bs:Hs:Bs:is:Hs:Bs:Bs:Bs:Ks:Hs:B}", "addr", decodedInstructions[i].addr, "size", decodedInstructions[i].size, "flags", decodedInstructions[i].flags, "segment", SEGMENT_GET(decodedInstructions[i].segment), "isSegmentDefault", SEGMENT_IS_DEFAULT(decodedInstructions[i].segment), "opcode", decodedInstructions[i].opcode, "base", decodedInstructions[i].base, "scale", decodedInstructions[i].scale, "dispSize", decodedInstructions[i].dispSize, "disp", decodedInstructions[i].disp, "unusedPrefixesMask", decodedInstructions[i].unusedPrefixesMask, "meta", decodedInstructions[i].meta); if (opsObj != NULL) { PyDict_SetItemString(pyObj, "ops", opsObj); Py_DECREF(opsObj); } /* Handle the special case where the instruction wasn't decoded. */ if (decodedInstructions[i].flags == FLAG_NOT_DECODABLE) { if ((o = PyLong_FromUnsignedLongLong(decodedInstructions[i].imm.byte)) == NULL) raise_exc(pyObj, ret); if (PyDict_SetItemString(pyObj, "imm", o) == -1) raise_exc(pyObj, ret); Py_XDECREF(o); } for (j = 0; j < OPERANDS_NO; j++) { /* Put dynamic immediate type. */ switch (decodedInstructions[i].ops[j].type) { case O_IMM: if ((o = PyLong_FromUnsignedLongLong(decodedInstructions[i].imm.qword)) == NULL) raise_exc(pyObj, ret); if (PyDict_SetItemString(pyObj, "imm", o) == -1) raise_exc(pyObj, ret); Py_XDECREF(o); break; case O_IMM1: if ((o = PyLong_FromUnsignedLong(decodedInstructions[i].imm.ex.i1)) == NULL) raise_exc(pyObj, ret); if (PyDict_SetItemString(pyObj, "imm1", o) == -1) raise_exc(pyObj, ret); Py_XDECREF(o); break; case O_IMM2: if ((o = PyLong_FromUnsignedLong(decodedInstructions[i].imm.ex.i2)) == NULL) raise_exc(pyObj, ret); if (PyDict_SetItemString(pyObj, "imm2", o) == -1) raise_exc(pyObj, ret); Py_XDECREF(o); break; case O_PTR: if ((o = PyLong_FromUnsignedLong(decodedInstructions[i].imm.ptr.seg)) == NULL) raise_exc(pyObj, ret); if (PyDict_SetItemString(pyObj, "seg", o) == -1) raise_exc(pyObj, ret); Py_XDECREF(o); if ((o = PyLong_FromUnsignedLong(decodedInstructions[i].imm.ptr.off)) == NULL) raise_exc(pyObj, ret); if (PyDict_SetItemString(pyObj, "off", o) == -1) raise_exc(pyObj, ret); Py_XDECREF(o); break; case O_PC: if ((o = PyLong_FromUnsignedLongLong(decodedInstructions[i].imm.qword)) == NULL) raise_exc(pyObj, ret); if (PyDict_SetItemString(pyObj, "imm", o) == -1) raise_exc(pyObj, ret); Py_XDECREF(o); break; } } if (pyObj == NULL) { Py_DECREF(ret); PyErr_SetString(PyExc_MemoryError, "Not enough memory to allocate an instruction."); return NULL; } if (PyList_Append(ret, pyObj) == -1) { Py_DECREF(pyObj); Py_DECREF(ret); PyErr_SetString(PyExc_MemoryError, "Not enough memory to append an instruction into the list."); return NULL; } Py_DECREF(pyObj); } /* Get offset difference. */ next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].addr - ci.codeOffset); next += decodedInstructions[decodedInstructionsCount-1].size; /* Advance ptr and recalc offset. */ ci.code += next; ci.codeLen -= next; ci.codeOffset += next; } return ret; }