xref: /aosp_15_r20/external/llvm/bindings/python/llvm/disassembler.py (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker#===- disassembler.py - Python LLVM Bindings -----------------*- python -*--===#
2*9880d681SAndroid Build Coastguard Worker#
3*9880d681SAndroid Build Coastguard Worker#                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker#
5*9880d681SAndroid Build Coastguard Worker# This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker# License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker#
8*9880d681SAndroid Build Coastguard Worker#===------------------------------------------------------------------------===#
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Workerfrom ctypes import CFUNCTYPE
11*9880d681SAndroid Build Coastguard Workerfrom ctypes import POINTER
12*9880d681SAndroid Build Coastguard Workerfrom ctypes import addressof
13*9880d681SAndroid Build Coastguard Workerfrom ctypes import c_byte
14*9880d681SAndroid Build Coastguard Workerfrom ctypes import c_char_p
15*9880d681SAndroid Build Coastguard Workerfrom ctypes import c_int
16*9880d681SAndroid Build Coastguard Workerfrom ctypes import c_size_t
17*9880d681SAndroid Build Coastguard Workerfrom ctypes import c_ubyte
18*9880d681SAndroid Build Coastguard Workerfrom ctypes import c_uint64
19*9880d681SAndroid Build Coastguard Workerfrom ctypes import c_void_p
20*9880d681SAndroid Build Coastguard Workerfrom ctypes import cast
21*9880d681SAndroid Build Coastguard Worker
22*9880d681SAndroid Build Coastguard Workerfrom .common import LLVMObject
23*9880d681SAndroid Build Coastguard Workerfrom .common import c_object_p
24*9880d681SAndroid Build Coastguard Workerfrom .common import get_library
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker__all__ = [
27*9880d681SAndroid Build Coastguard Worker    'Disassembler',
28*9880d681SAndroid Build Coastguard Worker]
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Workerlib = get_library()
31*9880d681SAndroid Build Coastguard Workercallbacks = {}
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker# Constants for set_options
34*9880d681SAndroid Build Coastguard WorkerOption_UseMarkup = 1
35*9880d681SAndroid Build Coastguard Worker
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker_initialized = False
39*9880d681SAndroid Build Coastguard Worker_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'X86', 'XCore']
40*9880d681SAndroid Build Coastguard Workerdef _ensure_initialized():
41*9880d681SAndroid Build Coastguard Worker    global _initialized
42*9880d681SAndroid Build Coastguard Worker    if not _initialized:
43*9880d681SAndroid Build Coastguard Worker        # Here one would want to call the functions
44*9880d681SAndroid Build Coastguard Worker        # LLVMInitializeAll{TargetInfo,TargetMC,Disassembler}s, but
45*9880d681SAndroid Build Coastguard Worker        # unfortunately they are only defined as static inline
46*9880d681SAndroid Build Coastguard Worker        # functions in the header files of llvm-c, so they don't exist
47*9880d681SAndroid Build Coastguard Worker        # as symbols in the shared library.
48*9880d681SAndroid Build Coastguard Worker        # So until that is fixed use this hack to initialize them all
49*9880d681SAndroid Build Coastguard Worker        for tgt in _targets:
50*9880d681SAndroid Build Coastguard Worker            for initializer in ("TargetInfo", "TargetMC", "Disassembler"):
51*9880d681SAndroid Build Coastguard Worker                try:
52*9880d681SAndroid Build Coastguard Worker                    f = getattr(lib, "LLVMInitialize" + tgt + initializer)
53*9880d681SAndroid Build Coastguard Worker                except AttributeError:
54*9880d681SAndroid Build Coastguard Worker                    continue
55*9880d681SAndroid Build Coastguard Worker                f()
56*9880d681SAndroid Build Coastguard Worker        _initialized = True
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Workerclass Disassembler(LLVMObject):
60*9880d681SAndroid Build Coastguard Worker    """Represents a disassembler instance.
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Worker    Disassembler instances are tied to specific "triple," which must be defined
63*9880d681SAndroid Build Coastguard Worker    at creation time.
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Worker    Disassembler instances can disassemble instructions from multiple sources.
66*9880d681SAndroid Build Coastguard Worker    """
67*9880d681SAndroid Build Coastguard Worker    def __init__(self, triple):
68*9880d681SAndroid Build Coastguard Worker        """Create a new disassembler instance.
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker        The triple argument is the triple to create the disassembler for. This
71*9880d681SAndroid Build Coastguard Worker        is something like 'i386-apple-darwin9'.
72*9880d681SAndroid Build Coastguard Worker        """
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker        _ensure_initialized()
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker        ptr = lib.LLVMCreateDisasm(c_char_p(triple), c_void_p(None), c_int(0),
77*9880d681SAndroid Build Coastguard Worker                callbacks['op_info'](0), callbacks['symbol_lookup'](0))
78*9880d681SAndroid Build Coastguard Worker        if not ptr:
79*9880d681SAndroid Build Coastguard Worker            raise Exception('Could not obtain disassembler for triple: %s' %
80*9880d681SAndroid Build Coastguard Worker                            triple)
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker        LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisasmDispose)
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker    def get_instruction(self, source, pc=0):
85*9880d681SAndroid Build Coastguard Worker        """Obtain the next instruction from an input source.
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Worker        The input source should be a str or bytearray or something that
88*9880d681SAndroid Build Coastguard Worker        represents a sequence of bytes.
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker        This function will start reading bytes from the beginning of the
91*9880d681SAndroid Build Coastguard Worker        source.
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker        The pc argument specifies the address that the first byte is at.
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker        This returns a 2-tuple of:
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker          long number of bytes read. 0 if no instruction was read.
98*9880d681SAndroid Build Coastguard Worker          str representation of instruction. This will be the assembly that
99*9880d681SAndroid Build Coastguard Worker            represents the instruction.
100*9880d681SAndroid Build Coastguard Worker        """
101*9880d681SAndroid Build Coastguard Worker        buf = cast(c_char_p(source), POINTER(c_ubyte))
102*9880d681SAndroid Build Coastguard Worker        out_str = cast((c_byte * 255)(), c_char_p)
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker        result = lib.LLVMDisasmInstruction(self, buf, c_uint64(len(source)),
105*9880d681SAndroid Build Coastguard Worker                                           c_uint64(pc), out_str, 255)
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker        return (result, out_str.value)
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker    def get_instructions(self, source, pc=0):
110*9880d681SAndroid Build Coastguard Worker        """Obtain multiple instructions from an input source.
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker        This is like get_instruction() except it is a generator for all
113*9880d681SAndroid Build Coastguard Worker        instructions within the source. It starts at the beginning of the
114*9880d681SAndroid Build Coastguard Worker        source and reads instructions until no more can be read.
115*9880d681SAndroid Build Coastguard Worker
116*9880d681SAndroid Build Coastguard Worker        This generator returns 3-tuple of:
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker          long address of instruction.
119*9880d681SAndroid Build Coastguard Worker          long size of instruction, in bytes.
120*9880d681SAndroid Build Coastguard Worker          str representation of instruction.
121*9880d681SAndroid Build Coastguard Worker        """
122*9880d681SAndroid Build Coastguard Worker        source_bytes = c_char_p(source)
123*9880d681SAndroid Build Coastguard Worker        out_str = cast((c_byte * 255)(), c_char_p)
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker        # This could probably be written cleaner. But, it does work.
126*9880d681SAndroid Build Coastguard Worker        buf = cast(source_bytes, POINTER(c_ubyte * len(source))).contents
127*9880d681SAndroid Build Coastguard Worker        offset = 0
128*9880d681SAndroid Build Coastguard Worker        address = pc
129*9880d681SAndroid Build Coastguard Worker        end_address = pc + len(source)
130*9880d681SAndroid Build Coastguard Worker        while address < end_address:
131*9880d681SAndroid Build Coastguard Worker            b = cast(addressof(buf) + offset, POINTER(c_ubyte))
132*9880d681SAndroid Build Coastguard Worker            result = lib.LLVMDisasmInstruction(self, b,
133*9880d681SAndroid Build Coastguard Worker                    c_uint64(len(source) - offset), c_uint64(address),
134*9880d681SAndroid Build Coastguard Worker                    out_str, 255)
135*9880d681SAndroid Build Coastguard Worker
136*9880d681SAndroid Build Coastguard Worker            if result == 0:
137*9880d681SAndroid Build Coastguard Worker                break
138*9880d681SAndroid Build Coastguard Worker
139*9880d681SAndroid Build Coastguard Worker            yield (address, result, out_str.value)
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker            address += result
142*9880d681SAndroid Build Coastguard Worker            offset += result
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker    def set_options(self, options):
145*9880d681SAndroid Build Coastguard Worker        if not lib.LLVMSetDisasmOptions(self, options):
146*9880d681SAndroid Build Coastguard Worker            raise Exception('Unable to set all disassembler options in %i' % options)
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Workerdef register_library(library):
150*9880d681SAndroid Build Coastguard Worker    library.LLVMCreateDisasm.argtypes = [c_char_p, c_void_p, c_int,
151*9880d681SAndroid Build Coastguard Worker        callbacks['op_info'], callbacks['symbol_lookup']]
152*9880d681SAndroid Build Coastguard Worker    library.LLVMCreateDisasm.restype = c_object_p
153*9880d681SAndroid Build Coastguard Worker
154*9880d681SAndroid Build Coastguard Worker    library.LLVMDisasmDispose.argtypes = [Disassembler]
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker    library.LLVMDisasmInstruction.argtypes = [Disassembler, POINTER(c_ubyte),
157*9880d681SAndroid Build Coastguard Worker            c_uint64, c_uint64, c_char_p, c_size_t]
158*9880d681SAndroid Build Coastguard Worker    library.LLVMDisasmInstruction.restype = c_size_t
159*9880d681SAndroid Build Coastguard Worker
160*9880d681SAndroid Build Coastguard Worker    library.LLVMSetDisasmOptions.argtypes = [Disassembler, c_uint64]
161*9880d681SAndroid Build Coastguard Worker    library.LLVMSetDisasmOptions.restype = c_int
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Workercallbacks['op_info'] = CFUNCTYPE(c_int, c_void_p, c_uint64, c_uint64, c_uint64,
165*9880d681SAndroid Build Coastguard Worker                                 c_int, c_void_p)
166*9880d681SAndroid Build Coastguard Workercallbacks['symbol_lookup'] = CFUNCTYPE(c_char_p, c_void_p, c_uint64,
167*9880d681SAndroid Build Coastguard Worker                                       POINTER(c_uint64), c_uint64,
168*9880d681SAndroid Build Coastguard Worker                                       POINTER(c_char_p))
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Workerregister_library(lib)
171