Imported Upstream version 5.18.0.246

Former-commit-id: 0c7ce5b1a7851e13f22acfd379b7f9fb304e4833
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-01-23 08:21:40 +00:00
parent a7724cd563
commit 279aa8f685
28482 changed files with 3866972 additions and 44 deletions

View File

@ -0,0 +1,67 @@
This directory contains Python bindings for LLVM's C library.
The bindings are currently a work in progress and are far from complete.
Use at your own risk.
Developer Info
==============
The single Python package is "llvm." Modules inside this package roughly
follow the names of the modules/headers defined by LLVM's C API.
Testing
-------
All test code is location in llvm/tests. Tests are written as classes
which inherit from llvm.tests.base.TestBase, which is a convenience base
class that provides common functionality.
Tests can be executed by installing nose:
pip install nosetests
Then by running nosetests:
nosetests
To see more output:
nosetests -v
To step into the Python debugger while running a test, add the following
to your test at the point you wish to enter the debugger:
import pdb; pdb.set_trace()
Then run nosetests:
nosetests -s -v
You should strive for high code coverage. To see current coverage:
pip install coverage
nosetests --with-coverage --cover-html
Then open cover/index.html in your browser of choice to see the code coverage.
Style Convention
----------------
All code should pass PyFlakes. First, install PyFlakes:
pip install pyflakes
Then at any time run it to see a report:
pyflakes .
Eventually we'll provide a Pylint config file. In the meantime, install
Pylint:
pip install pylint
And run:
pylint llvm
And try to keep the number of violations to a minimum.

View File

View File

@ -0,0 +1,30 @@
from .common import LLVMObject
from .common import c_object_p
from .common import get_library
from . import enumerations
from .core import MemoryBuffer
from .core import Module
from .core import OpCode
from ctypes import POINTER
from ctypes import byref
from ctypes import c_char_p
from ctypes import cast
__all__ = ['parse_bitcode']
lib = get_library()
def parse_bitcode(mem_buffer):
"""Input is .core.MemoryBuffer"""
module = c_object_p()
result = lib.LLVMParseBitcode2(mem_buffer, byref(module))
if result:
raise RuntimeError('LLVM Error')
m = Module(module)
m.take_ownership(mem_buffer)
return m
def register_library(library):
library.LLVMParseBitcode2.argtypes = [MemoryBuffer, POINTER(c_object_p)]
library.LLVMParseBitcode2.restype = bool
register_library(lib)

View File

