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