[python-bindings] Removed unused import byref from llvm/disassembler.py.
[oota-llvm.git] / bindings / python / llvm / disassembler.py
1 #===- disassembler.py - Python LLVM Bindings -----------------*- python -*--===#
2 #
3 #                     The LLVM Compiler Infrastructure
4 #
5 # This file is distributed under the University of Illinois Open Source
6 # License. See LICENSE.TXT for details.
7 #
8 #===------------------------------------------------------------------------===#
9
10 from ctypes import CFUNCTYPE
11 from ctypes import POINTER
12 from ctypes import addressof
13 from ctypes import c_byte
14 from ctypes import c_char_p
15 from ctypes import c_int
16 from ctypes import c_size_t
17 from ctypes import c_ubyte
18 from ctypes import c_uint64
19 from ctypes import c_void_p
20 from ctypes import cast
21
22 from .common import LLVMObject
23 from .common import c_object_p
24 from .common import get_library
25
26 __all__ = [
27     'Disassembler',
28 ]
29
30 lib = get_library()
31 callbacks = {}
32
33 # Constants for set_options
34 Option_UseMarkup = 1
35
36 class Disassembler(LLVMObject):
37     """Represents a disassembler instance.
38
39     Disassembler instances are tied to specific "triple," which must be defined
40     at creation time.
41
42     Disassembler instances can disassemble instructions from multiple sources.
43     """
44     def __init__(self, triple):
45         """Create a new disassembler instance.
46
47         The triple argument is the triple to create the disassembler for. This
48         is something like 'i386-apple-darwin9'.
49         """
50         ptr = lib.LLVMCreateDisasm(c_char_p(triple), c_void_p(None), c_int(0),
51                 callbacks['op_info'](0), callbacks['symbol_lookup'](0))
52         if not ptr.contents:
53             raise Exception('Could not obtain disassembler for triple: %s' %
54                             triple)
55
56         LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisasmDispose)
57
58     def get_instruction(self, source, pc=0):
59         """Obtain the next instruction from an input source.
60
61         The input source should be a str or bytearray or something that
62         represents a sequence of bytes.
63
64         This function will start reading bytes from the beginning of the
65         source.
66
67         The pc argument specifies the address that the first byte is at.
68
69         This returns a 2-tuple of:
70
71           long number of bytes read. 0 if no instruction was read.
72           str representation of instruction. This will be the assembly that
73             represents the instruction.
74         """
75         buf = cast(c_char_p(source), POINTER(c_ubyte))
76         out_str = cast((c_byte * 255)(), c_char_p)
77
78         result = lib.LLVMDisasmInstruction(self, buf, c_uint64(len(source)),
79                                            c_uint64(pc), out_str, 255)
80
81         return (result, out_str.value)
82
83     def get_instructions(self, source, pc=0):
84         """Obtain multiple instructions from an input source.
85
86         This is like get_instruction() except it is a generator for all
87         instructions within the source. It starts at the beginning of the
88         source and reads instructions until no more can be read.
89
90         This generator returns 3-tuple of:
91
92           long address of instruction.
93           long size of instruction, in bytes.
94           str representation of instruction.
95         """
96         source_bytes = c_char_p(source)
97         out_str = cast((c_byte * 255)(), c_char_p)
98
99         # This could probably be written cleaner. But, it does work.
100         buf = cast(source_bytes, POINTER(c_ubyte * len(source))).contents
101         offset = 0
102         address = pc
103         end_address = pc + len(source)
104         while address < end_address:
105             b = cast(addressof(buf) + offset, POINTER(c_ubyte))
106             result = lib.LLVMDisasmInstruction(self, b,
107                     c_uint64(len(source) - offset), c_uint64(address),
108                     out_str, 255)
109
110             if result == 0:
111                 break
112
113             yield (address, result, out_str.value)
114
115             address += result
116             offset += result
117
118     def set_options(self, options):
119         if not lib.LLVMSetDisasmOptions(self, options):
120             raise Exception('Unable to set all disassembler options in %i' % options)
121
122
123 def register_library(library):
124     library.LLVMCreateDisasm.argtypes = [c_char_p, c_void_p, c_int,
125         callbacks['op_info'], callbacks['symbol_lookup']]
126     library.LLVMCreateDisasm.restype = c_object_p
127
128     library.LLVMDisasmDispose.argtypes = [Disassembler]
129
130     library.LLVMDisasmInstruction.argtypes = [Disassembler, POINTER(c_ubyte),
131             c_uint64, c_uint64, c_char_p, c_size_t]
132     library.LLVMDisasmInstruction.restype = c_size_t
133
134     library.LLVMSetDisasmOptions.argtypes = [Disassembler, c_uint64]
135     library.LLVMSetDisasmOptions.restype = c_int
136
137
138 callbacks['op_info'] = CFUNCTYPE(c_int, c_void_p, c_uint64, c_uint64, c_uint64,
139                                  c_int, c_void_p)
140 callbacks['symbol_lookup'] = CFUNCTYPE(c_char_p, c_void_p, c_uint64,
141                                        POINTER(c_uint64), c_uint64,
142                                        POINTER(c_char_p))
143
144 register_library(lib)