1 #===- object.py - Python Object Bindings --------------------*- python -*--===#
3 # The LLVM Compiler Infrastructure
5 # This file is distributed under the University of Illinois Open Source
6 # License. See LICENSE.TXT for details.
8 #===------------------------------------------------------------------------===#
14 This module provides an interface for reading information from object files
15 (e.g. binary executables and libraries).
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.
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.
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.
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.
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.
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.
49 Here are some examples on how to perform iteration:
51 obj = ObjectFile(filename='/bin/ls')
53 # This is OK. Each Section is only accessed inside its own iteration slot.
55 for section in obj.get_sections():
56 section_names.append(section.name)
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.
63 # In this example, we mix a working and failing scenario.
65 for symbol in obj.get_symbols():
66 symbols.append(symbol)
69 for symbol in symbols:
70 print symbol.name # OK
71 print symbol.address # NOT OK. We didn't look up this property before.
73 # Cache everything up front.
74 symbols = list(obj.get_symbols(cache=True))
75 for symbol in symbols:
76 print symbol.name # OK
80 from ctypes import c_char_p
81 from ctypes import c_uint64
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
97 class ObjectFile(LLVMObject):
98 """Represents an object/binary file."""
100 def __init__(self, filename=None, contents=None):
101 """Construct an instance from a filename or binary data.
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.
108 assert isinstance(contents, MemoryBuffer)
110 if filename is not None:
111 contents = MemoryBuffer(filename=filename)
114 raise Exception('No input found.')
116 ptr = lib.LLVMCreateObjectFile(contents)
117 LLVMObject.__init__(self, ptr, disposer=lib.LLVMDisposeObjectFile)
118 self.take_ownership(contents)
120 def get_sections(self, cache=False):
121 """Obtain the sections in this object file.
123 This is a generator for llvm.object.Section instances.
125 Sections are exposed as limited-use objects. See the module's
126 documentation on iterators for more.
128 sections = lib.LLVMGetSections(self)
131 if lib.LLVMIsSectionIteratorAtEnd(self, sections):
134 last = Section(sections)
140 lib.LLVMMoveToNextSection(sections)
146 lib.LLVMDisposeSectionIterator(sections)
148 def get_symbols(self, cache=False):
149 """Obtain the symbols in this object file.
151 This is a generator for llvm.object.Symbol instances.
153 Each Symbol instance is a limited-use object. See this module's
154 documentation on iterators for more.
156 symbols = lib.LLVMGetSymbols(self)
159 if lib.LLVMIsSymbolIteratorAtEnd(self, symbols):
162 last = Symbol(symbols, self)
168 lib.LLVMMoveToNextSymbol(symbols)
174 lib.LLVMDisposeSymbolIterator(symbols)
176 class Section(LLVMObject):
177 """Represents a section in an object file."""
179 def __init__(self, ptr):
180 """Construct a new section instance.
182 Section instances can currently only be created from an ObjectFile
183 instance. Therefore, this constructor should not be used outside of
186 LLVMObject.__init__(self, ptr)
192 """Obtain the string name of the section.
194 This is typically something like '.dynsym' or '.rodata'.
197 raise Exception('Section instance has expired.')
199 return lib.LLVMGetSectionName(self)
203 """The size of the section, in long bytes."""
205 raise Exception('Section instance has expired.')
207 return lib.LLVMGetSectionSize(self)
212 raise Exception('Section instance has expired.')
214 return lib.LLVMGetSectionContents(self)
218 """The address of this section, in long bytes."""
220 raise Exception('Section instance has expired.')
222 return lib.LLVMGetSectionAddress(self)
224 def has_symbol(self, symbol):
225 """Returns whether a Symbol instance is present in this Section."""
227 raise Exception('Section instance has expired.')
229 assert isinstance(symbol, Symbol)
230 return lib.LLVMGetSectionContainsSymbol(self, symbol)
232 def get_relocations(self, cache=False):
233 """Obtain the relocations in this Section.
235 This is a generator for llvm.object.Relocation instances.
237 Each instance is a limited used object. See this module's documentation
238 on iterators for more.
241 raise Exception('Section instance has expired.')
243 relocations = lib.LLVMGetRelocations(self)
246 if lib.LLVMIsRelocationIteratorAtEnd(self, relocations):
249 last = Relocation(relocations)
255 lib.LLVMMoveToNextRelocation(relocations)
261 lib.LLVMDisposeRelocationIterator(relocations)
264 """Cache properties of this Section.
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.
270 getattr(self, 'name')
271 getattr(self, 'size')
272 getattr(self, 'contents')
273 getattr(self, 'address')
276 """Expire the section.
278 This is called internally by the section iterator.
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)
288 LLVMObject.__init__(self, ptr)
291 self._object_file = object_file
295 """The str name of the symbol.
297 This is often a function or variable name. Keep in mind that name
298 mangling could be in effect.
301 raise Exception('Symbol instance has expired.')
303 return lib.LLVMGetSymbolName(self)
307 """The address of this symbol, in long bytes."""
309 raise Exception('Symbol instance has expired.')
311 return lib.LLVMGetSymbolAddress(self)
314 def file_offset(self):
315 """The offset of this symbol in the file, in long bytes."""
317 raise Exception('Symbol instance has expired.')
319 return lib.LLVMGetSymbolFileOffset(self)
323 """The size of the symbol, in long bytes."""
325 raise Exception('Symbol instance has expired.')
327 return lib.LLVMGetSymbolSize(self)
331 """The Section to which this Symbol belongs.
333 The returned Section instance does not expire, unlike Sections that are
334 commonly obtained through iteration.
336 Because this obtains a new section iterator each time it is accessed,
337 calling this on a number of Symbol instances could be expensive.
339 sections = lib.LLVMGetSections(self._object_file)
340 lib.LLVMMoveToContainingSection(sections, self)
342 return Section(sections)
345 """Cache all cacheable properties."""
346 getattr(self, 'name')
347 getattr(self, 'address')
348 getattr(self, 'file_offset')
349 getattr(self, 'size')
352 """Mark the object as expired to prevent future API accesses.
354 This is called internally by this module and it is unlikely that
355 external callers have a legitimate reason for using it.
359 class Relocation(LLVMObject):
360 """Represents a relocation definition."""
361 def __init__(self, ptr):
362 """Create a new relocation instance.
364 Relocations are created from objects derived from Section instances.
365 Therefore, this constructor should not be called outside of this
366 module. See Section.get_relocations() for the proper method to obtain
367 a Relocation instance.
369 assert isinstance(ptr, c_object_p)
371 LLVMObject.__init__(self, ptr)
377 """The address of this relocation, in long bytes."""
379 raise Exception('Relocation instance has expired.')
381 return lib.LLVMGetRelocationAddress(self)
385 """The offset of this relocation, in long bytes."""
387 raise Exception('Relocation instance has expired.')
389 return lib.LLVMGetRelocationOffset(self)
393 """The Symbol corresponding to this Relocation."""
395 raise Exception('Relocation instance has expired.')
397 ptr = lib.LLVMGetRelocationSymbol(self)
401 def type_number(self):
402 """The relocation type, as a long."""
404 raise Exception('Relocation instance has expired.')
406 return lib.LLVMGetRelocationType(self)
410 """The relocation type's name, as a str."""
412 raise Exception('Relocation instance has expired.')
414 return lib.LLVMGetRelocationTypeName(self)
417 def value_string(self):
419 raise Exception('Relocation instance has expired.')
421 return lib.LLVMGetRelocationValueString(self)
424 """Expire this instance, making future API accesses fail."""
428 """Cache all cacheable properties on this instance."""
429 getattr(self, 'address')
430 getattr(self, 'offset')
431 getattr(self, 'symbol')
432 getattr(self, 'type')
433 getattr(self, 'type_name')
434 getattr(self, 'value_string')
436 def register_library(library):
437 """Register function prototypes with LLVM library instance."""
440 library.LLVMCreateObjectFile.argtypes = [MemoryBuffer]
441 library.LLVMCreateObjectFile.restype = c_object_p
443 library.LLVMDisposeObjectFile.argtypes = [ObjectFile]
445 library.LLVMGetSections.argtypes = [ObjectFile]
446 library.LLVMGetSections.restype = c_object_p
448 library.LLVMDisposeSectionIterator.argtypes = [c_object_p]
450 library.LLVMIsSectionIteratorAtEnd.argtypes = [ObjectFile, c_object_p]
451 library.LLVMIsSectionIteratorAtEnd.restype = bool
453 library.LLVMMoveToNextSection.argtypes = [c_object_p]
455 library.LLVMMoveToContainingSection.argtypes = [c_object_p, c_object_p]
457 library.LLVMGetSymbols.argtypes = [ObjectFile]
458 library.LLVMGetSymbols.restype = c_object_p
460 library.LLVMDisposeSymbolIterator.argtypes = [c_object_p]
462 library.LLVMIsSymbolIteratorAtEnd.argtypes = [ObjectFile, c_object_p]
463 library.LLVMIsSymbolIteratorAtEnd.restype = bool
465 library.LLVMMoveToNextSymbol.argtypes = [c_object_p]
467 library.LLVMGetSectionName.argtypes = [c_object_p]
468 library.LLVMGetSectionName.restype = c_char_p
470 library.LLVMGetSectionSize.argtypes = [c_object_p]
471 library.LLVMGetSectionSize.restype = c_uint64
473 library.LLVMGetSectionContents.argtypes = [c_object_p]
474 library.LLVMGetSectionContents.restype = c_char_p
476 library.LLVMGetSectionAddress.argtypes = [c_object_p]
477 library.LLVMGetSectionAddress.restype = c_uint64
479 library.LLVMGetSectionContainsSymbol.argtypes = [c_object_p, c_object_p]
480 library.LLVMGetSectionContainsSymbol.restype = bool
482 library.LLVMGetRelocations.argtypes = [c_object_p]
483 library.LLVMGetRelocations.restype = c_object_p
485 library.LLVMDisposeRelocationIterator.argtypes = [c_object_p]
487 library.LLVMIsRelocationIteratorAtEnd.argtypes = [c_object_p, c_object_p]
488 library.LLVMIsRelocationIteratorAtEnd.restype = bool
490 library.LLVMMoveToNextRelocation.argtypes = [c_object_p]
492 library.LLVMGetSymbolName.argtypes = [Symbol]
493 library.LLVMGetSymbolName.restype = c_char_p
495 library.LLVMGetSymbolAddress.argtypes = [Symbol]
496 library.LLVMGetSymbolAddress.restype = c_uint64
498 library.LLVMGetSymbolFileOffset.argtypes = [Symbol]
499 library.LLVMGetSymbolFileOffset.restype = c_uint64
501 library.LLVMGetSymbolSize.argtypes = [Symbol]
502 library.LLVMGetSymbolSize.restype = c_uint64
504 library.LLVMGetRelocationAddress.argtypes = [c_object_p]
505 library.LLVMGetRelocationAddress.restype = c_uint64
507 library.LLVMGetRelocationOffset.argtypes = [c_object_p]
508 library.LLVMGetRelocationOffset.restype = c_uint64
510 library.LLVMGetRelocationSymbol.argtypes = [c_object_p]
511 library.LLVMGetRelocationSymbol.restype = c_object_p
513 library.LLVMGetRelocationType.argtypes = [c_object_p]
514 library.LLVMGetRelocationType.restype = c_uint64
516 library.LLVMGetRelocationTypeName.argtypes = [c_object_p]
517 library.LLVMGetRelocationTypeName.restype = c_char_p
519 library.LLVMGetRelocationValueString.argtypes = [c_object_p]
520 library.LLVMGetRelocationValueString.restype = c_char_p
523 register_library(lib)