mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	It doesn't currently support the op info and symbol lookup callbacks, but it is better than nothing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152527 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			135 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#===- disassembler.py - Python LLVM Bindings -----------------*- python -*--===#
 | 
						|
#
 | 
						|
#                     The LLVM Compiler Infrastructure
 | 
						|
#
 | 
						|
# This file is distributed under the University of Illinois Open Source
 | 
						|
# License. See LICENSE.TXT for details.
 | 
						|
#
 | 
						|
#===------------------------------------------------------------------------===#
 | 
						|
 | 
						|
from ctypes import CFUNCTYPE
 | 
						|
from ctypes import POINTER
 | 
						|
from ctypes import addressof
 | 
						|
from ctypes import byref
 | 
						|
from ctypes import c_byte
 | 
						|
from ctypes import c_char_p
 | 
						|
from ctypes import c_int
 | 
						|
from ctypes import c_size_t
 | 
						|
from ctypes import c_ubyte
 | 
						|
from ctypes import c_uint64
 | 
						|
from ctypes import c_void_p
 | 
						|
from ctypes import cast
 | 
						|
 | 
						|
from .common import LLVMObject
 | 
						|
from .common import c_object_p
 | 
						|
from .common import get_library
 | 
						|
 | 
						|
__all__ = [
 | 
						|
    'Disassembler',
 | 
						|
]
 | 
						|
 | 
						|
lib = get_library()
 | 
						|
callbacks = {}
 | 
						|
 | 
						|
class Disassembler(LLVMObject):
 | 
						|
    """Represents a disassembler instance.
 | 
						|
 | 
						|
    Disassembler instances are tied to specific "triple," which must be defined
 | 
						|
    at creation time.
 | 
						|
 | 
						|
    Disassembler instances can disassemble instructions from multiple sources.
 | 
						|
    """
 | 
						|
    def __init__(self, triple):
 | 
						|
        """Create a new disassembler instance.
 | 
						|
 | 
						|
        The triple argument is the triple to create the disassembler for. This
 | 
						|
        is something like 'i386-apple-darwin9'.
 | 
						|
        """
 | 
						|
        ptr = lib.LLVMCreateDisasm(c_char_p(triple), c_void_p(None), c_int(0),
 | 
						|
                callbacks['op_info'](0), callbacks['symbol_lookup'](0))
 | 
						|
        if not ptr.contents:
 | 
						|
            raise Exception('Could not obtain disassembler for triple: %s' %
 | 
						|
                            triple)
 | 
						|
 | 
						|
        LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisasmDispose)
 | 
						|
 | 
						|
    def get_instruction(self, source, pc=0):
 | 
						|
        """Obtain the next instruction from an input source.
 | 
						|
 | 
						|
        The input source should be a str or bytearray or something that
 | 
						|
        represents a sequence of bytes.
 | 
						|
 | 
						|
        This function will start reading bytes from the beginning of the
 | 
						|
        source.
 | 
						|
 | 
						|
        The pc argument specifies the address that the first byte is at.
 | 
						|
 | 
						|
        This returns a 2-tuple of:
 | 
						|
 | 
						|
          long number of bytes read. 0 if no instruction was read.
 | 
						|
          str representation of instruction. This will be the assembly that
 | 
						|
            represents the instruction.
 | 
						|
        """
 | 
						|
        buf = cast(c_char_p(source), POINTER(c_ubyte))
 | 
						|
        out_str = cast((c_byte * 255)(), c_char_p)
 | 
						|
 | 
						|
        result = lib.LLVMDisasmInstruction(self, buf, c_uint64(len(source)),
 | 
						|
                                           c_uint64(pc), out_str, 255)
 | 
						|
 | 
						|
        return (result, out_str.value)
 | 
						|
 | 
						|
    def get_instructions(self, source, pc=0):
 | 
						|
        """Obtain multiple instructions from an input source.
 | 
						|
 | 
						|
        This is like get_instruction() except it is a generator for all
 | 
						|
        instructions within the source. It starts at the beginning of the
 | 
						|
        source and reads instructions until no more can be read.
 | 
						|
 | 
						|
        This generator returns 3-tuple of:
 | 
						|
 | 
						|
          long address of instruction.
 | 
						|
          long size of instruction, in bytes.
 | 
						|
          str representation of instruction.
 | 
						|
        """
 | 
						|
        source_bytes = c_char_p(source)
 | 
						|
        out_str = cast((c_byte * 255)(), c_char_p)
 | 
						|
 | 
						|
        # This could probably be written cleaner. But, it does work.
 | 
						|
        buf = cast(source_bytes, POINTER(c_ubyte * len(source))).contents
 | 
						|
        offset = 0
 | 
						|
        address = pc
 | 
						|
        end_address = pc + len(source)
 | 
						|
        while address < end_address:
 | 
						|
            b = cast(addressof(buf) + offset, POINTER(c_ubyte))
 | 
						|
            result = lib.LLVMDisasmInstruction(self, b,
 | 
						|
                    c_uint64(len(source) - offset), c_uint64(address),
 | 
						|
                    out_str, 255)
 | 
						|
 | 
						|
            if result == 0:
 | 
						|
                break
 | 
						|
 | 
						|
            yield (address, result, out_str.value)
 | 
						|
 | 
						|
            address += result
 | 
						|
            offset += result
 | 
						|
 | 
						|
 | 
						|
def register_library(library):
 | 
						|
    library.LLVMCreateDisasm.argtypes = [c_char_p, c_void_p, c_int,
 | 
						|
        callbacks['op_info'], callbacks['symbol_lookup']]
 | 
						|
    library.LLVMCreateDisasm.restype = c_object_p
 | 
						|
 | 
						|
    library.LLVMDisasmDispose.argtypes = [Disassembler]
 | 
						|
 | 
						|
    library.LLVMDisasmInstruction.argtypes = [Disassembler, POINTER(c_ubyte),
 | 
						|
            c_uint64, c_uint64, c_char_p, c_size_t]
 | 
						|
    library.LLVMDisasmInstruction.restype = c_size_t
 | 
						|
 | 
						|
callbacks['op_info'] = CFUNCTYPE(c_int, c_void_p, c_uint64, c_uint64, c_uint64,
 | 
						|
                                 c_int, c_void_p)
 | 
						|
callbacks['symbol_lookup'] = CFUNCTYPE(c_char_p, c_void_p, c_uint64,
 | 
						|
                                       POINTER(c_uint64), c_uint64,
 | 
						|
                                       POINTER(c_char_p))
 | 
						|
 | 
						|
register_library(lib)
 |