llvm.org GIT mirror llvm / 61e22cd
[llvm.py] Implement interface to object files It is now possible to load object files and scan over sections, symbols, and relocations! Includes test code with partial coverage. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152482 91177308-0d34-0410-b5e6-96231b3b80d8 Gregory Szorc 7 years ago
10 changed file(s) with 657 addition(s) and 181 deletion(s). Raw diff Collapse all Expand all
0 This directory contains Python bindings for LLVM's C library.
1
2 The bindings are currently a work in progress and are far from complete.
3 Use at your own risk.
4
5 Developer Info
6 ==============
7
8 The single Python package is "llvm." Modules inside this package roughly
9 follow the names of the modules/headers defined by LLVM's C API.
10
11 Testing
12 -------
13
14 All test code is location in llvm/tests. Tests are written as classes
15 which inherit from llvm.tests.base.TestBase, which is a convenience base
16 class that provides common functionality.
17
18 Tests can be executed by installing nose:
19
20 pip install nosetests
21
22 Then by running nosetests:
23
24 nosetests
25
26 To see more output:
27
28 nosetests -v
29
30 To step into the Python debugger while running a test, add the following
31 to your test at the point you wish to enter the debugger:
32
33 import pdb; pdb.set_trace()
34
35 Then run nosetests:
36
37 nosetests -s -v
38
39 You should strive for high code coverage. To see current coverage:
40
41 pip install coverage
42 nosetests --with-coverage --cover-html
43
44 Then open cover/index.html in your browser of choice to see the code coverage.
45
46 Style Convention
47 ----------------
48
49 All code should pass PyFlakes. First, install PyFlakes:
50
51 pip install pyflakes
52
53 Then at any time run it to see a report:
54
55 pyflakes .
56
57 Eventually we'll provide a Pylint config file. In the meantime, install
58 Pylint:
59
60 pip install pylint
61
62 And run:
63
64 pylint llvm
65
66 And try to keep the number of violations to a minimum.
1313 import ctypes.util
1414
1515 __all__ = [
16 'LLVMObject',
16 'c_object_p',
1717 'find_library',
1818 'get_library',
1919 ]
2020
21 LLVMObject = POINTER(c_void_p)
21 c_object_p = POINTER(c_void_p)
22
23 class LLVMObject(object):
24 """Base class for objects that are backed by an LLVM data structure.
25
26 This class should never be instantiated outside of this package.
27 """
28 def __init__(self, ptr, ownable=True, disposer=None):
29 assert isinstance(ptr, c_object_p)
30
31 self._ptr = self._as_parameter_ = ptr
32
33 self._self_owned = True
34 self._ownable = ownable
35 self._disposer = disposer
36
37 self._owned_objects = []
38
39 def take_ownership(self, obj):
40 """Take ownership of another object.
41
42 When you take ownership of another object, you are responsible for
43 destroying that object. In addition, a reference to that object is
44 placed inside this object so the Python garbage collector will not
45 collect the object while it is still alive in libLLVM.
46
47 This method should likely only be called from within modules inside
48 this package.
49 """
50 assert isinstance(obj, LLVMObject)
51
52 self._owned_objects.append(obj)
53 obj._self_owned = False
54
55 def from_param(self):
56 """ctypes function that converts this object to a function parameter."""
57 return self._as_parameter_
58
59 def __del__(self):
60 if self._self_owned and self._disposer:
61 self._disposer(self)
62
63 class CachedProperty(object):
64 """Decorator that caches the result of a property lookup.
65
66 This is a useful replacement for @property. It is recommended to use this
67 decorator on properties that invoke C API calls for which the result of the
68 call will be idempotent.
69 """
70 def __init__(self, wrapped):
71 self.wrapped = wrapped
72 try:
73 self.__doc__ = wrapped.__doc__
74 except: # pragma: no cover
75 pass
76
77 def __get__(self, instance, instance_type=None):
78 if instance is None:
79 return self
80
81 value = self.wrapped(instance)
82 setattr(instance, self.wrapped.__name__, value)
83
84 return value
2285
2386 def find_library():
2487 # FIXME should probably have build system define absolute path of shared
2588 # library at install time.
26 for lib in ['LLVM-3.1svn', 'LLVM']:
89 for lib in ['LLVM-3.1svn', 'libLLVM-3.1svn', 'LLVM', 'libLLVM']:
2790 result = ctypes.util.find_library(lib)
2891 if result:
2992 return result
3093
31 # FIXME This is a local hack to ease development.
32 return "/usr/local/llvm/lib/libLLVM-3.1svn.so"
94 return None
3395
3496 def get_library():
3597 """Obtain a reference to the llvm library."""
77 #===------------------------------------------------------------------------===#
88
99 from .common import LLVMObject
10 from .common import c_object_p
1011 from .common import get_library
1112
1213 from ctypes import POINTER
1314 from ctypes import byref
1415 from ctypes import c_char_p
15 from ctypes import c_void_p
1616
1717 __all__ = [
1818 "lib",
19 "MemoryBufferRef",
19 "MemoryBuffer",
2020 ]
2121
2222 lib = get_library()
2323
24 class MemoryBuffer(object):
24 class MemoryBuffer(LLVMObject):
2525 """Represents an opaque memory buffer."""
2626
2727 def __init__(self, filename=None):
3333 if filename is None:
3434 raise Exception("filename argument must be defined")
3535
36 memory = LLVMObject()
36 memory = c_object_p()
3737 out = c_char_p(None)
3838
3939 result = lib.LLVMCreateMemoryBufferWithContentsOfFile(filename,
4242 if result:
4343 raise Exception("Could not create memory buffer: %s" % out.value)
4444
45 self._memory = memory
46 self._as_parameter_ = self._memory
47 self._owned = True
48
49 def __del__(self):
50 if self._owned:
51 lib.LLVMDisposeMemoryBuffer(self._memory)
52
53 def from_param(self):
54 return self._as_parameter_
55
56 def release_ownership(self):
57 self._owned = False
58
45 LLVMObject.__init__(self, memory, disposer=lib.LLVMDisposeMemoryBuffer)
5946
6047 def register_library(library):
6148 library.LLVMCreateMemoryBufferWithContentsOfFile.argtypes = [c_char_p,
62 POINTER(LLVMObject), POINTER(c_char_p)]
49 POINTER(c_object_p), POINTER(c_char_p)]
6350 library.LLVMCreateMemoryBufferWithContentsOfFile.restype = bool
6451
65 library.LLVMDisposeMemoryBuffer.argtypes = [c_void_p]
52 library.LLVMDisposeMemoryBuffer.argtypes = [MemoryBuffer]
6653
6754 register_library(lib)
66 #
77 #===------------------------------------------------------------------------===#
88
9 r"""
10 Object File Interface
11 =====================
12
13 This module provides an interface for reading information from object files
14 (e.g. binary executables and libraries).
15
16 Using this module, you can obtain information about an object file's sections,
17 symbols, and relocations. These are represented by the classes ObjectFile,
18 Section, Symbol, and Relocation, respectively.
19
20 Usage
21 -----
22
23 The only way to use this module is to start by creating an ObjectFile. You can
24 create an ObjectFile by loading a file (specified by its path) or by creating a
25 llvm.core.MemoryBuffer and loading that.
26
27 Once you have an object file, you can inspect its sections and symbols directly
28 by calling get_sections() and get_symbols() respectively. To inspect
29 relocations, call get_relocations() on a Section instance.
30
31 Iterator Interface
32 ------------------
33
34 The LLVM bindings expose iteration over sections, symbols, and relocations in a
35 way that only allows one instance to be operated on at a single time. This is
36 slightly annoying from a Python perspective, as it isn't very Pythonic to have
37 objects that "expire" but are still active from a dynamic language.
38
39 To aid working around this limitation, each Section, Symbol, and Relocation
40 instance caches its properties after first access. So, if the underlying
41 iterator is advanced, the properties can still be obtained provided they have
42 already been retrieved.
43
44 In addition, we also provide a "cache" method on each class to cache all
45 available data. You can call this on each obtained instance. Or, you can pass
46 cache=True to the appropriate get_XXX() method to have this done for you.
47
48 Here are some examples on how to perform iteration:
49
50 obj = ObjectFile(filename='/bin/ls')
51
52 # This is OK. Each Section is only accessed inside its own iteration slot.
53 section_names = []
54 for section in obj.get_sections():
55 section_names.append(section.name)
56
57 # This is NOT OK. You perform a lookup after the object has expired.
58 symbols = list(obj.get_symbols())
59 for symbol in symbols:
60 print symbol.name # This raises because the object has expired.
61
62 # In this example, we mix a working and failing scenario.
63 symbols = []
64 for symbol in obj.get_symbols():
65 symbols.append(symbol)
66 print symbol.name
67
68 for symbol in symbols:
69 print symbol.name # OK
70 print symbol.address # NOT OK. We didn't look up this property before.
71
72 # Cache everything up front.
73 symbols = list(obj.get_symbols(cache=True))
74 for symbol in symbols:
75 print symbol.name # OK
76
77 """
78
979 from ctypes import c_char_p
1080 from ctypes import c_uint64
11 from ctypes import c_void_p
12
81
82 from .common import CachedProperty
1383 from .common import LLVMObject
84 from .common import c_object_p
1485 from .common import get_library
1586 from .core import MemoryBuffer
1687
2293 "Symbol",
2394 ]
2495
25 class ObjectFile(object):
96 class ObjectFile(LLVMObject):
2697 """Represents an object/binary file."""
2798
2899 def __init__(self, filename=None, contents=None):
38109 if filename is not None:
39110 contents = MemoryBuffer(filename=filename)
40111
41 self._memory = contents
42 self._obj = lib.LLVMCreateObjectFile(contents)
43 contents.release_ownership()
44 self._as_parameter_ = self._obj
45
46 def __del__(self):
47 lib.LLVMDisposeObjectFile(self)
48
49 def from_param(self):
50 return self._as_parameter_
51
52 def get_sections(self):
112 if contents is None:
113 raise Exception('No input found.')
114
115 ptr = lib.LLVMCreateObjectFile(contents)
116 LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisposeObjectFile)
117 self.take_ownership(contents)
118
119 def get_sections(self, cache=False):
53120 """Obtain the sections in this object file.
54121
55 This is an iterator for llvm.object.Section instances.
56 """
57 pass
58
59 def get_symbols(self):
122 This is a generator for llvm.object.Section instances.
123
124 Sections are exposed as limited-use objects. See the module's
125 documentation on iterators for more.
126 """
127 sections = lib.LLVMGetSections(self)
128 last = None
129 while True:
130 if lib.LLVMIsSectionIteratorAtEnd(self, sections):
131 break
132
133 last = Section(sections)
134 if cache:
135 last.cache()
136
137 yield last
138
139 lib.LLVMMoveToNextSection(sections)
140 last.expire()
141
142 if last is not None:
143 last.expire()
144
145 lib.LLVMDisposeSectionIterator(sections)
146
147 def get_symbols(self, cache=False):
60148 """Obtain the symbols in this object file.
61149
62 This is an iterator for llvm.object.Symbol instances.
63 """
64
65 class Section(object):
150 This is a generator for llvm.object.Symbol instances.
151
152 Each Symbol instance is a limited-use object. See this module's
153 documentation on iterators for more.
154 """
155 symbols = lib.LLVMGetSymbols(self)
156 last = None
157 while True:
158 if lib.LLVMIsSymbolIteratorAtEnd(self, symbols):
159 break
160
161 last = Symbol(symbols, self)
162 if cache:
163 last.cache()
164
165 yield last
166
167 lib.LLVMMoveToNextSymbol(symbols)
168 last.expire()
169
170 if last is not None:
171 last.expire()
172
173 lib.LLVMDisposeSymbolIterator(symbols)
174
175 class Section(LLVMObject):
66176 """Represents a section in an object file."""
67177
68 def __init__(self, obj=None):
178 def __init__(self, ptr):
69179 """Construct a new section instance.
70180
71181 Section instances can currently only be created from an ObjectFile
72182 instance. Therefore, this constructor should not be used outside of
73183 this module.
74184 """
75 pass
76
77 def __del__(self):
78 pass
79
80 @property
185 LLVMObject.__init__(self, ptr)
186
187 self.expired = False
188
189 @CachedProperty
81190 def name(self):
82 pass
83
84 @property
191 """Obtain the string name of the section.
192
193 This is typically something like '.dynsym' or '.rodata'.
194 """
195 if self.expired:
196 raise Exception('Section instance has expired.')
197
198 return lib.LLVMGetSectionName(self)
199
200 @CachedProperty
85201 def size(self):
86 pass
87
88 @property
202 """The size of the section, in long bytes."""
203 if self.expired:
204 raise Exception('Section instance has expired.')
205
206 return lib.LLVMGetSectionSize(self)
207
208 @CachedProperty
89209 def contents(self):
90 pass
91
92 @property
210 if self.expired:
211 raise Exception('Section instance has expired.')
212
213 return lib.LLVMGetSectionContents(self)
214
215 @CachedProperty
93216 def address(self):
94 pass
95
96 # TODO consider exposing more Pythonic interface, like __contains__
217 """The address of this section, in long bytes."""
218 if self.expired:
219 raise Exception('Section instance has expired.')
220
221 return lib.LLVMGetSectionAddress(self)
222
97223 def has_symbol(self, symbol):
98 pass
99
100 def get_relocations(self):
101 pass
102
103 class Symbol(object):
104 def __init__(self):
105 pass
106
107 @property
224 """Returns whether a Symbol instance is present in this Section."""
225 if self.expired:
226 raise Exception('Section instance has expired.')
227
228 assert isinstance(symbol, Symbol)
229 return lib.LLVMGetSectionContainsSymbol(self, symbol)
230
231 def get_relocations(self, cache=False):
232 """Obtain the relocations in this Section.
233
234 This is a generator for llvm.object.Relocation instances.
235
236 Each instance is a limited used object. See this module's documentation
237 on iterators for more.
238 """
239 if self.expired:
240 raise Exception('Section instance has expired.')
241
242 relocations = lib.LLVMGetRelocations(self)
243 last = None
244 while True:
245 if lib.LLVMIsRelocationIteratorAtEnd(self, relocations):
246 break
247
248 last = Relocation(relocations)
249 if cache:
250 last.cache()
251
252 yield last
253
254 lib.LLVMMoveToNextRelocation(relocations)
255 last.expire()
256
257 if last is not None:
258 last.expire()
259
260 lib.LLVMDisposeRelocationIterator(relocations)
261
262 def cache(self):
263 """Cache properties of this Section.
264
265 This can be called as a workaround to the single active Section
266 limitation. When called, the properties of the Section are fetched so
267 they are still available after the Section has been marked inactive.
268 """
269 getattr(self, 'name')
270 getattr(self, 'size')
271 getattr(self, 'contents')
272 getattr(self, 'address')
273
274 def expire(self):
275 """Expire the section.
276
277 This is called internally by the section iterator.
278 """
279 self.expired = True
280
281 class Symbol(LLVMObject):
282 """Represents a symbol in an object file."""
283 def __init__(self, ptr, object_file):
284 assert isinstance(ptr, c_object_p)
285 assert isinstance(object_file, ObjectFile)
286
287 LLVMObject.__init__(self, ptr)
288
289 self.expired = False
290 self._object_file = object_file
291
292 @CachedProperty
108293 def name(self):
109 pass
110
111 @property
294 """The str name of the symbol.
295
296 This is often a function or variable name. Keep in mind that name
297 mangling could be in effect.
298 """
299 if self.expired:
300 raise Exception('Symbol instance has expired.')
301
302 return lib.LLVMGetSymbolName(self)
303
304 @CachedProperty
112305 def address(self):
113 pass
114
115 @property
306 """The address of this symbol, in long bytes."""
307 if self.expired:
308 raise Exception('Symbol instance has expired.')
309
310 return lib.LLVMGetSymbolAddress(self)
311
312 @CachedProperty
116313 def file_offset(self):
117 pass
118
119 @property
314 """The offset of this symbol in the file, in long bytes."""
315 if self.expired:
316 raise Exception('Symbol instance has expired.')
317
318 return lib.LLVMGetSymbolFileOffset(self)
319
320 @CachedProperty
120321 def size(self):
121 pass
122
123 class Relocation(object):
124 def __init__(self):
125 pass
126
127 @property
322 """The size of the symbol, in long bytes."""
323 if self.expired:
324 raise Exception('Symbol instance has expired.')
325
326 return lib.LLVMGetSymbolSize(self)
327
328 @CachedProperty
329 def section(self):
330 """The Section to which this Symbol belongs.
331
332 The returned Section instance does not expire, unlike Sections that are
333 commonly obtained through iteration.
334
335 Because this obtains a new section iterator each time it is accessed,
336 calling this on a number of Symbol instances could be expensive.
337 """
338 sections = lib.LLVMGetSections(self._object_file)
339 lib.LLVMMoveToContainingSection(sections, self)
340
341 return Section(sections)
342
343 def cache(self):
344 """Cache all cacheable properties."""
345 getattr(self, 'name')
346 getattr(self, 'address')
347 getattr(self, 'file_offset')
348 getattr(self, 'size')
349
350 def expire(self):
351 """Mark the object as expired to prevent future API accesses.
352
353 This is called internally by this module and it is unlikely that
354 external callers have a legitimate reason for using it.
355 """
356 self.expired = True
357
358 class Relocation(LLVMObject):
359 """Represents a relocation definition."""
360 def __init__(self, ptr):
361 """Create a new relocation instance.
362
363 Relocations are created from objects derived from Section instances.
364 Therefore, this constructor should not be called outside of this
365 module. See Section.get_relocations() for the proper method to obtain
366 a Relocation instance.
367 """
368 assert isinstance(ptr, c_object_p)
369
370 LLVMObject.__init__(self, ptr)
371
372 self.expired = False
373
374 @CachedProperty
128375 def address(self):
129 pass
130
131 @property
376 """The address of this relocation, in long bytes."""
377 if self.expired:
378 raise Exception('Relocation instance has expired.')
379
380 return lib.LLVMGetRelocationAddress(self)
381
382 @CachedProperty
132383 def offset(self):
133 pass
134
135 @property
384 """The offset of this relocation, in long bytes."""
385 if self.expired:
386 raise Exception('Relocation instance has expired.')
387
388 return lib.LLVMGetRelocationOffset(self)
389
390 @CachedProperty
136391 def symbol(self):
137 pass
138
139 @property
140 def type(self):
141 pass
142
143 @property
392 """The Symbol corresponding to this Relocation."""
393 if self.expired:
394 raise Exception('Relocation instance has expired.')
395
396 ptr = lib.LLVMGetRelocationSymbol(self)
397 return Symbol(ptr)
398
399 @CachedProperty
400 def type_number(self):
401 """The relocation type, as a long."""
402 if self.expired:
403 raise Exception('Relocation instance has expired.')
404
405 return lib.LLVMGetRelocationType(self)
406
407 @CachedProperty
144408 def type_name(self):
145 pass
146
147 @property
409 """The relocation type's name, as a str."""
410 if self.expired:
411 raise Exception('Relocation instance has expired.')
412
413 return lib.LLVMGetRelocationTypeName(self)
414
415 @CachedProperty
148416 def value_string(self):
149 pass
150
151 SectionIteratorRef = c_void_p
152 SymbolIteratorRef = c_void_p
153 RelocationIteratorRef = c_void_p
417 if self.expired:
418 raise Exception('Relocation instance has expired.')
419
420 return lib.LLVMGetRelocationValueString(self)
421
422 def expire(self):
423 """Expire this instance, making future API accesses fail."""
424 self.expired = True
425
426 def cache(self):
427 """Cache all cacheable properties on this instance."""
428 getattr(self, 'address')
429 getattr(self, 'offset')
430 getattr(self, 'symbol')
431 getattr(self, 'type')
432 getattr(self, 'type_name')
433 getattr(self, 'value_string')
154434
155435 def register_library(library):
156436 """Register function prototypes with LLVM library instance."""
157437
158438 # Object.h functions
159439 library.LLVMCreateObjectFile.argtypes = [MemoryBuffer]
160 library.LLVMCreateObjectFile.restype = LLVMObject
440 library.LLVMCreateObjectFile.restype = c_object_p
161441
162442 library.LLVMDisposeObjectFile.argtypes = [ObjectFile]
163443
164444 library.LLVMGetSections.argtypes = [ObjectFile]
165 library.LLVMGetSections.restype = SectionIteratorRef
166
167 library.LLVMDisposeSectionIterator.argtypes = [SectionIteratorRef]
168
169 library.LLVMIsSectionIteratorAtEnd.argtypes = [ObjectFile,
170 SectionIteratorRef]
445 library.LLVMGetSections.restype = c_object_p
446
447 library.LLVMDisposeSectionIterator.argtypes = [c_object_p]
448
449 library.LLVMIsSectionIteratorAtEnd.argtypes = [ObjectFile, c_object_p]
171450 library.LLVMIsSectionIteratorAtEnd.restype = bool
172451
173 library.LLVMMoveToNextSection.argtypes = [SectionIteratorRef]
174
175 library.LLVMMoveToContainingSection.argtypes = [SectionIteratorRef,
176 SymbolIteratorRef]
452 library.LLVMMoveToNextSection.argtypes = [c_object_p]
453
454 library.LLVMMoveToContainingSection.argtypes = [c_object_p, c_object_p]
177455
178456 library.LLVMGetSymbols.argtypes = [ObjectFile]
179 library.LLVMGetSymbols.restype = SymbolIteratorRef
180
181 library.LLVMDisposeSymbolIterator.argtypes = [SymbolIteratorRef]
182
183 library.LLVMIsSymbolIteratorAtEnd.argtypes = [ObjectFile,
184 SymbolIteratorRef]
457 library.LLVMGetSymbols.restype = c_object_p
458
459 library.LLVMDisposeSymbolIterator.argtypes = [c_object_p]
460
461 library.LLVMIsSymbolIteratorAtEnd.argtypes = [ObjectFile, c_object_p]
185462 library.LLVMIsSymbolIteratorAtEnd.restype = bool
186463
187 library.LLVMMoveToNextSymbol.argtypes = [SymbolIteratorRef]
188
189 library.LLVMGetSectionName.argtypes = [SectionIteratorRef]
464 library.LLVMMoveToNextSymbol.argtypes = [c_object_p]
465
466 library.LLVMGetSectionName.argtypes = [c_object_p]
190467 library.LLVMGetSectionName.restype = c_char_p
191468
192 library.LLVMGetSectionSize.argtypes = [SectionIteratorRef]
469 library.LLVMGetSectionSize.argtypes = [c_object_p]
193470 library.LLVMGetSectionSize.restype = c_uint64
194471
195 library.LLVMGetSectionContents.argtypes = [SectionIteratorRef]
472 library.LLVMGetSectionContents.argtypes = [c_object_p]
196473 library.LLVMGetSectionContents.restype = c_char_p
197474
198 library.LLVMGetSectionAddress.argtypes = [SectionIteratorRef]
475 library.LLVMGetSectionAddress.argtypes = [c_object_p]
199476 library.LLVMGetSectionAddress.restype = c_uint64
200477
201 library.LLVMGetSectionContainsSymbol.argtypes = [SectionIteratorRef,
202 SymbolIteratorRef]
478 library.LLVMGetSectionContainsSymbol.argtypes = [c_object_p, c_object_p]
203479 library.LLVMGetSectionContainsSymbol.restype = bool
204480
205 library.LLVMGetRelocations.argtypes = [SectionIteratorRef]
206 library.LLVMGetRelocations.restype = RelocationIteratorRef
207
208 library.LLVMDisposeRelocationIterator.argtypes = [RelocationIteratorRef]
209
210 library.LLVMIsRelocationIteratorAtEnd.argtypes = [SectionIteratorRef,
211 RelocationIteratorRef]
481 library.LLVMGetRelocations.argtypes = [c_object_p]
482 library.LLVMGetRelocations.restype = c_object_p
483
484 library.LLVMDisposeRelocationIterator.argtypes = [c_object_p]
485
486 library.LLVMIsRelocationIteratorAtEnd.argtypes = [c_object_p, c_object_p]
212487 library.LLVMIsRelocationIteratorAtEnd.restype = bool
213488
214 library.LLVMMoveToNextRelocation.argtypes = [RelocationIteratorRef]
215
216 library.LLVMGetSymbolName.argtypes = [SymbolIteratorRef]
489 library.LLVMMoveToNextRelocation.argtypes = [c_object_p]
490
491 library.LLVMGetSymbolName.argtypes = [Symbol]
217492 library.LLVMGetSymbolName.restype = c_char_p
218493
219 library.LLVMGetSymbolAddress.argtypes = [SymbolIteratorRef]
494 library.LLVMGetSymbolAddress.argtypes = [Symbol]
220495 library.LLVMGetSymbolAddress.restype = c_uint64
221496
222 library.LLVMGetSymbolFileOffset.argtypes = [SymbolIteratorRef]
497 library.LLVMGetSymbolFileOffset.argtypes = [Symbol]
223498 library.LLVMGetSymbolFileOffset.restype = c_uint64
224499
225 library.LLVMGetSymbolSize.argtypes = [SymbolIteratorRef]
500 library.LLVMGetSymbolSize.argtypes = [Symbol]
226501 library.LLVMGetSymbolSize.restype = c_uint64
227502
228 library.LLVMGetRelocationAddress.argtypes = [SymbolIteratorRef]
503 library.LLVMGetRelocationAddress.argtypes = [c_object_p]
229504 library.LLVMGetRelocationAddress.restype = c_uint64
230505
231 library.LLVMGetRelocationOffset.argtypes = [RelocationIteratorRef]
506 library.LLVMGetRelocationOffset.argtypes = [c_object_p]
232507 library.LLVMGetRelocationOffset.restype = c_uint64
233508
234 library.LLVMGetRelocationSymbol.argtypes = [RelocationIteratorRef]
235 library.LLVMGetRelocationSymbol.restype = SymbolIteratorRef
236
237 library.LLVMGetRelocationType.argtypes = [RelocationIteratorRef]
509 library.LLVMGetRelocationSymbol.argtypes = [c_object_p]
510 library.LLVMGetRelocationSymbol.restype = c_object_p
511
512 library.LLVMGetRelocationType.argtypes = [c_object_p]
238513 library.LLVMGetRelocationType.restype = c_uint64
239514
240 library.LLVMGetRelocationTypeName.argtypes = [RelocationIteratorRef]
515 library.LLVMGetRelocationTypeName.argtypes = [c_object_p]
241516 library.LLVMGetRelocationTypeName.restype = c_char_p
242517
243 library.LLVMGetRelocationValueString.argtypes = [RelocationIteratorRef]
518 library.LLVMGetRelocationValueString.argtypes = [c_object_p]
244519 library.LLVMGetRelocationValueString.restype = c_char_p
245520
246521 lib = get_library()
0 import os.path
1 import unittest
2
3 POSSIBLE_TEST_BINARIES = [
4 'libreadline.so.5',
5 'libreadline.so.6',
6 ]
7
8 POSSIBLE_TEST_BINARY_PATHS = [
9 '/lib',
10 '/usr/lib',
11 '/usr/local/lib',
12 ]
13
14 class TestBase(unittest.TestCase):
15 def get_test_binary(self):
16 """Helper to obtain a test binary for object file testing.
17
18 FIXME Support additional, highly-likely targets or create one
19 ourselves.
20 """
21 for d in POSSIBLE_TEST_BINARY_PATHS:
22 for lib in POSSIBLE_TEST_BINARIES:
23 path = os.path.join(d, lib)
24
25 if os.path.exists(path):
26 return path
27
28 raise Exception('No suitable test binaries available!')
0 from llvm.core import MemoryBuffer
1
2 from .base import TestBase
3
4 class TestCore(TestBase):
5 def test_memory_buffer_create_from_file(self):
6 source = self.get_test_binary()
7
8 MemoryBuffer(filename=source)
0 from .base import TestBase
1 from ..object import ObjectFile
2 from ..object import Relocation
3 from ..object import Section
4 from ..object import Symbol
5
6 class TestObjectFile(TestBase):
7 def get_object_file(self):
8 source = self.get_test_binary()
9 return ObjectFile(filename=source)
10
11 def test_create_from_file(self):
12 self.get_object_file()
13
14 def test_get_sections(self):
15 o = self.get_object_file()
16
17 count = 0
18 for section in o.get_sections():
19 count += 1
20 assert isinstance(section, Section)
21 assert isinstance(section.name, str)
22 assert isinstance(section.size, long)
23 assert isinstance(section.contents, str)
24 assert isinstance(section.address, long)
25
26 self.assertGreater(count, 0)
27
28 for section in o.get_sections():
29 section.cache()
30
31 def test_get_symbols(self):
32 o = self.get_object_file()
33
34 count = 0
35 for symbol in o.get_symbols():
36 count += 1
37 assert isinstance(symbol, Symbol)
38 assert isinstance(symbol.name, str)
39 assert isinstance(symbol.address, long)
40 assert isinstance(symbol.size, long)
41 assert isinstance(symbol.file_offset, long)
42
43 self.assertGreater(count, 0)
44
45 for symbol in o.get_symbols():
46 symbol.cache()
47
48 def test_symbol_section_accessor(self):
49 o = self.get_object_file()
50
51 for symbol in o.get_symbols():
52 section = symbol.section
53 assert isinstance(section, Section)
54
55 break
56
57 def test_get_relocations(self):
58 o = self.get_object_file()
59 for section in o.get_sections():
60 for relocation in section.get_relocations():
61 assert isinstance(relocation, Relocation)
62 assert isinstance(relocation.address, long)
63 assert isinstance(relocation.offset, long)
64 assert isinstance(relocation.type_number, long)
65 assert isinstance(relocation.type_name, str)
66 assert isinstance(relocation.value_string, str)
+0
-11
bindings/python/tests/test_core.py less more
None from llvm.common import find_library
1 from llvm.core import MemoryBuffer
2
3 import unittest
4
5 class TestCore(unittest.TestCase):
6 def test_memory_buffer_create_from_file(self):
7 source = find_library()
8 self.assertIsNotNone(source)
9
10 mb = MemoryBuffer(filename=source)
+0
-9
bindings/python/tests/test_object.py less more
None from llvm.common import find_library
1 from llvm.object import ObjectFile
2
3 import unittest
4
5 class TestObjectFile(unittest.TestCase):
6 def test_create_from_file(self):
7 source = find_library()
8 of = ObjectFile(filename=source)