from ctypes import c_char_p
from ctypes import c_char
from ctypes import POINTER
from ctypes import c_uint64
from ctypes import string_at
from .common import CachedProperty
from .common import LLVMObject
from .common import c_object_p
from .common import get_library
from .core import MemoryBuffer
__all__ = [
"lib",
"ObjectFile",
"Relocation",
"Section",
"Symbol",
]
class ObjectFile(LLVMObject):
def __init__(self, filename=None, contents=None):
if contents:
assert isinstance(contents, MemoryBuffer)
if filename is not None:
contents = MemoryBuffer(filename=filename)
if contents is None:
raise Exception('No input found.')
ptr = lib.LLVMCreateObjectFile(contents)
LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisposeObjectFile)
self.take_ownership(contents)
def get_sections(self, cache=False):
sections = lib.LLVMGetSections(self)
last = None
while True:
if lib.LLVMIsSectionIteratorAtEnd(self, sections):
break
last = Section(sections)
if cache:
last.cache()
yield last
lib.LLVMMoveToNextSection(sections)
last.expire()
if last is not None:
last.expire()
lib.LLVMDisposeSectionIterator(sections)
def get_symbols(self, cache=False):
symbols = lib.LLVMGetSymbols(self)
last = None
while True:
if lib.LLVMIsSymbolIteratorAtEnd(self, symbols):
break
last = Symbol(symbols, self)
if cache:
last.cache()
yield last
lib.LLVMMoveToNextSymbol(symbols)
last.expire()
if last is not None:
last.expire()
lib.LLVMDisposeSymbolIterator(symbols)
class Section(LLVMObject):
def __init__(self, ptr):
LLVMObject.__init__(self, ptr)
self.expired = False
@CachedProperty
def name(self):
if self.expired:
raise Exception('Section instance has expired.')
return lib.LLVMGetSectionName(self)
@CachedProperty
def size(self):
if self.expired:
raise Exception('Section instance has expired.')
return lib.LLVMGetSectionSize(self)
@CachedProperty
def contents(self):
if self.expired:
raise Exception('Section instance has expired.')
siz = self.size
r = lib.LLVMGetSectionContents(self)
if r:
return string_at(r, siz)
return None
@CachedProperty
def address(self):
if self.expired:
raise Exception('Section instance has expired.')
return lib.LLVMGetSectionAddress(self)
def has_symbol(self, symbol):
if self.expired:
raise Exception('Section instance has expired.')
assert isinstance(symbol, Symbol)
return lib.LLVMGetSectionContainsSymbol(self, symbol)
def get_relocations(self, cache=False):
if self.expired:
raise Exception('Section instance has expired.')
relocations = lib.LLVMGetRelocations(self)
last = None
while True:
if lib.LLVMIsRelocationIteratorAtEnd(self, relocations):
break
last = Relocation(relocations)
if cache:
last.cache()
yield last
lib.LLVMMoveToNextRelocation(relocations)
last.expire()
if last is not None:
last.expire()
lib.LLVMDisposeRelocationIterator(relocations)
def cache(self):
getattr(self, 'name')
getattr(self, 'size')
getattr(self, 'contents')
getattr(self, 'address')
def expire(self):
self.expired = True
class Symbol(LLVMObject):
def __init__(self, ptr, object_file):
assert isinstance(ptr, c_object_p)
assert isinstance(object_file, ObjectFile)
LLVMObject.__init__(self, ptr)
self.expired = False
self._object_file = object_file
@CachedProperty
def name(self):
if self.expired:
raise Exception('Symbol instance has expired.')
return lib.LLVMGetSymbolName(self)
@CachedProperty
def address(self):
if self.expired:
raise Exception('Symbol instance has expired.')
return lib.LLVMGetSymbolAddress(self)
@CachedProperty
def size(self):
if self.expired:
raise Exception('Symbol instance has expired.')
return lib.LLVMGetSymbolSize(self)
@CachedProperty
def section(self):
sections = lib.LLVMGetSections(self._object_file)
lib.LLVMMoveToContainingSection(sections, self)
return Section(sections)
def cache(self):
getattr(self, 'name')
getattr(self, 'address')
getattr(self, 'size')
def expire(self):
self.expired = True
class Relocation(LLVMObject):
def __init__(self, ptr):
assert isinstance(ptr, c_object_p)
LLVMObject.__init__(self, ptr)
self.expired = False
@CachedProperty
def offset(self):
if self.expired:
raise Exception('Relocation instance has expired.')
return lib.LLVMGetRelocationOffset(self)
@CachedProperty
def symbol(self):
if self.expired:
raise Exception('Relocation instance has expired.')
ptr = lib.LLVMGetRelocationSymbol(self)
return Symbol(ptr)
@CachedProperty
def type_number(self):
if self.expired:
raise Exception('Relocation instance has expired.')
return lib.LLVMGetRelocationType(self)
@CachedProperty
def type_name(self):
if self.expired:
raise Exception('Relocation instance has expired.')
return lib.LLVMGetRelocationTypeName(self)
@CachedProperty
def value_string(self):
if self.expired:
raise Exception('Relocation instance has expired.')
return lib.LLVMGetRelocationValueString(self)
def expire(self):
self.expired = True
def cache(self):
getattr(self, 'address')
getattr(self, 'offset')
getattr(self, 'symbol')
getattr(self, 'type')
getattr(self, 'type_name')
getattr(self, 'value_string')
def register_library(library):
library.LLVMCreateObjectFile.argtypes = [MemoryBuffer]
library.LLVMCreateObjectFile.restype = c_object_p
library.LLVMDisposeObjectFile.argtypes = [ObjectFile]
library.LLVMGetSections.argtypes = [ObjectFile]
library.LLVMGetSections.restype = c_object_p
library.LLVMDisposeSectionIterator.argtypes = [c_object_p]
library.LLVMIsSectionIteratorAtEnd.argtypes = [ObjectFile, c_object_p]
library.LLVMIsSectionIteratorAtEnd.restype = bool
library.LLVMMoveToNextSection.argtypes = [c_object_p]
library.LLVMMoveToContainingSection.argtypes = [c_object_p, c_object_p]
library.LLVMGetSymbols.argtypes = [ObjectFile]
library.LLVMGetSymbols.restype = c_object_p
library.LLVMDisposeSymbolIterator.argtypes = [c_object_p]
library.LLVMIsSymbolIteratorAtEnd.argtypes = [ObjectFile, c_object_p]
library.LLVMIsSymbolIteratorAtEnd.restype = bool
library.LLVMMoveToNextSymbol.argtypes = [c_object_p]
library.LLVMGetSectionName.argtypes = [c_object_p]
library.LLVMGetSectionName.restype = c_char_p
library.LLVMGetSectionSize.argtypes = [c_object_p]
library.LLVMGetSectionSize.restype = c_uint64
library.LLVMGetSectionContents.argtypes = [c_object_p]
library.LLVMGetSectionContents.restype = POINTER(c_char)
library.LLVMGetSectionAddress.argtypes = [c_object_p]
library.LLVMGetSectionAddress.restype = c_uint64
library.LLVMGetSectionContainsSymbol.argtypes = [c_object_p, c_object_p]
library.LLVMGetSectionContainsSymbol.restype = bool
library.LLVMGetRelocations.argtypes = [c_object_p]
library.LLVMGetRelocations.restype = c_object_p
library.LLVMDisposeRelocationIterator.argtypes = [c_object_p]
library.LLVMIsRelocationIteratorAtEnd.argtypes = [c_object_p, c_object_p]
library.LLVMIsRelocationIteratorAtEnd.restype = bool
library.LLVMMoveToNextRelocation.argtypes = [c_object_p]
library.LLVMGetSymbolName.argtypes = [Symbol]
library.LLVMGetSymbolName.restype = c_char_p
library.LLVMGetSymbolAddress.argtypes = [Symbol]
library.LLVMGetSymbolAddress.restype = c_uint64
library.LLVMGetSymbolSize.argtypes = [Symbol]
library.LLVMGetSymbolSize.restype = c_uint64
library.LLVMGetRelocationOffset.argtypes = [c_object_p]
library.LLVMGetRelocationOffset.restype = c_uint64
library.LLVMGetRelocationSymbol.argtypes = [c_object_p]
library.LLVMGetRelocationSymbol.restype = c_object_p
library.LLVMGetRelocationType.argtypes = [c_object_p]
library.LLVMGetRelocationType.restype = c_uint64
library.LLVMGetRelocationTypeName.argtypes = [c_object_p]
library.LLVMGetRelocationTypeName.restype = c_char_p
library.LLVMGetRelocationValueString.argtypes = [c_object_p]
library.LLVMGetRelocationValueString.restype = c_char_p
lib = get_library()
register_library(lib)