bba20d28b1ec86acbeff4b4af62f004f64e3d8d2
[oota-llvm.git] / bindings / python / llvm / object.py
1 #===- object.py - Python Object Bindings --------------------*- python -*--===#
2 #
3 #                     The LLVM Compiler Infrastructure
4 #
5 # This file is distributed under the University of Illinois Open Source
6 # License. See LICENSE.TXT for details.
7 #
8 #===------------------------------------------------------------------------===#
9
10 r"""
11 Object File Interface
12 =====================
13
14 This module provides an interface for reading information from object files
15 (e.g. binary executables and libraries).
16
17 Using this module, you can obtain information about an object file's sections,
18 symbols, and relocations. These are represented by the classes ObjectFile,
19 Section, Symbol, and Relocation, respectively.
20
21 Usage
22 -----
23
24 The only way to use this module is to start by creating an ObjectFile. You can
25 create an ObjectFile by loading a file (specified by its path) or by creating a
26 llvm.core.MemoryBuffer and loading that.
27
28 Once you have an object file, you can inspect its sections and symbols directly
29 by calling get_sections() and get_symbols() respectively. To inspect
30 relocations, call get_relocations() on a Section instance.
31
32 Iterator Interface
33 ------------------
34
35 The LLVM bindings expose iteration over sections, symbols, and relocations in a
36 way that only allows one instance to be operated on at a single time. This is
37 slightly annoying from a Python perspective, as it isn't very Pythonic to have
38 objects that "expire" but are still active from a dynamic language.
39
40 To aid working around this limitation, each Section, Symbol, and Relocation
41 instance caches its properties after first access. So, if the underlying
42 iterator is advanced, the properties can still be obtained provided they have
43 already been retrieved.
44
45 In addition, we also provide a "cache" method on each class to cache all
46 available data. You can call this on each obtained instance. Or, you can pass
47 cache=True to the appropriate get_XXX() method to have this done for you.
48
49 Here are some examples on how to perform iteration:
50
51     obj = ObjectFile(filename='/bin/ls')
52
53     # This is OK. Each Section is only accessed inside its own iteration slot.
54     section_names = []
55     for section in obj.get_sections():
56         section_names.append(section.name)
57
58     # This is NOT OK. You perform a lookup after the object has expired.
59     symbols = list(obj.get_symbols())
60     for symbol in symbols:
61         print symbol.name # This raises because the object has expired.
62
63     # In this example, we mix a working and failing scenario.
64     symbols = []
65     for symbol in obj.get_symbols():
66         symbols.append(symbol)
67         print symbol.name
68
69     for symbol in symbols:
70         print symbol.name # OK
71         print symbol.address # NOT OK. We didn't look up this property before.
72
73     # Cache everything up front.
74     symbols = list(obj.get_symbols(cache=True))
75     for symbol in symbols:
76         print symbol.name # OK
77
78 """
79
80 from ctypes import c_char_p
81 from ctypes import c_uint64
82
83 from .common import CachedProperty
84 from .common import LLVMObject
85 from .common import c_object_p
86 from .common import get_library
87 from .core import MemoryBuffer
88
89 __all__ = [
90     "lib",
91     "ObjectFile",
92     "Relocation",
93     "Section",
94     "Symbol",
95 ]
96
97 class ObjectFile(LLVMObject):
98     """Represents an object/binary file."""
99
100     def __init__(self, filename=None, contents=None):
101         """Construct an instance from a filename or binary data.
102
103         filename must be a path to a file that can be opened with open().
104         contents can be either a native Python buffer type (like str) or a
105         llvm.core.MemoryBuffer instance.
106         """
107         if contents:
108             assert isinstance(contents, MemoryBuffer)
109
110         if filename is not None:
111             contents = MemoryBuffer(filename=filename)
112
113         if contents is None:
114             raise Exception('No input found.')
115
116         ptr = lib.LLVMCreateObjectFile(contents)
117         LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisposeObjectFile)
118         self.take_ownership(contents)
119
120     def get_sections(self, cache=False):
121         """Obtain the sections in this object file.
122
123         This is a generator for llvm.object.Section instances.
124
125         Sections are exposed as limited-use objects. See the module's
126         documentation on iterators for more.
127         """
128         sections = lib.LLVMGetSections(self)
129         last = None
130         while True:
131             if lib.LLVMIsSectionIteratorAtEnd(self, sections):
132                 break
133
134             last = Section(sections)
135             if cache:
136                 last.cache()
137
138             yield last
139
140             lib.LLVMMoveToNextSection(sections)
141             last.expire()
142
143         if last is not None:
144             last.expire()
145
146         lib.LLVMDisposeSectionIterator(sections)
147
148     def get_symbols(self, cache=False):
149         """Obtain the symbols in this object file.
150
151         This is a generator for llvm.object.Symbol instances.
152
153         Each Symbol instance is a limited-use object. See this module's
154         documentation on iterators for more.
155         """
156         symbols = lib.LLVMGetSymbols(self)
157         last = None
158         while True:
159             if lib.LLVMIsSymbolIteratorAtEnd(self, symbols):
160                 break
161
162             last = Symbol(symbols, self)
163             if cache:
164                 last.cache()
165
166             yield last
167
168             lib.LLVMMoveToNextSymbol(symbols)
169             last.expire()
170
171         if last is not None:
172             last.expire()
173
174         lib.LLVMDisposeSymbolIterator(symbols)
175
176 class Section(LLVMObject):
177     """Represents a section in an object file."""
178
179     def __init__(self, ptr):
180         """Construct a new section instance.
181
182         Section instances can currently only be created from an ObjectFile
183         instance. Therefore, this constructor should not be used outside of
184         this module.
185         """
186         LLVMObject.__init__(self, ptr)
187
188         self.expired = False
189
190     @CachedProperty
191     def name(self):
192         """Obtain the string name of the section.
193
194         This is typically something like '.dynsym' or '.rodata'.
195         """
196         if self.expired:
197             raise Exception('Section instance has expired.')
198
199         return lib.LLVMGetSectionName(self)
200
201     @CachedProperty
202     def size(self):
203         """The size of the section, in long bytes."""
204         if self.expired:
205             raise Exception('Section instance has expired.')
206
207         return lib.LLVMGetSectionSize(self)
208
209     @CachedProperty
210     def contents(self):
211         if self.expired:
212             raise Exception('Section instance has expired.')
213
214         return lib.LLVMGetSectionContents(self)
215
216     @CachedProperty
217     def address(self):
218         """The address of this section, in long bytes."""
219         if self.expired:
220             raise Exception('Section instance has expired.')
221
222         return lib.LLVMGetSectionAddress(self)
223
224     def has_symbol(self, symbol):
225         """Returns whether a Symbol instance is present in this Section."""
226         if self.expired:
227             raise Exception('Section instance has expired.')
228
229         assert isinstance(symbol, Symbol)
230         return lib.LLVMGetSectionContainsSymbol(self, symbol)
231
232     def get_relocations(self, cache=False):
233         """Obtain the relocations in this Section.
234
235         This is a generator for llvm.object.Relocation instances.
236
237         Each instance is a limited used object. See this module's documentation
238         on iterators for more.
239         """
240         if self.expired:
241             raise Exception('Section instance has expired.')
242
243         relocations = lib.LLVMGetRelocations(self)
244         last = None
245         while True:
246             if lib.LLVMIsRelocationIteratorAtEnd(self, relocations):
247                 break
248
249             last = Relocation(relocations)
250             if cache:
251                 last.cache()
252
253             yield last
254
255             lib.LLVMMoveToNextRelocation(relocations)
256             last.expire()
257
258         if last is not None:
259             last.expire()
260
261         lib.LLVMDisposeRelocationIterator(relocations)
262
263     def cache(self):
264         """Cache properties of this Section.
265
266         This can be called as a workaround to the single active Section
267         limitation. When called, the properties of the Section are fetched so
268         they are still available after the Section has been marked inactive.
269         """
270         getattr(self, 'name')
271         getattr(self, 'size')
272         getattr(self, 'contents')
273         getattr(self, 'address')
274
275     def expire(self):
276         """Expire the section.
277
278         This is called internally by the section iterator.
279         """
280         self.expired = True
281
282 class Symbol(LLVMObject):
283     """Represents a symbol in an object file."""
284     def __init__(self, ptr, object_file):
285         assert isinstance(ptr, c_object_p)
286         assert isinstance(object_file, ObjectFile)
287
288         LLVMObject.__init__(self, ptr)
289
290         self.expired = False
291         self._object_file = object_file
292
293     @CachedProperty
294     def name(self):
295         """The str name of the symbol.
296
297         This is often a function or variable name. Keep in mind that name
298         mangling could be in effect.
299         """
300         if self.expired:
301             raise Exception('Symbol instance has expired.')
302
303         return lib.LLVMGetSymbolName(self)
304
305     @CachedProperty
306     def address(self):
307         """The address of this symbol, in long bytes."""
308         if self.expired:
309             raise Exception('Symbol instance has expired.')
310
311         return lib.LLVMGetSymbolAddress(self)
312
313     @CachedProperty
314     def size(self):
315         """The size of the symbol, in long bytes."""
316         if self.expired:
317             raise Exception('Symbol instance has expired.')
318
319         return lib.LLVMGetSymbolSize(self)
320
321     @CachedProperty
322     def section(self):
323         """The Section to which this Symbol belongs.
324
325         The returned Section instance does not expire, unlike Sections that are
326         commonly obtained through iteration.
327
328         Because this obtains a new section iterator each time it is accessed,
329         calling this on a number of Symbol instances could be expensive.
330         """
331         sections = lib.LLVMGetSections(self._object_file)
332         lib.LLVMMoveToContainingSection(sections, self)
333
334         return Section(sections)
335
336     def cache(self):
337         """Cache all cacheable properties."""
338         getattr(self, 'name')
339         getattr(self, 'address')
340         getattr(self, 'size')
341
342     def expire(self):
343         """Mark the object as expired to prevent future API accesses.
344
345         This is called internally by this module and it is unlikely that
346         external callers have a legitimate reason for using it.
347         """
348         self.expired = True
349
350 class Relocation(LLVMObject):
351     """Represents a relocation definition."""
352     def __init__(self, ptr):
353         """Create a new relocation instance.
354
355         Relocations are created from objects derived from Section instances.
356         Therefore, this constructor should not be called outside of this
357         module. See Section.get_relocations() for the proper method to obtain
358         a Relocation instance.
359         """
360         assert isinstance(ptr, c_object_p)
361
362         LLVMObject.__init__(self, ptr)
363
364         self.expired = False
365
366     @CachedProperty
367     def address(self):
368         """The address of this relocation, in long bytes."""
369         if self.expired:
370             raise Exception('Relocation instance has expired.')
371
372         return lib.LLVMGetRelocationAddress(self)
373
374     @CachedProperty
375     def offset(self):
376         """The offset of this relocation, in long bytes."""
377         if self.expired:
378             raise Exception('Relocation instance has expired.')
379
380         return lib.LLVMGetRelocationOffset(self)
381
382     @CachedProperty
383     def symbol(self):
384         """The Symbol corresponding to this Relocation."""
385         if self.expired:
386             raise Exception('Relocation instance has expired.')
387
388         ptr = lib.LLVMGetRelocationSymbol(self)
389         return Symbol(ptr)
390
391     @CachedProperty
392     def type_number(self):
393         """The relocation type, as a long."""
394         if self.expired:
395             raise Exception('Relocation instance has expired.')
396
397         return lib.LLVMGetRelocationType(self)
398
399     @CachedProperty
400     def type_name(self):
401         """The relocation type's name, as a str."""
402         if self.expired:
403             raise Exception('Relocation instance has expired.')
404
405         return lib.LLVMGetRelocationTypeName(self)
406
407     @CachedProperty
408     def value_string(self):
409         if self.expired:
410             raise Exception('Relocation instance has expired.')
411
412         return lib.LLVMGetRelocationValueString(self)
413
414     def expire(self):
415         """Expire this instance, making future API accesses fail."""
416         self.expired = True
417
418     def cache(self):
419         """Cache all cacheable properties on this instance."""
420         getattr(self, 'address')
421         getattr(self, 'offset')
422         getattr(self, 'symbol')
423         getattr(self, 'type')
424         getattr(self, 'type_name')
425         getattr(self, 'value_string')
426
427 def register_library(library):
428     """Register function prototypes with LLVM library instance."""
429
430     # Object.h functions
431     library.LLVMCreateObjectFile.argtypes = [MemoryBuffer]
432     library.LLVMCreateObjectFile.restype = c_object_p
433
434     library.LLVMDisposeObjectFile.argtypes = [ObjectFile]
435
436     library.LLVMGetSections.argtypes = [ObjectFile]
437     library.LLVMGetSections.restype = c_object_p
438
439     library.LLVMDisposeSectionIterator.argtypes = [c_object_p]
440
441     library.LLVMIsSectionIteratorAtEnd.argtypes = [ObjectFile, c_object_p]
442     library.LLVMIsSectionIteratorAtEnd.restype = bool
443
444     library.LLVMMoveToNextSection.argtypes = [c_object_p]
445
446     library.LLVMMoveToContainingSection.argtypes = [c_object_p, c_object_p]
447
448     library.LLVMGetSymbols.argtypes = [ObjectFile]
449     library.LLVMGetSymbols.restype = c_object_p
450
451     library.LLVMDisposeSymbolIterator.argtypes = [c_object_p]
452
453     library.LLVMIsSymbolIteratorAtEnd.argtypes = [ObjectFile, c_object_p]
454     library.LLVMIsSymbolIteratorAtEnd.restype = bool
455
456     library.LLVMMoveToNextSymbol.argtypes = [c_object_p]
457
458     library.LLVMGetSectionName.argtypes = [c_object_p]
459     library.LLVMGetSectionName.restype = c_char_p
460
461     library.LLVMGetSectionSize.argtypes = [c_object_p]
462     library.LLVMGetSectionSize.restype = c_uint64
463
464     library.LLVMGetSectionContents.argtypes = [c_object_p]
465     library.LLVMGetSectionContents.restype = c_char_p
466
467     library.LLVMGetSectionAddress.argtypes = [c_object_p]
468     library.LLVMGetSectionAddress.restype = c_uint64
469
470     library.LLVMGetSectionContainsSymbol.argtypes = [c_object_p, c_object_p]
471     library.LLVMGetSectionContainsSymbol.restype = bool
472
473     library.LLVMGetRelocations.argtypes = [c_object_p]
474     library.LLVMGetRelocations.restype = c_object_p
475
476     library.LLVMDisposeRelocationIterator.argtypes = [c_object_p]
477
478     library.LLVMIsRelocationIteratorAtEnd.argtypes = [c_object_p, c_object_p]
479     library.LLVMIsRelocationIteratorAtEnd.restype = bool
480
481     library.LLVMMoveToNextRelocation.argtypes = [c_object_p]
482
483     library.LLVMGetSymbolName.argtypes = [Symbol]
484     library.LLVMGetSymbolName.restype = c_char_p
485
486     library.LLVMGetSymbolAddress.argtypes = [Symbol]
487     library.LLVMGetSymbolAddress.restype = c_uint64
488
489     library.LLVMGetSymbolSize.argtypes = [Symbol]
490     library.LLVMGetSymbolSize.restype = c_uint64
491
492     library.LLVMGetRelocationAddress.argtypes = [c_object_p]
493     library.LLVMGetRelocationAddress.restype = c_uint64
494
495     library.LLVMGetRelocationOffset.argtypes = [c_object_p]
496     library.LLVMGetRelocationOffset.restype = c_uint64
497
498     library.LLVMGetRelocationSymbol.argtypes = [c_object_p]
499     library.LLVMGetRelocationSymbol.restype = c_object_p
500
501     library.LLVMGetRelocationType.argtypes = [c_object_p]
502     library.LLVMGetRelocationType.restype = c_uint64
503
504     library.LLVMGetRelocationTypeName.argtypes = [c_object_p]
505     library.LLVMGetRelocationTypeName.restype = c_char_p
506
507     library.LLVMGetRelocationValueString.argtypes = [c_object_p]
508     library.LLVMGetRelocationValueString.restype = c_char_p
509
510 lib = get_library()
511 register_library(lib)