@ -0,0 +1,126 @@
#===- common.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 POINTER
from ctypes import c_void_p
from ctypes import cdll
import ctypes.util
import platform
# LLVM_VERSION: sync with PACKAGE_VERSION in autoconf/configure.ac and CMakeLists.txt
# but leave out the 'svn' suffix.
LLVM_VERSION = '3.4'
__all__ = [
'c_object_p',
'get_library',
]
c_object_p = POINTER(c_void_p)
class LLVMObject(object):
"""Base class for objects that are backed by an LLVM data structure.
This class should never be instantiated outside of this package.
"""
def __init__(self, ptr, ownable=True, disposer=None):
assert isinstance(ptr, c_object_p)
self._ptr = self._as_parameter_ = ptr
self._self_owned = True
self._ownable = ownable
self._disposer = disposer
self._owned_objects = []
def take_ownership(self, obj):
"""Take ownership of another object.
When you take ownership of another object, you are responsible for
destroying that object. In addition, a reference to that object is
placed inside this object so the Python garbage collector will not
collect the object while it is still alive in libLLVM.
This method should likely only be called from within modules inside
this package.
"""
assert isinstance(obj, LLVMObject)
self._owned_objects.append(obj)
obj._self_owned = False
def from_param(self):
"""ctypes function that converts this object to a function parameter."""
return self._as_parameter_
def __del__(self):
if not hasattr(self, '_self_owned') or not hasattr(self, '_disposer'):
return
if self._self_owned and self._disposer:
self._disposer(self)
class CachedProperty(object):
"""Decorator that caches the result of a property lookup.
This is a useful replacement for @property. It is recommended to use this
decorator on properties that invoke C API calls for which the result of the
call will be idempotent.
"""
def __init__(self, wrapped):
self.wrapped = wrapped
try:
self.__doc__ = wrapped.__doc__
except: # pragma: no cover
pass
def __get__(self, instance, instance_type=None):
if instance is None:
return self
value = self.wrapped(instance)
setattr(instance, self.wrapped.__name__, value)
return value
def get_library():
"""Obtain a reference to the llvm library."""
# On Linux, ctypes.cdll.LoadLibrary() respects LD_LIBRARY_PATH
# while ctypes.util.find_library() doesn't.
# See http://docs.python.org/2/library/ctypes.html#finding-shared-libraries
#
# To make it possible to run the unit tests without installing the LLVM shared
# library into a default linker search path. Always Try ctypes.cdll.LoadLibrary()
# with all possible library names first, then try ctypes.util.find_library().
names = ['LLVM-' + LLVM_VERSION, 'LLVM-' + LLVM_VERSION + 'svn']
t = platform.system()
if t == 'Darwin':
pfx, ext = 'lib', '.dylib'
elif t == 'Windows':
pfx, ext = '', '.dll'
else:
pfx, ext = 'lib', '.so'
for i in names:
try:
lib = cdll.LoadLibrary(pfx + i + ext)
except OSError:
pass
else:
return lib
for i in names:
t = ctypes.util.find_library(i)
if t:
return cdll.LoadLibrary(t)
raise Exception('LLVM shared library not found!')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,170 @@
#===- 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 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 = {}
# Constants for set_options
Option_UseMarkup = 1
_initialized = False
_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'X86', 'XCore']
def _ensure_initialized():
global _initialized
if not _initialized:
# Here one would want to call the functions
# LLVMInitializeAll{TargetInfo,TargetMC,Disassembler}s, but
# unfortunately they are only defined as static inline
# functions in the header files of llvm-c, so they don't exist
# as symbols in the shared library.
# So until that is fixed use this hack to initialize them all
for tgt in _targets:
for initializer in ("TargetInfo", "TargetMC", "Disassembler"):
try:
f = getattr(lib, "LLVMInitialize" + tgt + initializer)
except AttributeError:
continue
f()
_initialized = True
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'.
"""
_ensure_initialized()
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:
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 set_options(self, options):
if not lib.LLVMSetDisasmOptions(self, options):
raise Exception('Unable to set all disassembler options in %i' % options)
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
library.LLVMSetDisasmOptions.argtypes = [Disassembler, c_uint64]
library.LLVMSetDisasmOptions.restype = c_int
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)

View File

@ -0,0 +1,211 @@
#===- enumerations.py - Python LLVM Enumerations -------------*- python -*--===#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
r"""
LLVM Enumerations
=================
This file defines enumerations from LLVM.
Each enumeration is exposed as a list of 2-tuples. These lists are consumed by
dedicated types elsewhere in the package. The enumerations are centrally
defined in this file so they are easier to locate and maintain.
"""
__all__ = [
'Attributes',
'OpCodes',
'TypeKinds',
'Linkages',
'Visibility',
'CallConv',
'IntPredicate',
'RealPredicate',
'LandingPadClauseTy',
]
Attributes = [
('ZExt', 1 << 0),
('MSExt', 1 << 1),
('NoReturn', 1 << 2),
('InReg', 1 << 3),
('StructRet', 1 << 4),
('NoUnwind', 1 << 5),
('NoAlias', 1 << 6),
('ByVal', 1 << 7),
('Nest', 1 << 8),
('ReadNone', 1 << 9),
('ReadOnly', 1 << 10),
('NoInline', 1 << 11),
('AlwaysInline', 1 << 12),
('OptimizeForSize', 1 << 13),
('StackProtect', 1 << 14),
('StackProtectReq', 1 << 15),
('Alignment', 31 << 16),
('NoCapture', 1 << 21),
('NoRedZone', 1 << 22),
('ImplicitFloat', 1 << 23),
('Naked', 1 << 24),
('InlineHint', 1 << 25),
('StackAlignment', 7 << 26),
('ReturnsTwice', 1 << 29),
('UWTable', 1 << 30),
('NonLazyBind', 1 << 31),
]
OpCodes = [
('Ret', 1),
('Br', 2),
('Switch', 3),
('IndirectBr', 4),
('Invoke', 5),
('Unreachable', 7),
('Add', 8),
('FAdd', 9),
('Sub', 10),
('FSub', 11),
('Mul', 12),
('FMul', 13),
('UDiv', 14),
('SDiv', 15),
('FDiv', 16),
('URem', 17),
('SRem', 18),
('FRem', 19),
('Shl', 20),
('LShr', 21),
('AShr', 22),
('And', 23),
('Or', 24),
('Xor', 25),
('Alloca', 26),
('Load', 27),
('Store', 28),
('GetElementPtr', 29),
('Trunc', 30),
('ZExt', 31),
('SExt', 32),
('FPToUI', 33),
('FPToSI', 34),
('UIToFP', 35),
('SIToFP', 36),
('FPTrunc', 37),
('FPExt', 38),
('PtrToInt', 39),
('IntToPtr', 40),
('BitCast', 41),
('ICmp', 42),
('FCmpl', 43),
('PHI', 44),
('Call', 45),
('Select', 46),
('UserOp1', 47),
('UserOp2', 48),
('AArg', 49),
('ExtractElement', 50),
('InsertElement', 51),
('ShuffleVector', 52),
('ExtractValue', 53),
('InsertValue', 54),
('Fence', 55),
('AtomicCmpXchg', 56),
('AtomicRMW', 57),
('Resume', 58),
('LandingPad', 59),
]
TypeKinds = [
('Void', 0),
('Half', 1),
('Float', 2),
('Double', 3),
('X86_FP80', 4),
('FP128', 5),
('PPC_FP128', 6),
('Label', 7),
('Integer', 8),
('Function', 9),
('Struct', 10),
('Array', 11),
('Pointer', 12),
('Vector', 13),
('Metadata', 14),
('X86_MMX', 15),
]
Linkages = [
('External', 0),
('AvailableExternally', 1),
('LinkOnceAny', 2),
('LinkOnceODR', 3),
('WeakAny', 4),
('WeakODR', 5),
('Appending', 6),
('Internal', 7),
('Private', 8),
('DLLImport', 9),
('DLLExport', 10),
('ExternalWeak', 11),
('Ghost', 12),
('Common', 13),
('LinkerPrivate', 14),
('LinkerPrivateWeak', 15),
('LinkerPrivateWeakDefAuto', 16),
]
Visibility = [
('Default', 0),
('Hidden', 1),
('Protected', 2),
]
CallConv = [
('CCall', 0),
('FastCall', 8),
('ColdCall', 9),
('X86StdcallCall', 64),
('X86FastcallCall', 65),
]
IntPredicate = [
('EQ', 32),
('NE', 33),
('UGT', 34),
('UGE', 35),
('ULT', 36),
('ULE', 37),
('SGT', 38),
('SGE', 39),
('SLT', 40),
('SLE', 41),
]
RealPredicate = [
('PredicateFalse', 0),
('OEQ', 1),
('OGT', 2),
('OGE', 3),
('OLT', 4),
('OLE', 5),
('ONE', 6),
('ORD', 7),
('UNO', 8),
('UEQ', 9),
('UGT', 10),
('UGE', 11),
('ULT', 12),
('ULE', 13),
('UNE', 14),
('PredicateTrue', 15),
]
LandingPadClauseTy = [
('Catch', 0),
('Filter', 1),
]

File diff suppressed because it is too large Load Diff

View File

View File

@ -0,0 +1,38 @@
import os.path
import unittest
POSSIBLE_TEST_BINARIES = [
'libreadline.so.5',
'libreadline.so.6',
]
POSSIBLE_TEST_BINARY_PATHS = [
'/usr/lib/debug',
'/lib',
'/usr/lib',
'/usr/local/lib',
'/lib/i386-linux-gnu',
]
class TestBase(unittest.TestCase):
def get_test_binary(self):
"""Helper to obtain a test binary for object file testing.
FIXME Support additional, highly-likely targets or create one
ourselves.
"""
for d in POSSIBLE_TEST_BINARY_PATHS:
for lib in POSSIBLE_TEST_BINARIES:
path = os.path.join(d, lib)
if os.path.exists(path):
return path
raise Exception('No suitable test binaries available!')
get_test_binary.__test__ = False
def get_test_file(self):
return os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_file")
def get_test_bc(self):
return os.path.join(os.path.dirname(os.path.abspath(__file__)), "test.bc")

Binary file not shown.

View File

@ -0,0 +1,15 @@
from .base import TestBase
from ..core import OpCode
from ..core import MemoryBuffer
from ..core import PassRegistry
from ..core import Context
from ..core import Module
from ..bit_reader import parse_bitcode
class TestBitReader(TestBase):
def test_parse_bitcode(self):
source = self.get_test_bc()
m = parse_bitcode(MemoryBuffer(filename=source))
print m.target
print m.datalayout

View File

@ -0,0 +1,140 @@
from .base import TestBase
from ..core import MemoryBuffer
from ..core import PassRegistry
from ..core import Context
from ..core import Module
from ..core import Enums
from ..core import OpCode
from ..bit_reader import parse_bitcode
class TestCore(TestBase):
def test_enumerations(self):
for enum_cls, enum_spec in Enums:
for enum_name, enum_value in enum_spec:
# First make sure that enum_cls has the name of the enum as an
# attribute. People will access these values as
# EnumCls.EnumName.
self.assertTrue(hasattr(enum_cls, enum_name))
v_attr = getattr(enum_cls, enum_name)
self.assertTrue(isinstance(v_attr, enum_cls))
# Then make sure that the value returned for this attribute is
# correct in both ways.
self.assertEqual(v_attr.value, enum_value)
e = enum_cls.from_value(enum_value)
self.assertTrue(isinstance(e, enum_cls))
self.assertEqual(e, v_attr)
def test_memory_buffer_create_from_file(self):
source = self.get_test_file()
MemoryBuffer(filename=source)
def test_memory_buffer_failing(self):
with self.assertRaises(Exception):
MemoryBuffer(filename="/hopefully/this/path/doesnt/exist")
def test_memory_buffer_len(self):
source = self.get_test_file()
m = MemoryBuffer(filename=source)
self.assertEqual(len(m), 50)
def test_create_passregistry(self):
PassRegistry()
def test_create_context(self):
Context.GetGlobalContext()
def test_create_module_with_name(self):
# Make sure we can not create a module without a LLVMModuleRef.
with self.assertRaises(TypeError):
m = Module()
m = Module.CreateWithName("test-module")
def test_module_getset_datalayout(self):
m = Module.CreateWithName("test-module")
dl = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"
m.datalayout = dl
self.assertEqual(m.datalayout, dl)
def test_module_getset_target(self):
m = Module.CreateWithName("test-module")
target = "thumbv7-apple-ios5.0.0"
m.target = target
self.assertEqual(m.target, target)
def test_module_print_module_to_file(self):
m = Module.CreateWithName("test")
dl = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"
m.datalayout = dl
target = "thumbv7-apple-ios5.0.0"
m.target = target
m.print_module_to_file("test2.ll")
def test_module_function_iteration(self):
m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc()))
i = 0
functions = ["f", "f2", "f3", "f4", "f5", "f6", "g1", "g2", "h1", "h2",
"h3"]
# Forward
for f in m:
self.assertEqual(f.name, functions[i])
f.dump()
i += 1
# Backwards
for f in reversed(m):
i -= 1
self.assertEqual(f.name, functions[i])
f.dump()
def test_function_basicblock_iteration(self):
m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc()))
i = 0
bb_list = ['b1', 'b2', 'end']
f = m.first
while f.name != "f6":
f = f.next
# Forward
for bb in f:
self.assertEqual(bb.name, bb_list[i])
bb.dump()
i += 1
# Backwards
for bb in reversed(f):
i -= 1
self.assertEqual(bb.name, bb_list[i])
bb.dump()
def test_basicblock_instruction_iteration(self):
m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc()))
i = 0
inst_list = [('arg1', OpCode.ExtractValue),
('arg2', OpCode.ExtractValue),
('', OpCode.Call),
('', OpCode.Ret)]
bb = m.first.first
# Forward
for inst in bb:
self.assertEqual(inst.name, inst_list[i][0])
self.assertEqual(inst.opcode, inst_list[i][1])
for op in range(len(inst)):
o = inst.get_operand(op)
print o.name
o.dump()
inst.dump()
i += 1
# Backwards
for inst in reversed(bb):
i -= 1
self.assertEqual(inst.name, inst_list[i][0])
self.assertEqual(inst.opcode, inst_list[i][1])
inst.dump()

View File

@ -0,0 +1,43 @@
from .base import TestBase
from ..disassembler import Disassembler, Option_UseMarkup
class TestDisassembler(TestBase):
def test_instantiate(self):
Disassembler('i686-apple-darwin9')
def test_basic(self):
sequence = '\x67\xe3\x81' # jcxz -127
triple = 'i686-apple-darwin9'
disassembler = Disassembler(triple)
count, s = disassembler.get_instruction(sequence)
self.assertEqual(count, 3)
self.assertEqual(s, '\tjcxz\t-127')
def test_nonexistent_triple(self):
with self.assertRaisesRegexp(Exception, "Could not obtain disassembler for triple"):
Disassembler("nonexistent-triple-raises")
def test_get_instructions(self):
sequence = '\x67\xe3\x81\x01\xc7' # jcxz -127; addl %eax, %edi
disassembler = Disassembler('i686-apple-darwin9')
instructions = list(disassembler.get_instructions(sequence))
self.assertEqual(len(instructions), 2)
self.assertEqual(instructions[0], (0, 3, '\tjcxz\t-127'))
self.assertEqual(instructions[1], (3, 2, '\taddl\t%eax, %edi'))
def test_set_options(self):
sequence = '\x10\x40\x2d\xe9'
triple = 'arm-linux-android'
disassembler = Disassembler(triple)
disassembler.set_options(Option_UseMarkup)
count, s = disassembler.get_instruction(sequence)
print s
self.assertEqual(count, 4)
self.assertEqual(s, '\tpush\t{<reg:r4>, <reg:lr>}')

View File

@ -0,0 +1 @@
I,"<22>cAG<41>xq<78><71>Ԑ<EFBFBD>d<><64><EFBFBD><1C><>vl<76><6C>\<5C>L><3E>g>`<60><><EFBFBD><EFBFBD>`<60><>wɩ

View File

@ -0,0 +1,67 @@
from .base import TestBase
from ..object import ObjectFile
from ..object import Relocation
from ..object import Section
from ..object import Symbol
class TestObjectFile(TestBase):
def get_object_file(self):
source = self.get_test_binary()
return ObjectFile(filename=source)
def test_create_from_file(self):
self.get_object_file()
def test_get_sections(self):
o = self.get_object_file()
count = 0
for section in o.get_sections():
count += 1
assert isinstance(section, Section)
assert isinstance(section.name, str)
assert isinstance(section.size, long)
assert isinstance(section.contents, str)
assert isinstance(section.address, long)
assert len(section.contents) == section.size
self.assertGreater(count, 0)
for section in o.get_sections():
section.cache()
def test_get_symbols(self):
o = self.get_object_file()
count = 0
for symbol in o.get_symbols():
count += 1
assert isinstance(symbol, Symbol)
assert isinstance(symbol.name, str)
assert isinstance(symbol.address, long)
assert isinstance(symbol.size, long)
self.assertGreater(count, 0)
for symbol in o.get_symbols():
symbol.cache()
def test_symbol_section_accessor(self):
o = self.get_object_file()
for symbol in o.get_symbols():
section = symbol.section
assert isinstance(section, Section)
break
def test_get_relocations(self):
o = self.get_object_file()
for section in o.get_sections():
for relocation in section.get_relocations():
assert isinstance(relocation, Relocation)
assert isinstance(relocation.address, long)
assert isinstance(relocation.offset, long)
assert isinstance(relocation.type_number, long)
assert isinstance(relocation.type_name, str)
assert isinstance(relocation.value_string, str)