File: pydistorm.py

package info (click to toggle)
python-ptrace 0.9.9-0.2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 788 kB
  • sloc: python: 10,167; ansic: 263; makefile: 164
file content (127 lines) | stat: -rw-r--r-- 3,461 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"""
:[diStorm64 1.7.27}:
Copyright RageStorm (C) 2007, Gil Dabah

diStorm is licensed under the BSD license.
http://ragestorm.net/distorm/
---
Python binding of diStorm64 library written by Victor Stinner
"""

from ctypes import cdll, c_long, c_ulong, c_int, c_uint, c_char, POINTER, Structure, addressof, byref, c_void_p, create_string_buffer, sizeof, cast

# Define (u)int32_t and (u)int64_t types
int32_t = c_int
uint32_t = c_uint
if sizeof(c_ulong) == 8:
    int64_t = c_long
    uint64_t = c_ulong
else:
    from ctypes import c_longlong, c_ulonglong
    assert sizeof(c_longlong) == 8
    assert sizeof(c_ulonglong) == 8
    int64_t = c_longlong
    uint64_t = c_ulonglong

SUPPORT_64BIT_OFFSET = True
if SUPPORT_64BIT_OFFSET:
    _OffsetType = uint64_t
else:
    _OffsetType = uint32_t

LIB_FILENAME = 'libdistorm64.so'
distorm = cdll.LoadLibrary(LIB_FILENAME)
Decode16Bits = 0
Decode32Bits = 1
Decode64Bits = 2
DECODERS = (Decode16Bits, Decode32Bits, Decode64Bits)

internal_decode = distorm.internal_decode

DECRES_NONE = 0
DECRES_SUCCESS = 1
DECRES_MEMORYERR = 2
DECRES_INPUTERR = 3

MAX_INSTRUCTIONS = 100
MAX_TEXT_SIZE = 60


class _WString(Structure):
    _fields_ = (
        ("pos", c_uint),
        ("p", c_char * MAX_TEXT_SIZE),
    )

    def __str__(self):
        # FIXME: Use pos?
        return self.p


class _DecodedInst(Structure):
    _fields_ = (
        ("mnemonic", _WString),
        ("operands", _WString),
        ("instructionHex", _WString),
        ("size", c_uint),
        ("offset", _OffsetType),
    )

    def __str__(self):
        return "%s %s" % (self.mnemonic, self.operands)


internal_decode.argtypes = (_OffsetType, c_void_p,
                            c_int, c_int, c_void_p, c_uint, POINTER(c_uint))


def Decode(codeOffset, code, dt=Decode32Bits):
    """
    Errors: TypeError, IndexError, MemoryError, ValueError
    """
    # Check arguments
    if not isinstance(codeOffset, int):
        raise TypeError("codeOffset have to be an integer")
    if not isinstance(code, bytes):
        raise TypeError("code have to be a bytes, not %s"
                        % (type(code).__name__,))
    if dt not in DECODERS:
        raise IndexError(
            "Decoding-type must be either Decode16Bits, Decode32Bits or Decode64Bits.")

    # Allocate memory for decoder
    code_buffer = create_string_buffer(code)
    decodedInstructionsCount = c_uint()
    result = create_string_buffer(sizeof(_DecodedInst) * MAX_INSTRUCTIONS)

    # Prepare arguments
    codeLen = len(code)
    code = addressof(code_buffer)
    while codeLen:
        # Call internal decoder
        res = internal_decode(codeOffset, code, codeLen, dt, result,
                              MAX_INSTRUCTIONS, byref(decodedInstructionsCount))

        # Check for errors
        if res == DECRES_INPUTERR:
            raise ValueError("Invalid argument")
        count = decodedInstructionsCount.value
        if res == DECRES_MEMORYERR and not count:
            raise MemoryError()

        # No more instruction
        if not count:
            break

        # Yield instruction and compute decoded size
        size = 0
        instr_array = cast(result, POINTER(_DecodedInst))
        for index in range(count):
            instr = instr_array[index]
            size += instr.size
            yield instr

        # Update parameters to move to next instructions
        code += size
        codeOffset += size
        codeLen -= size