示例#1
0
_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);
}
示例#2
0
	_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;
}