[csw-devel] SF.net SVN: gar:[21254] csw/mgar/pkg/lang-python/pyelftools/trunk

chninkel at users.sourceforge.net chninkel at users.sourceforge.net
Mon Jun 3 18:07:10 CEST 2013


Revision: 21254
          http://gar.svn.sourceforge.net/gar/?rev=21254&view=rev
Author:   chninkel
Date:     2013-06-03 16:07:09 +0000 (Mon, 03 Jun 2013)
Log Message:
-----------
lang-python/pyelftools/trunk: updated to last upstream code + symbol versioning support

Modified Paths:
--------------
    csw/mgar/pkg/lang-python/pyelftools/trunk/Makefile

Added Paths:
-----------
    csw/mgar/pkg/lang-python/pyelftools/trunk/files/0001-syminfo+symbol_versioning_support.patch

Modified: csw/mgar/pkg/lang-python/pyelftools/trunk/Makefile
===================================================================
--- csw/mgar/pkg/lang-python/pyelftools/trunk/Makefile	2013-06-03 16:04:14 UTC (rev 21253)
+++ csw/mgar/pkg/lang-python/pyelftools/trunk/Makefile	2013-06-03 16:07:09 UTC (rev 21254)
@@ -17,6 +17,8 @@
 PACKAGING_PLATFORMS = solaris9-sparc solaris9-i386
 PACKAGING_PLATFORMS += solaris10-sparc solaris10-i386
 
+PATCHFILES += 0001-syminfo+symbol_versioning_support.patch
+
 TEST_SCRIPTS =
 
 ARCHALL_CSWpy-pyelftools = 1

Added: csw/mgar/pkg/lang-python/pyelftools/trunk/files/0001-syminfo+symbol_versioning_support.patch
===================================================================
--- csw/mgar/pkg/lang-python/pyelftools/trunk/files/0001-syminfo+symbol_versioning_support.patch	                        (rev 0)
+++ csw/mgar/pkg/lang-python/pyelftools/trunk/files/0001-syminfo+symbol_versioning_support.patch	2013-06-03 16:07:09 UTC (rev 21254)
@@ -0,0 +1,2070 @@
+diff -r 249a5ca85159 CHANGES
+--- a/CHANGES	Wed Apr 17 05:57:58 2013 -0700
++++ b/CHANGES	Mon Jun 03 17:52:42 2013 +0200
+@@ -1,7 +1,14 @@
+ Changelog
+ =========
+ 
+-+ Version 0.22 (17.04.2013)
+++ Version 0.22 (??)
++
++  - Added some initial support for parsing Solaris OpenCSW ELF files
++    (contributed by Yann Rouillard).
++  - Added some initial support for DWARF4 (as generated by gcc 4.8)
++    and DWARF generated by recent versions of Clang (3.3).
++
+++ Version 0.21 (17.04.2013)
+ 
+   - Added new example: dwarf_decode_address - decode function name and
+     file & line information from an address.
+diff -r 249a5ca85159 elftools/dwarf/callframe.py
+--- a/elftools/dwarf/callframe.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/dwarf/callframe.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -26,13 +26,13 @@
+             Eventually, each entry gets its own structs based on the initial
+             length field it starts with. The address_size, however, is taken
+             from base_structs. This appears to be a limitation of the DWARFv3
+-            standard, fixed in v4 (where an address_size field exists for each
+-            CFI. A discussion I had on dwarf-discuss confirms this.
+-            Currently for base_structs I simply use the elfclass of the
+-            containing file, but more sophisticated methods are used by
+-            libdwarf and others, such as guessing which CU contains which FDEs
+-            (based on their address ranges) and taking the address_size from
+-            those CUs.
++            standard, fixed in v4.
++            A discussion I had on dwarf-discuss confirms this.
++            So for DWARFv4 we'll take the address size from the CIE header,
++            but for earlier versions will use the elfclass of the containing
++            file; more sophisticated methods are used by libdwarf and others,
++            such as guessing which CU contains which FDEs (based on their
++            address ranges) and taking the address_size from those CUs.
+     """
+     def __init__(self, stream, size, base_structs):
+         self.stream = stream
+@@ -99,6 +99,14 @@
+         header = struct_parse(
+             header_struct, self.stream, offset)
+ 
++        # If this is DWARF version 4 or later, we can have a more precise
++        # address size, read from the CIE header.
++        if entry_structs.dwarf_version >= 4:
++            entry_structs = DWARFStructs(
++                little_endian=entry_structs.little_endian,
++                dwarf_format=entry_structs.dwarf_format,
++                address_size=header.address_size)
++
+         # For convenience, compute the end offset for this entry
+         end_offset = (
+             offset + header.length +
+diff -r 249a5ca85159 elftools/dwarf/descriptions.py
+--- a/elftools/dwarf/descriptions.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/dwarf/descriptions.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -197,6 +197,12 @@
+     """
+     return '1' if attr.value else '0'
+ 
++def _describe_attr_present(attr, die, section_offset):
++    """ Some forms may simply mean that an attribute is present,
++        without providing any value.
++    """
++    return '1'
++
+ def _describe_attr_block(attr, die, section_offset):
+     s = '%s byte block: ' % len(attr.value)
+     s += ' '.join('%x' % item for item in attr.value) + ' '
+@@ -227,6 +233,9 @@
+     DW_FORM_block2=_describe_attr_block,
+     DW_FORM_block4=_describe_attr_block,
+     DW_FORM_block=_describe_attr_block,
++    DW_FORM_flag_present=_describe_attr_present,
++    DW_FORM_exprloc=_describe_attr_block,
++    DW_FORM_ref_sig8=_describe_attr_ref,
+ )
+ 
+ 
+diff -r 249a5ca85159 elftools/dwarf/dwarfinfo.py
+--- a/elftools/dwarf/dwarfinfo.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/dwarf/dwarfinfo.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -21,7 +21,7 @@
+ 
+ 
+ # Describes a debug section
+-# 
++#
+ # stream: a stream object containing the data of this section
+ # name: section name in the container file
+ # global_offset: the global offset of the section in its container file
+@@ -30,7 +30,7 @@
+ # 'name' and 'global_offset' are for descriptional purposes only and
+ # aren't strictly required for the DWARF parsing to work.
+ #
+-DebugSectionDescriptor = namedtuple('DebugSectionDescriptor', 
++DebugSectionDescriptor = namedtuple('DebugSectionDescriptor',
+     'stream name global_offset size')
+ 
+ 
+@@ -51,7 +51,7 @@
+ 
+ 
+ class DWARFInfo(object):
+-    """ Acts also as a "context" to other major objects, bridging between 
++    """ Acts also as a "context" to other major objects, bridging between
+         various parts of the debug infromation.
+     """
+     def __init__(self,
+@@ -59,6 +59,7 @@
+             debug_info_sec,
+             debug_abbrev_sec,
+             debug_frame_sec,
++            eh_frame_sec,
+             debug_str_sec,
+             debug_loc_sec,
+             debug_ranges_sec,
+@@ -68,19 +69,20 @@
+ 
+             debug_*_sec:
+                 DebugSectionDescriptor for a section. Pass None for sections
+-                that don't exist. These arguments are best given with 
++                that don't exist. These arguments are best given with
+                 keyword syntax.
+         """
+         self.config = config
+         self.debug_info_sec = debug_info_sec
+         self.debug_abbrev_sec = debug_abbrev_sec
+         self.debug_frame_sec = debug_frame_sec
++        self.eh_frame_sec = eh_frame_sec
+         self.debug_str_sec = debug_str_sec
+         self.debug_loc_sec = debug_loc_sec
+         self.debug_ranges_sec = debug_ranges_sec
+         self.debug_line_sec = debug_line_sec
+ 
+-        # This is the DWARFStructs the context uses, so it doesn't depend on 
++        # This is the DWARFStructs the context uses, so it doesn't depend on
+         # DWARF format and address_size (these are determined per CU) - set them
+         # to default values.
+         self.structs = DWARFStructs(
+@@ -119,7 +121,7 @@
+         return self._abbrevtable_cache[offset]
+ 
+     def get_string_from_table(self, offset):
+-        """ Obtain a string from the string table section, given an offset 
++        """ Obtain a string from the string table section, given an offset
+             relative to the section.
+         """
+         return parse_cstring_from_stream(self.debug_str_sec.stream, offset)
+@@ -139,12 +141,12 @@
+             return None
+ 
+     def has_CFI(self):
+-        """ Does this dwarf info has a CFI section?
++        """ Does this dwarf info have a dwarf_frame CFI section?
+         """
+         return self.debug_frame_sec is not None
+ 
+     def CFI_entries(self):
+-        """ Get a list of CFI entries from the .debug_frame section.
++        """ Get a list of dwarf_frame CFI entries from the .debug_frame section.
+         """
+         cfi = CallFrameInfo(
+             stream=self.debug_frame_sec.stream,
+@@ -152,6 +154,20 @@
+             base_structs=self.structs)
+         return cfi.get_entries()
+ 
++    def has_EH_CFI(self):
++        """ Does this dwarf info have a eh_frame CFI section?
++        """
++        return self.eh_frame_sec is not None
++
++    def EH_CFI_entries(self):
++        """ Get a list of eh_frame CFI entries from the .eh_frame section.
++        """
++        cfi = CallFrameInfo(
++            stream=self.eh_frame_sec.stream,
++            size=self.eh_frame_sec.size,
++            base_structs=self.structs)
++        return cfi.get_entries()
++
+     def location_lists(self):
+         """ Get a LocationLists object representing the .debug_loc section of
+             the DWARF data, or None if this section doesn't exist.
+@@ -175,18 +191,18 @@
+             # Compute the offset of the next CU in the section. The unit_length
+             # field of the CU header contains its size not including the length
+             # field itself.
+-            offset = (  offset + 
+-                        cu['unit_length'] + 
++            offset = (  offset +
++                        cu['unit_length'] +
+                         cu.structs.initial_length_field_size())
+             yield cu
+-        
++
+     def _parse_CU_at_offset(self, offset):
+         """ Parse and return a CU at the given offset in the debug_info stream.
+         """
+         # Section 7.4 (32-bit and 64-bit DWARF Formats) of the DWARF spec v3
+-        # states that the first 32-bit word of the CU header determines 
++        # states that the first 32-bit word of the CU header determines
+         # whether the CU is represented with 32-bit or 64-bit DWARF format.
+-        # 
++        #
+         # So we peek at the first word in the CU header to determine its
+         # dwarf format. Based on it, we then create a new DWARFStructs
+         # instance suitable for this CU and use it to parse the rest.
+@@ -205,15 +221,15 @@
+             little_endian=self.config.little_endian,
+             dwarf_format=dwarf_format,
+             address_size=4)
+-        
++
+         cu_header = struct_parse(
+             cu_structs.Dwarf_CU_header, self.debug_info_sec.stream, offset)
+         if cu_header['address_size'] == 8:
+             cu_structs = DWARFStructs(
+                 little_endian=self.config.little_endian,
+                 dwarf_format=dwarf_format,
+-                 address_size=8)
+-        
++                address_size=8)
++
+         cu_die_offset = self.debug_info_sec.stream.tell()
+         dwarf_assert(
+             self._is_supported_version(cu_header['version']),
+@@ -224,11 +240,11 @@
+                 structs=cu_structs,
+                 cu_offset=offset,
+                 cu_die_offset=cu_die_offset)
+-        
++
+     def _is_supported_version(self, version):
+         """ DWARF version supported by this parser
+         """
+-        return 2 <= version <= 3
++        return 2 <= version <= 4
+ 
+     def _parse_line_program_at_offset(self, debug_line_offset, structs):
+         """ Given an offset to the .debug_line section, parse the line program
+diff -r 249a5ca85159 elftools/dwarf/enums.py
+--- a/elftools/dwarf/enums.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/dwarf/enums.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -185,7 +185,9 @@
+     DW_AT_main_subprogram       = 0x6a,
+     DW_AT_data_bit_offset       = 0x6b,
+     DW_AT_const_expr            = 0x6c,
+-    
++    DW_AT_enum_class            = 0x6d,
++    DW_AT_linkage_name          = 0x6e,
++
+     DW_AT_MIPS_fde                      = 0x2001,
+     DW_AT_MIPS_loop_begin               = 0x2002,
+     DW_AT_MIPS_tail_loop_begin          = 0x2003,
+@@ -197,8 +199,46 @@
+     DW_AT_MIPS_abstract_name            = 0x2009,
+     DW_AT_MIPS_clone_origin             = 0x200a,
+     DW_AT_MIPS_has_inlines              = 0x200b,
++    DW_AT_MIPS_stride_byte              = 0x200c,
++    DW_AT_MIPS_stride_elem              = 0x200d,
++    DW_AT_MIPS_ptr_dopetype             = 0x200e,
++    DW_AT_MIPS_allocatable_dopetype     = 0x200f,
++    DW_AT_MIPS_assumed_shape_dopetype   = 0x2010,
++    DW_AT_MIPS_assumed_size             = 0x2011,
+ 
+-    _default_                   = Pass,
++    DW_AT_sf_names                      = 0x2101,
++    DW_AT_src_info                      = 0x2102,
++    DW_AT_mac_info                      = 0x2103,
++    DW_AT_src_coords                    = 0x2104,
++    DW_AT_body_begin                    = 0x2105,
++    DW_AT_body_end                      = 0x2106,
++    DW_AT_GNU_vector                    = 0x2107,
++    DW_AT_GNU_template_name             = 0x2110,
++
++    DW_AT_GNU_call_site_value               = 0x2111,
++    DW_AT_GNU_call_site_data_value          = 0x2112,
++    DW_AT_GNU_call_site_target              = 0x2113,
++    DW_AT_GNU_call_site_target_clobbered    = 0x2114,
++    DW_AT_GNU_tail_call                     = 0x2115,
++    DW_AT_GNU_all_tail_call_sites           = 0x2116,
++    DW_AT_GNU_all_call_sites                = 0x2117,
++    DW_AT_GNU_all_source_call_sites         = 0x2118,
++
++    DW_AT_APPLE_optimized               = 0x3fe1,
++    DW_AT_APPLE_flags                   = 0x3fe2,
++    DW_AT_APPLE_isa                     = 0x3fe3,
++    DW_AT_APPLE_block                   = 0x3fe4,
++    DW_AT_APPLE_major_runtime_vers      = 0x3fe5,
++    DW_AT_APPLE_runtime_class           = 0x3fe6,
++    DW_AT_APPLE_omit_frame_ptr          = 0x3fe7,
++    DW_AT_APPLE_property_name           = 0x3fe8,
++    DW_AT_APPLE_property_getter         = 0x3fe9,
++    DW_AT_APPLE_property_setter         = 0x3fea,
++    DW_AT_APPLE_property_attribute      = 0x3feb,
++    DW_AT_APPLE_objc_complete_type      = 0x3fec,
++    DW_AT_APPLE_property                = 0x3fed,
++
++    _default_ = Pass,
+ )
+ 
+ 
+@@ -225,6 +265,10 @@
+     DW_FORM_ref8            = 0x14,
+     DW_FORM_ref_udata       = 0x15,
+     DW_FORM_indirect        = 0x16,
++    DW_FORM_sec_offset      = 0x17,
++    DW_FORM_exprloc         = 0x18,
++    DW_FORM_flag_present    = 0x19,
++    DW_FORM_ref_sig8        = 0x20,
+ 
+     _default_               = Pass,
+ )
+diff -r 249a5ca85159 elftools/dwarf/lineprogram.py
+--- a/elftools/dwarf/lineprogram.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/dwarf/lineprogram.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -215,10 +215,10 @@
+                     add_entry_old_state(opcode, [operand])
+                 elif opcode == DW_LNS_negate_stmt:
+                     state.is_stmt = not state.is_stmt
+-                    add_entry_old_state(opcode, [operand])
++                    add_entry_old_state(opcode, [])
+                 elif opcode == DW_LNS_set_basic_block:
+                     state.basic_block = True
+-                    add_entry_old_state(opcode, [operand])
++                    add_entry_old_state(opcode, [])
+                 elif opcode == DW_LNS_const_add_pc:
+                     adjusted_opcode = 255 - self['opcode_base']
+                     address_addend = ((adjusted_opcode // self['line_range']) *
+diff -r 249a5ca85159 elftools/dwarf/structs.py
+--- a/elftools/dwarf/structs.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/dwarf/structs.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -11,7 +11,7 @@
+     UBInt8, UBInt16, UBInt32, UBInt64, ULInt8, ULInt16, ULInt32, ULInt64,
+     SBInt8, SBInt16, SBInt32, SBInt64, SLInt8, SLInt16, SLInt32, SLInt64,
+     Adapter, Struct, ConstructError, If, RepeatUntil, Field, Rename, Enum,
+-    Array, PrefixedArray, CString, Embed,
++    Array, PrefixedArray, CString, Embed, StaticField
+     )
+ from ..common.construct_utils import RepeatUntilExcluding
+ 
+@@ -19,39 +19,39 @@
+ 
+ 
+ class DWARFStructs(object):
+-    """ Exposes Construct structs suitable for parsing information from DWARF 
++    """ Exposes Construct structs suitable for parsing information from DWARF
+         sections. Each compile unit in DWARF info can have its own structs
+-        object. Keep in mind that these structs have to be given a name (by 
++        object. Keep in mind that these structs have to be given a name (by
+         calling them with a name) before being used for parsing (like other
+         Construct structs). Those that should be used without a name are marked
+         by (+).
+-    
++
+         Accessible attributes (mostly as described in chapter 7 of the DWARF
+         spec v3):
+-    
++
+             Dwarf_[u]int{8,16,32,64):
+                 Data chunks of the common sizes
+-            
++
+             Dwarf_offset:
+                 32-bit or 64-bit word, depending on dwarf_format
+-            
++
+             Dwarf_target_addr:
+                 32-bit or 64-bit word, depending on address size
+-            
++
+             Dwarf_initial_length:
+                 "Initial length field" encoding
+                 section 7.4
+-            
++
+             Dwarf_{u,s}leb128:
+                 ULEB128 and SLEB128 variable-length encoding
+-            
++
+             Dwarf_CU_header (+):
+                 Compilation unit header
+-        
++
+             Dwarf_abbrev_declaration (+):
+                 Abbreviation table declaration - doesn't include the initial
+                 code, only the contents.
+-            
++
+             Dwarf_dw_form (+):
+                 A dictionary mapping 'DW_FORM_*' keys into construct Structs
+                 that parse such forms. These Structs have already been given
+@@ -62,7 +62,7 @@
+ 
+             Dwarf_lineprog_file_entry (+):
+                 A single file entry in a line program header or instruction
+-        
++
+             Dwarf_CIE_header (+):
+                 A call-frame CIE
+ 
+@@ -71,22 +71,27 @@
+ 
+         See also the documentation of public methods.
+     """
+-    def __init__(self, little_endian, dwarf_format, address_size):
+-        """ little_endian:
++    def __init__(self,
++                 little_endian, dwarf_format, address_size, dwarf_version=2):
++        """ dwarf_version:
++                Numeric DWARF version
++
++            little_endian:
+                 True if the file is little endian, False if big
+-            
++
+             dwarf_format:
+                 DWARF Format: 32 or 64-bit (see spec section 7.4)
+-            
++
+             address_size:
+-                Target machine address size, in bytes (4 or 8). (See spec 
++                Target machine address size, in bytes (4 or 8). (See spec
+                 section 7.5.1)
+         """
+         assert dwarf_format == 32 or dwarf_format == 64
+         assert address_size == 8 or address_size == 4
+         self.little_endian = little_endian
+-        self.dwarf_format = dwarf_format  
++        self.dwarf_format = dwarf_format
+         self.address_size = address_size
++        self.dwarf_version = dwarf_version
+         self._create_structs()
+ 
+     def initial_length_field_size(self):
+@@ -131,7 +136,7 @@
+     def _create_initial_length(self):
+         def _InitialLength(name):
+             # Adapts a Struct that parses forward a full initial length field.
+-            # Only if the first word is the continuation value, the second 
++            # Only if the first word is the continuation value, the second
+             # word is parsed from the stream.
+             #
+             return _InitialLengthAdapter(
+@@ -152,13 +157,13 @@
+             self.Dwarf_uint16('version'),
+             self.Dwarf_offset('debug_abbrev_offset'),
+             self.Dwarf_uint8('address_size'))
+-    
++
+     def _create_abbrev_declaration(self):
+         self.Dwarf_abbrev_declaration = Struct('Dwarf_abbrev_entry',
+             Enum(self.Dwarf_uleb128('tag'), **ENUM_DW_TAG),
+             Enum(self.Dwarf_uint8('children_flag'), **ENUM_DW_CHILDREN),
+             RepeatUntilExcluding(
+-                lambda obj, ctx: 
++                lambda obj, ctx:
+                     obj.name == 'DW_AT_null' and obj.form == 'DW_FORM_null',
+                 Struct('attr_spec',
+                     Enum(self.Dwarf_uleb128('name'), **ENUM_DW_AT),
+@@ -167,12 +172,12 @@
+     def _create_dw_form(self):
+         self.Dwarf_dw_form = dict(
+             DW_FORM_addr=self.Dwarf_target_addr(''),
+-            
++
+             DW_FORM_block1=self._make_block_struct(self.Dwarf_uint8),
+             DW_FORM_block2=self._make_block_struct(self.Dwarf_uint16),
+             DW_FORM_block4=self._make_block_struct(self.Dwarf_uint32),
+             DW_FORM_block=self._make_block_struct(self.Dwarf_uleb128),
+-            
++
+             # All DW_FORM_data<n> forms are assumed to be unsigned
+             DW_FORM_data1=self.Dwarf_uint8(''),
+             DW_FORM_data2=self.Dwarf_uint16(''),
+@@ -180,19 +185,25 @@
+             DW_FORM_data8=self.Dwarf_uint64(''),
+             DW_FORM_sdata=self.Dwarf_sleb128(''),
+             DW_FORM_udata=self.Dwarf_uleb128(''),
+-            
++
+             DW_FORM_string=CString(''),
+             DW_FORM_strp=self.Dwarf_offset(''),
+             DW_FORM_flag=self.Dwarf_uint8(''),
+-            
++
+             DW_FORM_ref1=self.Dwarf_uint8(''),
+             DW_FORM_ref2=self.Dwarf_uint16(''),
+             DW_FORM_ref4=self.Dwarf_uint32(''),
+             DW_FORM_ref8=self.Dwarf_uint64(''),
+             DW_FORM_ref_udata=self.Dwarf_uleb128(''),
+             DW_FORM_ref_addr=self.Dwarf_offset(''),
+-            
++
+             DW_FORM_indirect=self.Dwarf_uleb128(''),
++
++            # New forms in DWARFv4
++            DW_FORM_flag_present = StaticField('', 0),
++            DW_FORM_sec_offset = self.Dwarf_offset(''),
++            DW_FORM_exprloc = self._make_block_struct(self.Dwarf_uleb128),
++            DW_FORM_ref_sig8 = self.Dwarf_offset(''),
+         )
+ 
+     def _create_lineprog_header(self):
+@@ -215,7 +226,7 @@
+             self.Dwarf_int8('line_base'),
+             self.Dwarf_uint8('line_range'),
+             self.Dwarf_uint8('opcode_base'),
+-            Array(lambda ctx: ctx['opcode_base'] - 1, 
++            Array(lambda ctx: ctx['opcode_base'] - 1,
+                   self.Dwarf_uint8('standard_opcode_lengths')),
+             RepeatUntilExcluding(
+                 lambda obj, ctx: obj == b'',
+@@ -226,14 +237,27 @@
+             )
+ 
+     def _create_callframe_entry_headers(self):
+-        self.Dwarf_CIE_header = Struct('Dwarf_CIE_header',
+-            self.Dwarf_initial_length('length'),
+-            self.Dwarf_offset('CIE_id'),
+-            self.Dwarf_uint8('version'),
+-            CString('augmentation'),
+-            self.Dwarf_uleb128('code_alignment_factor'),
+-            self.Dwarf_sleb128('data_alignment_factor'),
+-            self.Dwarf_uleb128('return_address_register'))
++        # The CIE header was modified in DWARFv4.
++        if self.dwarf_version == 4:
++            self.Dwarf_CIE_header = Struct('Dwarf_CIE_header',
++                self.Dwarf_initial_length('length'),
++                self.Dwarf_offset('CIE_id'),
++                self.Dwarf_uint8('version'),
++                CString('augmentation'),
++                self.Dwarf_uint8('address_size'),
++                self.Dwarf_uint8('segment_size'),
++                self.Dwarf_uleb128('code_alignment_factor'),
++                self.Dwarf_sleb128('data_alignment_factor'),
++                self.Dwarf_uleb128('return_address_register'))
++        else:
++            self.Dwarf_CIE_header = Struct('Dwarf_CIE_header',
++                self.Dwarf_initial_length('length'),
++                self.Dwarf_offset('CIE_id'),
++                self.Dwarf_uint8('version'),
++                CString('augmentation'),
++                self.Dwarf_uleb128('code_alignment_factor'),
++                self.Dwarf_sleb128('data_alignment_factor'),
++                self.Dwarf_uleb128('return_address_register'))
+ 
+         self.Dwarf_FDE_header = Struct('Dwarf_FDE_header',
+             self.Dwarf_initial_length('length'),
+@@ -242,7 +266,7 @@
+             self.Dwarf_target_addr('address_range'))
+ 
+     def _make_block_struct(self, length_field):
+-        """ Create a struct for DW_FORM_block<size> 
++        """ Create a struct for DW_FORM_block<size>
+         """
+         return PrefixedArray(
+                     subcon=self.Dwarf_uint8('elem'),
+diff -r 249a5ca85159 elftools/elf/constants.py
+--- a/elftools/elf/constants.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/elf/constants.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -45,3 +45,25 @@
+     PF_MASKOS=0x00FF0000
+     PF_MASKPROC=0xFF000000
+ 
++
++# symbol info flags for entries
++# in the .SUNW_syminfo section
++class SUNW_SYMINFO_FLAGS(object):
++    """ Flags for the si_flags field of entries
++        in the .SUNW_syminfo section
++    """
++    SYMINFO_FLG_DIRECT=0x1
++    SYMINFO_FLG_FILTER=0x2
++    SYMINFO_FLG_COPY=0x4
++    SYMINFO_FLG_LAZYLOAD=0x8
++    SYMINFO_FLG_DIRECTBIND=0x10
++    SYMINFO_FLG_NOEXTDIRECT=0x20
++    SYMINFO_FLG_AUXILIARY=0x40
++    SYMINFO_FLG_INTERPOSE=0x80
++    SYMINFO_FLG_CAP=0x100
++    SYMINFO_FLG_DEFERRED=0x200
++
++class VER_FLAGS(object):
++    VER_FLG_BASE=0x1
++    VER_FLG_WEAK=0x2
++    VER_FLG_INFO=0x4 
+diff -r 249a5ca85159 elftools/elf/descriptions.py
+--- a/elftools/elf/descriptions.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/elf/descriptions.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -9,7 +9,7 @@
+ from .enums import (
+     ENUM_D_TAG, ENUM_E_VERSION, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
+     )
+-from .constants import P_FLAGS, SH_FLAGS
++from .constants import P_FLAGS, SH_FLAGS, SUNW_SYMINFO_FLAGS, VER_FLAGS
+ from ..common.py3compat import iteritems
+ 
+ 
+@@ -84,6 +84,28 @@
+     return _DESCR_D_TAG.get(x, _unknown)
+ 
+ 
++def describe_syminfo_flags(x):
++    return ''.join(_DESCR_SYMINFO_FLAGS[flag] for flag in (
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_CAP,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECT,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_FILTER,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_AUXILIARY,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECTBIND,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_COPY,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_LAZYLOAD,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_NOEXTDIRECT,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_INTERPOSE,
++        SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DEFERRED) if x & flag)
++
++def describe_symbol_boundto(x):
++    return _DESCR_SYMINFO_BOUNDTO.get(x, '%3s' % x)
++
++def describe_ver_flags(x):
++    return ' | '.join(_DESCR_VER_FLAGS[flag] for flag in (
++        VER_FLAGS.VER_FLG_WEAK,
++        VER_FLAGS.VER_FLG_BASE,
++        VER_FLAGS.VER_FLG_INFO) if x & flag)
++
+ #-------------------------------------------------------------------------------
+ _unknown = '<unknown>'
+ 
+@@ -236,6 +258,33 @@
+     SHN_COMMON='COM',
+ )
+ 
++_DESCR_SYMINFO_FLAGS = {
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECT: 'D',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECTBIND: 'B',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_COPY: 'C',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_LAZYLOAD: 'L',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_NOEXTDIRECT: 'N',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_AUXILIARY: 'A',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_FILTER: 'F',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_INTERPOSE: 'I',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_CAP: 'S',
++    SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DEFERRED: 'P',
++}
++
++_DESCR_SYMINFO_BOUNDTO = dict(
++    SYMINFO_BT_SELF='<self>',
++    SYMINFO_BT_PARENT='<parent>',
++    SYMINFO_BT_NONE='',
++    SYMINFO_BT_EXTERN='<extern>',
++)
++
++_DESCR_VER_FLAGS = {
++    0: '',
++    VER_FLAGS.VER_FLG_BASE: 'BASE',
++    VER_FLAGS.VER_FLG_WEAK: 'WEAK',
++    VER_FLAGS.VER_FLG_INFO: 'INFO',
++}
++
+ _DESCR_RELOC_TYPE_i386 = dict(
+         (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_i386))
+ 
+diff -r 249a5ca85159 elftools/elf/dynamic.py
+--- a/elftools/elf/dynamic.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/elf/dynamic.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -25,7 +25,8 @@
+         value of DT_SONAME (fetched from the dynamic symbol table).
+     """
+     _HANDLED_TAGS = frozenset(
+-        ['DT_NEEDED', 'DT_RPATH', 'DT_RUNPATH', 'DT_SONAME'])
++        ['DT_NEEDED', 'DT_RPATH', 'DT_RUNPATH', 'DT_SONAME',
++         'DT_SUNW_FILTER'])
+ 
+     def __init__(self, entry, elffile):
+         self.entry = entry
+diff -r 249a5ca85159 elftools/elf/elffile.py
+--- a/elftools/elf/elffile.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/elf/elffile.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -12,9 +12,13 @@
+ from ..construct import ConstructError
+ from .structs import ELFStructs
+ from .sections import (
+-        Section, StringTableSection, SymbolTableSection, NullSection)
++        Section, StringTableSection, SymbolTableSection,
++        SUNWSyminfoTableSection, NullSection)
+ from .dynamic import DynamicSection, DynamicSegment
+ from .relocation import RelocationSection, RelocationHandler
++from .gnuversions import (
++        GNUVerNeedSection, GNUVerDefSection,
++        GNUVerSymSection)
+ from .segments import Segment, InterpSegment
+ from .enums import ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
+ from ..dwarf.dwarfinfo import DWARFInfo, DebugSectionDescriptor, DwarfConfig
+@@ -125,15 +129,15 @@
+         #
+         debug_sections = {}
+         for secname in (b'.debug_info', b'.debug_abbrev', b'.debug_str',
+-                        b'.debug_line', b'.debug_frame', b'.debug_loc',
+-                        b'.debug_ranges'):
++                        b'.debug_line', b'.debug_frame',
++                        b'.debug_loc', b'.debug_ranges'):
+             section = self.get_section_by_name(secname)
+             if section is None:
+                 debug_sections[secname] = None
+             else:
+                 debug_sections[secname] = self._read_dwarf_section(
+-                        section,
+-                        relocate_dwarf_sections)
++                    section,
++                    relocate_dwarf_sections)
+ 
+         return DWARFInfo(
+                 config=DwarfConfig(
+@@ -143,6 +147,8 @@
+                 debug_info_sec=debug_sections[b'.debug_info'],
+                 debug_abbrev_sec=debug_sections[b'.debug_abbrev'],
+                 debug_frame_sec=debug_sections[b'.debug_frame'],
++                # TODO(eliben): reading of eh_frame is not hooked up yet
++                eh_frame_sec=None,
+                 debug_str_sec=debug_sections[b'.debug_str'],
+                 debug_loc_sec=debug_sections[b'.debug_loc'],
+                 debug_ranges_sec=debug_sections[b'.debug_ranges'],
+@@ -243,6 +249,14 @@
+             return NullSection(section_header, name, self.stream)
+         elif sectype in ('SHT_SYMTAB', 'SHT_DYNSYM'):
+             return self._make_symbol_table_section(section_header, name)
++        elif sectype == 'SHT_SUNW_syminfo':
++            return self._make_sunwsyminfo_table_section(section_header, name)
++        elif sectype == 'SHT_GNU_verneed':
++            return self._make_gnu_verneed_section(section_header, name)
++        elif sectype == 'SHT_GNU_verdef':
++            return self._make_gnu_verdef_section(section_header, name)
++        elif sectype == 'SHT_GNU_versym':
++            return self._make_gnu_versym_section(section_header, name)
+         elif sectype in ('SHT_REL', 'SHT_RELA'):
+             return RelocationSection(
+                 section_header, name, self.stream, self)
+@@ -261,6 +275,46 @@
+             elffile=self,
+             stringtable=strtab_section)
+ 
++    def _make_sunwsyminfo_table_section(self, section_header, name):
++        """ Create a SUNWSyminfoTableSection
++        """
++        linked_strtab_index = section_header['sh_link']
++        strtab_section = self.get_section(linked_strtab_index)
++        return SUNWSyminfoTableSection(
++            section_header, name, self.stream,
++            elffile=self,
++            symboltable=strtab_section)
++
++    def _make_gnu_verneed_section(self, section_header, name):
++        """ Create a GNUVerNeedSection
++        """
++        linked_strtab_index = section_header['sh_link']
++        strtab_section = self.get_section(linked_strtab_index)
++        return GNUVerNeedSection(
++            section_header, name, self.stream,
++            elffile=self,
++            stringtable=strtab_section)
++
++    def _make_gnu_verdef_section(self, section_header, name):
++        """ Create a GNUVerDefSection
++        """
++        linked_strtab_index = section_header['sh_link']
++        strtab_section = self.get_section(linked_strtab_index)
++        return GNUVerDefSection(
++            section_header, name, self.stream,
++            elffile=self,
++            stringtable=strtab_section)
++
++    def _make_gnu_versym_section(self, section_header, name):
++        """ Create a GNUVerSymSection
++        """
++        linked_strtab_index = section_header['sh_link']
++        strtab_section = self.get_section(linked_strtab_index)
++        return GNUVerSymSection(
++            section_header, name, self.stream,
++            elffile=self,
++            symboltable=strtab_section)
++
+     def _get_segment_header(self, n):
+         """ Find the header of segment #n, parse it and return the struct
+         """
+diff -r 249a5ca85159 elftools/elf/enums.py
+--- a/elftools/elf/enums.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/elf/enums.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -184,14 +184,15 @@
+     SHT_NUM=19,
+     SHT_LOOS=0x60000000,
+     SHT_GNU_HASH=0x6ffffff6,
+-    SHT_GNU_verdef=0x6ffffffd,
+-    SHT_GNU_verneed=0x6ffffffe,
+-    SHT_GNU_versym=0x6fffffff,
++    SHT_GNU_verdef=0x6ffffffd,  # also SHT_SUNW_verdef
++    SHT_GNU_verneed=0x6ffffffe, # also SHT_SUNW_verneed
++    SHT_GNU_versym=0x6fffffff,  # also SHT_SUNW_versym
+     SHT_LOPROC=0x70000000,
+     SHT_HIPROC=0x7fffffff,
+     SHT_LOUSER=0x80000000,
+     SHT_HIUSER=0xffffffff,
+     SHT_AMD64_UNWIND=0x70000001,
++    SHT_SUNW_syminfo=0x6ffffffc,
+     _default_=Pass,
+ )
+ 
+@@ -301,6 +302,24 @@
+     DT_PREINIT_ARRAYSZ=33,
+     DT_NUM=34,
+     DT_LOOS=0x6000000d,
++    DT_SUNW_AUXILIARY=0x6000000d,
++    DT_SUNW_RTLDINF=0x6000000e,
++    DT_SUNW_FILTER=0x6000000f,
++    DT_SUNW_CAP=0x60000010,
++    DT_SUNW_SYMTAB=0x60000011,
++    DT_SUNW_SYMSZ=0x60000012,
++    DT_SUNW_ENCODING=0x60000013,
++    DT_SUNW_SORTENT=0x60000013,
++    DT_SUNW_SYMSORT=0x60000014,
++    DT_SUNW_SYMSORTSZ=0x60000015,
++    DT_SUNW_TLSSORT=0x60000016,
++    DT_SUNW_TLSSORTSZ=0x60000017,
++    DT_SUNW_CAPINFO=0x60000018,
++    DT_SUNW_STRPAD=0x60000019,
++    DT_SUNW_CAPCHAIN=0x6000001a,
++    DT_SUNW_LDMACH=0x6000001b,
++    DT_SUNW_CAPCHAINENT=0x6000001d,
++    DT_SUNW_CAPCHAINSZ=0x6000001f,
+     DT_HIOS=0x6ffff000,
+     DT_LOPROC=0x70000000,
+     DT_HIPROC=0x7fffffff,
+@@ -428,3 +447,29 @@
+     _default_=Pass,
+ )
+ 
++# Sunw Syminfo Bound To special values
++ENUM_SUNW_SYMINFO_BOUNDTO = dict(
++    SYMINFO_BT_SELF=0xffff,
++    SYMINFO_BT_PARENT=0xfffe,
++    SYMINFO_BT_NONE=0xfffd,
++    SYMINFO_BT_EXTERN=0xfffc,
++    _default_=Pass,
++)
++
++# Versym section, version dependency index 
++ENUM_VERSYM = dict(
++    VER_NDX_LOCAL=0,
++    VER_NDX_GLOBAL=1,
++    VER_NDX_LORESERVE=0xff00,
++    VER_NDX_ELIMINATE=0xff01,
++    _default_=Pass,
++)
++# Sunw Syminfo Bound To special values
++ENUM_SUNW_SYMINFO_BOUNDTO = dict(
++    SYMINFO_BT_SELF=0xffff,
++    SYMINFO_BT_PARENT=0xfffe,
++    SYMINFO_BT_NONE=0xfffd,
++    SYMINFO_BT_EXTERN=0xfffc,
++    _default_=Pass,
++)
++
+diff -r 249a5ca85159 elftools/elf/gnuversions.py
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/elftools/elf/gnuversions.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -0,0 +1,228 @@
++#------------------------------------------------------------------------------
++# elftools: elf/gnuversions.py
++#
++# ELF sections
++#
++# Yann Rouillard (yann at pleiades.fr.eu.org)
++# This code is in the public domain
++#------------------------------------------------------------------------------
++from ..construct import CString
++from ..common.utils import struct_parse, elf_assert
++from .sections import Section, Symbol
++
++
++class Version(object):
++    """ Version object - representing a version definition or dependency
++        entry from a "Version Needed" or a "Version Dependency" table section.
++
++        This kind of entry contains a pointer to an array of auxiliary entries
++        that store the information about version names or dependencies.
++        These entries are not stored in this object and should be accessed
++        through the appropriate method of a section object which will return
++        an iterator of VersionAuxiliary objects.
++
++        Similarly to Section objects, allows dictionary-like access to
++        verdef/verneed entry
++    """
++    def __init__(self, entry, name=None):
++        self.entry = entry
++        self.name = name
++
++    def __getitem__(self, name):
++        """ Implement dict-like access to entry
++        """
++        return self.entry[name]
++
++
++class VersionAuxiliary(object):
++    """ Version Auxiliary object - representing an auxiliary entry of a version
++        definition or dependency entry
++
++        Similarly to Section objects, allows dictionary-like access to the
++        verdaux/vernaux entry
++    """
++    def __init__(self, entry, name):
++        self.entry = entry
++        self.name = name
++
++    def __getitem__(self, name):
++        """ Implement dict-like access to entries
++        """
++        return self.entry[name]
++
++
++class GNUVersionSection(Section):
++    """ Common ancestor class for ELF SUNW|GNU Version Needed/Dependency
++        sections class which contains shareable code
++    """
++
++    def __init__(self, header, name, stream, elffile, stringtable,
++                 field_prefix, version_struct, version_auxiliaries_struct):
++        super(GNUVersionSection, self).__init__(header, name, stream)
++        self.elffile = elffile
++        self.stringtable = stringtable
++        self.field_prefix = field_prefix
++        self.version_struct = version_struct
++        self.version_auxiliaries_struct = version_auxiliaries_struct
++
++    def num_versions(self):
++        """ Number of version entries in the section
++        """
++        return self['sh_info']
++
++    def _field_name(self, name, auxiliary=False):
++        """ Return the real field's name of version or a version auxiliary
++            entry
++        """
++        middle = 'a_' if auxiliary else '_'
++        return self.field_prefix + middle + name
++
++    def _iter_version_auxiliaries(self, entry_offset, count):
++        """ Yield all auxiliary entries of a version entry
++        """
++        name_field = self._field_name('name', auxiliary=True)
++        next_field = self._field_name('next', auxiliary=True)
++
++        for _ in range(count):
++            entry = struct_parse(
++                        self.version_auxiliaries_struct,
++                        self.stream,
++                        stream_pos=entry_offset)
++
++            name = self.stringtable.get_string(entry[name_field])
++            version_aux = VersionAuxiliary(entry, name)
++            yield version_aux
++
++            entry_offset += entry[next_field]
++
++    def iter_versions(self):
++        """ Yield all the version entries in the section
++            Each time it returns the main version structure
++            and an iterator to walk through its auxiliaries entries
++        """
++        aux_field = self._field_name('aux')
++        count_field = self._field_name('cnt')
++        next_field = self._field_name('next')
++
++        entry_offset = self['sh_offset']
++        for _ in range(self.num_versions()):
++            entry = struct_parse(
++                self.version_struct,
++                self.stream,
++                stream_pos=entry_offset)
++
++            elf_assert(entry[count_field] > 0,
++                'Expected number of version auxiliary entries (%s) to be > 0'
++                'for the following version entry: %s' % (
++                    count_field, str(entry)))
++
++            version = Version(entry)
++            aux_entries_offset = entry_offset + entry[aux_field]
++            version_auxiliaries_iter = self._iter_version_auxiliaries(
++                    aux_entries_offset, entry[count_field])
++
++            yield version, version_auxiliaries_iter
++
++            entry_offset += entry[next_field]
++
++
++class GNUVerNeedSection(GNUVersionSection):
++    """ ELF SUNW or GNU Version Needed table section.
++        Has an associated StringTableSection that's passed in the constructor.
++    """
++    def __init__(self, header, name, stream, elffile, stringtable):
++        super(GNUVerNeedSection, self).__init__(
++                header, name, stream, elffile, stringtable, 'vn',
++                elffile.structs.Elf_Verneed, elffile.structs.Elf_Vernaux)
++        self._has_indexes = None
++
++    def has_indexes(self):
++        """ Return True if at least one version definition entry has an index
++            that is stored in the vna_other field.
++            This information is used for symbol versioning
++        """
++        if self._has_indexes is None:
++            self._has_indexes = False
++            for _, vernaux_iter in self.iter_versions():
++                for vernaux in vernaux_iter:
++                    if vernaux['vna_other']:
++                        self._has_indexes = True
++                        break
++
++        return self._has_indexes
++
++    def iter_versions(self):
++        for verneed, vernaux in super(GNUVerNeedSection, self).iter_versions():
++            verneed.name = self.stringtable.get_string(verneed['vn_file'])
++            yield verneed, vernaux
++
++    def get_version(self, index):
++        """ Get the version information located at index #n in the table
++            Return boths the verneed structure and the vernaux structure
++            that contains the name of the version
++        """
++        for verneed, vernaux_iter in self.iter_versions():
++            for vernaux in vernaux_iter:
++                if vernaux['vna_other'] == index:
++                    return verneed, vernaux
++
++        return None
++
++
++class GNUVerDefSection(GNUVersionSection):
++    """ ELF SUNW or GNU Version Definition table section.
++        Has an associated StringTableSection that's passed in the constructor.
++    """
++    def __init__(self, header, name, stream, elffile, stringtable):
++        super(GNUVerDefSection, self).__init__(
++                header, name, stream, elffile, stringtable, 'vd',
++                elffile.structs.Elf_Verdef, elffile.structs.Elf_Verdaux)
++
++    def get_version(self, index):
++        """ Get the version information located at index #n in the table
++            Return boths the verdef structure and an iterator to retrieve
++            both the version names and dependencies in the form of
++            verdaux entries
++        """
++        for verdef, verdaux_iter in self.iter_versions():
++            if verdef['vd_ndx'] == index:
++                return verdef, verdaux_iter
++
++        return None
++
++
++class GNUVerSymSection(Section):
++    """ ELF SUNW or GNU Versym table section.
++        Has an associated SymbolTableSection that's passed in the constructor.
++    """
++    def __init__(self, header, name, stream, elffile, symboltable):
++        super(GNUVerSymSection, self).__init__(header, name, stream)
++        self.elffile = elffile
++        self.elfstructs = self.elffile.structs
++        self.symboltable = symboltable
++
++    def num_symbols(self):
++        """ Number of symbols in the table
++        """
++        return self['sh_size'] // self['sh_entsize']
++
++    def get_symbol(self, n):
++        """ Get the symbol at index #n from the table (Symbol object)
++            It begins at 1 and not 0 since the first entry is used to
++            store the current version of the syminfo table
++        """
++        # Grab the symbol's entry from the stream
++        entry_offset = self['sh_offset'] + n * self['sh_entsize']
++        entry = struct_parse(
++            self.elfstructs.Elf_Versym,
++            self.stream,
++            stream_pos=entry_offset)
++        # Find the symbol name in the associated symbol table
++        name = self.symboltable.get_symbol(n).name
++        return Symbol(entry, name)
++
++    def iter_symbols(self):
++        """ Yield all the symbols in the table
++        """
++        for i in range(self.num_symbols()):
++            yield self.get_symbol(i)
+diff -r 249a5ca85159 elftools/elf/relocation.py
+--- a/elftools/elf/relocation.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/elf/relocation.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -202,6 +202,9 @@
+     def _reloc_calc_sym_plus_addend(value, sym_value, offset, addend=0):
+         return sym_value + addend
+ 
++    def _reloc_calc_sym_plus_addend_pcrel(value, sym_value, offset, addend=0):
++        return sym_value + addend - offset
++
+     _RELOCATION_RECIPES_X86 = {
+         ENUM_RELOC_TYPE_i386['R_386_NONE']: _RELOCATION_RECIPE_TYPE(
+             bytesize=4, has_addend=False, calc_func=_reloc_calc_identity),
+@@ -218,6 +221,9 @@
+             bytesize=8, has_addend=True, calc_func=_reloc_calc_identity),
+         ENUM_RELOC_TYPE_x64['R_X86_64_64']: _RELOCATION_RECIPE_TYPE(
+             bytesize=8, has_addend=True, calc_func=_reloc_calc_sym_plus_addend),
++        ENUM_RELOC_TYPE_x64['R_X86_64_PC32']: _RELOCATION_RECIPE_TYPE(
++            bytesize=8, has_addend=True,
++            calc_func=_reloc_calc_sym_plus_addend_pcrel),
+         ENUM_RELOC_TYPE_x64['R_X86_64_32']: _RELOCATION_RECIPE_TYPE(
+             bytesize=4, has_addend=True, calc_func=_reloc_calc_sym_plus_addend),
+         ENUM_RELOC_TYPE_x64['R_X86_64_32S']: _RELOCATION_RECIPE_TYPE(
+diff -r 249a5ca85159 elftools/elf/sections.py
+--- a/elftools/elf/sections.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/elf/sections.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -13,7 +13,7 @@
+ class Section(object):
+     """ Base class for ELF sections. Also used for all sections types that have
+         no special functionality.
+-        
++
+         Allows dictionary-like access to the section header. For example:
+          > sec = Section(...)
+          > sec['sh_type']  # section type
+@@ -22,7 +22,7 @@
+         self.header = header
+         self.name = name
+         self.stream = stream
+-    
++
+     def data(self):
+         """ The section data from the file.
+         """
+@@ -33,7 +33,7 @@
+         """ Is this a null section?
+         """
+         return False
+-        
++
+     def __getitem__(self, name):
+         """ Implement dict-like access to header entries
+         """
+@@ -51,14 +51,14 @@
+ 
+     def is_null(self):
+         return True
+-        
++
+ 
+ class StringTableSection(Section):
+     """ ELF string table section.
+     """
+     def __init__(self, header, name, stream):
+         super(StringTableSection, self).__init__(header, name, stream)
+-        
++
+     def get_string(self, offset):
+         """ Get the string stored at the given offset in this string table.
+         """
+@@ -85,7 +85,7 @@
+         """ Number of symbols in the table
+         """
+         return self['sh_size'] // self['sh_entsize']
+-        
++
+     def get_symbol(self, n):
+         """ Get the symbol at index #n from the table (Symbol object)
+         """
+@@ -123,3 +123,38 @@
+         return self.entry[name]
+ 
+ 
++class SUNWSyminfoTableSection(Section):
++    """ ELF .SUNW Syminfo table section.
++        Has an associated SymbolTableSection that's passed in the constructor.
++    """
++    def __init__(self, header, name, stream, elffile, symboltable):
++        super(SUNWSyminfoTableSection, self).__init__(header, name, stream)
++        self.elffile = elffile
++        self.elfstructs = self.elffile.structs
++        self.symboltable = symboltable
++
++    def num_symbols(self):
++        """ Number of symbols in the table
++        """
++        return self['sh_size'] // self['sh_entsize'] - 1
++
++    def get_symbol(self, n):
++        """ Get the symbol at index #n from the table (Symbol object).
++            It begins at 1 and not 0 since the first entry is used to
++            store the current version of the syminfo table.
++        """
++        # Grab the symbol's entry from the stream
++        entry_offset = self['sh_offset'] + n * self['sh_entsize']
++        entry = struct_parse(
++            self.elfstructs.Elf_Sunw_Syminfo,
++            self.stream,
++            stream_pos=entry_offset)
++        # Find the symbol name in the associated symbol table
++        name = self.symboltable.get_symbol(n).name
++        return Symbol(entry, name)
++
++    def iter_symbols(self):
++        """ Yield all the symbols in the table
++        """
++        for i in range(1, self.num_symbols() + 1):
++            yield self.get_symbol(i)
+diff -r 249a5ca85159 elftools/elf/structs.py
+--- a/elftools/elf/structs.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/elftools/elf/structs.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -19,20 +19,20 @@
+ 
+ class ELFStructs(object):
+     """ Accessible attributes:
+-    
++
+             Elf_{byte|half|word|word64|addr|offset|sword|xword|xsword}:
+-                Data chunks, as specified by the ELF standard, adjusted for 
++                Data chunks, as specified by the ELF standard, adjusted for
+                 correct endianness and word-size.
+ 
+             Elf_Ehdr:
+                 ELF file header
+-            
++
+             Elf_Phdr:
+                 Program header
+-            
++
+             Elf_Shdr:
+                 Section header
+-            
++
+             Elf_Sym:
+                 Symbol table entry
+ 
+@@ -42,9 +42,9 @@
+     def __init__(self, little_endian=True, elfclass=32):
+         assert elfclass == 32 or elfclass == 64
+         self.little_endian = little_endian
+-        self.elfclass = elfclass        
++        self.elfclass = elfclass
+         self._create_structs()
+-    
++
+     def _create_structs(self):
+         if self.little_endian:
+             self.Elf_byte = ULInt8
+@@ -66,14 +66,18 @@
+             self.Elf_sword = SBInt32
+             self.Elf_xword = UBInt32 if self.elfclass == 32 else UBInt64
+             self.Elf_sxword = SBInt32 if self.elfclass == 32 else SBInt64
+-        
++
+         self._create_ehdr()
+         self._create_phdr()
+         self._create_shdr()
+         self._create_sym()
+         self._create_rel()
+         self._create_dyn()
+-    
++        self._create_sunw_syminfo()
++        self._create_gnu_verneed()
++        self._create_gnu_verdef()
++        self._create_gnu_versym()
++
+     def _create_ehdr(self):
+         self.Elf_Ehdr = Struct('Elf_Ehdr',
+             Struct('e_ident',
+@@ -99,7 +103,7 @@
+             self.Elf_half('e_shnum'),
+             self.Elf_half('e_shstrndx'),
+         )
+-    
++
+     def _create_phdr(self):
+         if self.elfclass == 32:
+             self.Elf_Phdr = Struct('Elf_Phdr',
+@@ -122,8 +126,8 @@
+                 self.Elf_xword('p_filesz'),
+                 self.Elf_xword('p_memsz'),
+                 self.Elf_xword('p_align'),
+-            )   
+-        
++            )
++
+     def _create_shdr(self):
+         self.Elf_Shdr = Struct('Elf_Shdr',
+             self.Elf_word('sh_name'),
+@@ -137,7 +141,7 @@
+             self.Elf_xword('sh_addralign'),
+             self.Elf_xword('sh_entsize'),
+         )
+-    
++
+     def _create_rel(self):
+         # r_info is also taken apart into r_info_sym and r_info_type.
+         # This is done in Value to avoid endianity issues while parsing.
+@@ -203,5 +207,50 @@
+                 self.Elf_xword('st_size'),
+             )
+ 
++    def _create_sunw_syminfo(self):
++        self.Elf_Sunw_Syminfo = Struct('Elf_Sunw_Syminfo',
++            Enum(self.Elf_half('si_boundto'), **ENUM_SUNW_SYMINFO_BOUNDTO),
++            self.Elf_half('si_flags'),
++        )
+ 
++    def _create_gnu_verneed(self):
++        # Structure of "version needed" entries is documented in
++        # Oracle "Linker and Libraries Guide", Chapter 7 Object File Format
++        self.Elf_Verneed = Struct('Elf_Verneed',
++            self.Elf_half('vn_version'),
++            self.Elf_half('vn_cnt'),
++            self.Elf_word('vn_file'),
++            self.Elf_word('vn_aux'),
++            self.Elf_word('vn_next'),
++        )
++        self.Elf_Vernaux = Struct('Elf_Vernaux',
++            self.Elf_word('vna_hash'),
++            self.Elf_half('vna_flags'),
++            self.Elf_half('vna_other'),
++            self.Elf_word('vna_name'),
++            self.Elf_word('vna_next'),
++        )
+ 
++    def _create_gnu_verdef(self):
++        # Structure off "version definition" entries are documented in
++        # Oracle "Linker and Libraries Guide", Chapter 7 Object File Format
++        self.Elf_Verdef = Struct('Elf_Verdef',
++            self.Elf_half('vd_version'),
++            self.Elf_half('vd_flags'),
++            self.Elf_half('vd_ndx'),
++            self.Elf_half('vd_cnt'),
++            self.Elf_word('vd_hash'),
++            self.Elf_word('vd_aux'),
++            self.Elf_word('vd_next'),
++        )
++        self.Elf_Verdaux = Struct('Elf_Verdaux',
++            self.Elf_word('vda_name'),
++            self.Elf_word('vda_next'),
++        )
++
++    def _create_gnu_versym(self):
++        # Structure off "version symbol" entries are documented in
++        # Oracle "Linker and Libraries Guide", Chapter 7 Object File Format
++        self.Elf_Versym = Struct('Elf_Versym',
++            Enum(self.Elf_half('ndx'), **ENUM_VERSYM),
++        )
+diff -r 249a5ca85159 scripts/readelf.py
+--- a/scripts/readelf.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/scripts/readelf.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -25,6 +25,10 @@
+ from elftools.elf.enums import ENUM_D_TAG
+ from elftools.elf.segments import InterpSegment
+ from elftools.elf.sections import SymbolTableSection
++from elftools.elf.gnuversions import (
++    GNUVerSymSection, GNUVerDefSection,
++    GNUVerNeedSection,
++    )
+ from elftools.elf.relocation import RelocationSection
+ from elftools.elf.descriptions import (
+     describe_ei_class, describe_ei_data, describe_ei_version,
+@@ -33,6 +37,7 @@
+     describe_sh_type, describe_sh_flags,
+     describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
+     describe_symbol_shndx, describe_reloc_type, describe_dyn_tag,
++    describe_ver_flags,
+     )
+ from elftools.dwarf.dwarfinfo import DWARFInfo
+ from elftools.dwarf.descriptions import (
+@@ -61,6 +66,8 @@
+         # Lazily initialized if a debug dump is requested
+         self._dwarfinfo = None
+ 
++        self._versioninfo = None
++
+     def display_file_header(self):
+         """ Display the ELF file header
+         """
+@@ -254,6 +261,8 @@
+     def display_symbol_tables(self):
+         """ Display the symbol tables contained in the file
+         """
++        self._init_versioninfo()
++
+         for section in self.elffile.iter_sections():
+             if not isinstance(section, SymbolTableSection):
+                 continue
+@@ -272,16 +281,37 @@
+                 self._emitline('   Num:    Value          Size Type    Bind   Vis      Ndx Name')
+ 
+             for nsym, symbol in enumerate(section.iter_symbols()):
++
++                version_info = ''
++                # readelf doesn't display version info for Solaris versioning
++                if (section['sh_type'] == 'SHT_DYNSYM' and
++                        self._versioninfo['type'] == 'GNU'):
++                    version = self._symbol_version(nsym)
++                    if (version['name'] != bytes2str(symbol.name) and
++                        version['index'] not in ('VER_NDX_LOCAL',
++                                                 'VER_NDX_GLOBAL')):
++                        if version['filename']:
++                            # external symbol
++                            version_info = '@%(name)s (%(index)i)' % version
++                        else:
++                            # internal symbol
++                            if version['hidden']:
++                                version_info = '@%(name)s' % version
++                            else:
++                                version_info = '@@%(name)s' % version
++
+                 # symbol names are truncated to 25 chars, similarly to readelf
+-                self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s' % (
++                self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s%s' % (
+                     nsym,
+-                    self._format_hex(symbol['st_value'], fullhex=True, lead0x=False),
++                    self._format_hex(
++                        symbol['st_value'], fullhex=True, lead0x=False),
+                     symbol['st_size'],
+                     describe_symbol_type(symbol['st_info']['type']),
+                     describe_symbol_bind(symbol['st_info']['bind']),
+                     describe_symbol_visibility(symbol['st_other']['visibility']),
+                     describe_symbol_shndx(symbol['st_shndx']),
+-                    bytes2str(symbol.name)))
++                    bytes2str(symbol.name),
++                    version_info))
+ 
+     def display_dynamic_tags(self):
+         """ Display the dynamic tags contained in the file
+@@ -384,6 +414,111 @@
+         if not has_relocation_sections:
+             self._emitline('\nThere are no relocations in this file.')
+ 
++    def display_version_info(self):
++        """ Display the version info contained in the file
++        """
++        self._init_versioninfo()
++
++        if not self._versioninfo['type']:
++            self._emitline("\nNo version information found in this file.")
++            return
++
++        for section in self.elffile.iter_sections():
++            if isinstance(section, GNUVerSymSection):
++                self._print_version_section_header(
++                    section, 'Version symbols', lead0x=False)
++
++                num_symbols = section.num_symbols()
++    
++                # Symbol version info are printed four by four entries 
++                for idx_by_4 in range(0, num_symbols, 4):
++
++                    self._emit('  %03x:' % idx_by_4)
++
++                    for idx in range(idx_by_4, min(idx_by_4 + 4, num_symbols)):
++
++                        symbol_version = self._symbol_version(idx)
++                        if symbol_version['index'] == 'VER_NDX_LOCAL':
++                            version_index = 0
++                            version_name = '(*local*)'
++                        elif symbol_version['index'] == 'VER_NDX_GLOBAL':
++                            version_index = 1
++                            version_name = '(*global*)'
++                        else:
++                            version_index = symbol_version['index']
++                            version_name = '(%(name)s)' % symbol_version
++
++                        visibility = 'h' if symbol_version['hidden'] else ' '
++
++                        self._emit('%4x%s%-13s' % (
++                            version_index, visibility, version_name))
++
++                    self._emitline()
++
++            elif isinstance(section, GNUVerDefSection):
++                self._print_version_section_header(
++                    section, 'Version definition', indent=2)
++
++                offset = 0
++                for verdef, verdaux_iter in section.iter_versions():
++                    verdaux = next(verdaux_iter)
++
++                    name = verdaux.name
++                    if verdef['vd_flags']:
++                        flags = describe_ver_flags(verdef['vd_flags'])
++                        # Mimic exactly the readelf output
++                        flags += ' '
++                    else:
++                        flags = 'none'
++
++                    self._emitline('  %s: Rev: %i  Flags: %s  Index: %i'
++                                   '  Cnt: %i  Name: %s' % (
++                            self._format_hex(offset, fieldsize=6,
++                                             alternate=True),
++                            verdef['vd_version'], flags, verdef['vd_ndx'],
++                            verdef['vd_cnt'], bytes2str(name)))
++
++                    verdaux_offset = (
++                            offset + verdef['vd_aux'] + verdaux['vda_next'])
++                    for idx, verdaux in enumerate(verdaux_iter, start=1):
++                        self._emitline('  %s: Parent %i: %s' %
++                            (self._format_hex(verdaux_offset, fieldsize=4),
++                                              idx, bytes2str(verdaux.name)))
++                        verdaux_offset += verdaux['vda_next']
++
++                    offset += verdef['vd_next']
++
++            elif isinstance(section, GNUVerNeedSection):
++                self._print_version_section_header(section, 'Version needs')
++
++                offset = 0
++                for verneed, verneed_iter in section.iter_versions():
++
++                    self._emitline('  %s: Version: %i  File: %s  Cnt: %i' % (
++                            self._format_hex(offset, fieldsize=6,
++                                             alternate=True),
++                            verneed['vn_version'], bytes2str(verneed.name),
++                            verneed['vn_cnt']))
++
++                    vernaux_offset = offset + verneed['vn_aux']
++                    for idx, vernaux in enumerate(verneed_iter, start=1):
++                        if vernaux['vna_flags']:
++                            flags = describe_ver_flags(vernaux['vna_flags'])
++                            # Mimic exactly the readelf output
++                            flags += ' '
++                        else:
++                            flags = 'none'
++
++                        self._emitline(
++                            '  %s:   Name: %s  Flags: %s  Version: %i' % (
++                                self._format_hex(vernaux_offset, fieldsize=4),
++                                bytes2str(vernaux.name), flags,
++                                vernaux['vna_other']))
++
++                        vernaux_offset += vernaux['vna_next']
++
++                    offset += verneed['vn_next']
++
+     def display_hex_dump(self, section_spec):
+         """ Display a hex dump of a section. section_spec is either a section
+             number or a name.
+@@ -486,7 +621,8 @@
+         else:
+             self._emitline('debug dump not yet supported for "%s"' % dump_what)
+ 
+-    def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True):
++    def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True,
++                    alternate=False):
+         """ Format an address into a hexadecimal string.
+ 
+             fieldsize:
+@@ -501,7 +637,20 @@
+ 
+             lead0x:
+                 If True, leading 0x is added
++
++            alternate:
++                If True, override lead0x to emulate the alternate
++                hexadecimal form specified in format string with the #
++                character: only non-zero values are prefixed with 0x.
++                This form is used by readelf.
+         """
++        if alternate:
++            if addr == 0:
++                lead0x = False
++            else:
++                lead0x = True
++                fieldsize -= 2
++
+         s = '0x' if lead0x else ''
+         if fullhex:
+             fieldsize = 8 if self.elffile.elfclass == 32 else 16
+@@ -511,6 +660,97 @@
+             field = '%' + '0%sx' % fieldsize
+         return s + field % addr
+ 
++    def _print_version_section_header(self, version_section, name, lead0x=True,
++                                      indent=1):
++        """ Print a section header of one version related section (versym,
++            verneed or verdef) with some options to accomodate readelf
++            little differences between each header (e.g. indentation
++            and 0x prefixing).
++        """
++        if hasattr(version_section, 'num_versions'):
++            num_entries = version_section.num_versions()
++        else:
++            num_entries = version_section.num_symbols()
++
++        self._emitline("\n%s section '%s' contains %s entries:" %
++            (name, bytes2str(version_section.name), num_entries))
++        self._emitline('%sAddr: %s  Offset: %s  Link: %i (%s)' % (
++            ' ' * indent,
++            self._format_hex(
++                version_section['sh_addr'], fieldsize=16, lead0x=lead0x),
++            self._format_hex(
++                version_section['sh_offset'], fieldsize=6, lead0x=True),
++            version_section['sh_link'],
++            bytes2str(
++                self.elffile.get_section(version_section['sh_link']).name)
++            )
++        )
++
++    def _init_versioninfo(self):
++        """ Search and initialize informations about version related sections
++            and the kind of versioning used (GNU or Solaris).
++        """
++        if self._versioninfo is not None:
++            return
++
++        self._versioninfo = {'versym': None, 'verdef': None,
++                             'verneed': None, 'type': None}
++
++        for section in self.elffile.iter_sections():
++            if isinstance(section, GNUVerSymSection):
++                self._versioninfo['versym'] = section
++            elif isinstance(section, GNUVerDefSection):
++                self._versioninfo['verdef'] = section
++            elif isinstance(section, GNUVerNeedSection):
++                self._versioninfo['verneed'] = section
++            elif isinstance(section, DynamicSection):
++                for tag in section.iter_tags():
++                    if tag['d_tag'] == 'DT_VERSYM':
++                        self._versioninfo['type'] = 'GNU'
++                        break
++
++        if not self._versioninfo['type'] and (
++                self._versioninfo['verneed'] or self._versioninfo['verdef']):
++            self._versioninfo['type'] = 'Solaris'
++
++    def _symbol_version(self, nsym):
++        """ Return a dict containing information on the
++                   or None if no version information is available
++        """
++        self._init_versioninfo()
++
++        symbol_version = dict.fromkeys(('index', 'name', 'filename', 'hidden'))
++
++        if (not self._versioninfo['versym'] or
++                nsym >= self._versioninfo['versym'].num_symbols()):
++            return None
++
++        symbol = self._versioninfo['versym'].get_symbol(nsym)
++        index = symbol.entry['ndx']
++        if not index in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL'):
++            index = int(index)
++
++            if self._versioninfo['type'] == 'GNU':
++                # In GNU versioning mode, the highest bit is used to
++                # store wether the symbol is hidden or not
++                if index & 0x8000:
++                    index &= ~0x8000
++                    symbol_version['hidden'] = True
++
++            if (self._versioninfo['verdef'] and
++                    index <= self._versioninfo['verdef'].num_versions()):
++                _, verdaux_iter = \
++                        self._versioninfo['verdef'].get_version(index)
++                symbol_version['name'] = bytes2str(next(verdaux_iter).name)
++            else:
++                verneed, vernaux = \
++                        self._versioninfo['verneed'].get_version(index)
++                symbol_version['name'] = bytes2str(vernaux.name)
++                symbol_version['filename'] = bytes2str(verneed.name)
++
++        symbol_version['index'] = index
++        return symbol_version
++
+     def _section_from_spec(self, spec):
+         """ Retrieve a section given a "spec" (either number or name).
+             Return None if no such section exists in the file.
+@@ -802,6 +1042,9 @@
+     optparser.add_option('-p', '--string-dump',
+             action='store', dest='show_string_dump', metavar='<number|name>',
+             help='Dump the contents of section <number|name> as strings')
++    optparser.add_option('-V', '--version-info',
++            action='store_true', dest='show_version_info',
++            help='Display the version sections (if present)')
+     optparser.add_option('--debug-dump',
+             action='store', dest='debug_dump_what', metavar='<what>',
+             help=(
+@@ -838,6 +1081,8 @@
+                 readelf.display_symbol_tables()
+             if options.show_relocs:
+                 readelf.display_relocations()
++            if options.show_version_info:
++                readelf.display_version_info()
+             if options.show_hex_dump:
+                 readelf.display_hex_dump(options.show_hex_dump)
+             if options.show_string_dump:
+diff -r 249a5ca85159 setup.py
+--- a/setup.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/setup.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -44,7 +44,7 @@
+         'elftools.construct', 'elftools.construct.lib',
+         ],
+ 
+-    scripts=['scripts/readelf.py'],
++    scripts=['scripts/readelf.py']
+ )
+ 
+     
+diff -r 249a5ca85159 test/run_readelf_tests.py
+--- a/test/run_readelf_tests.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/test/run_readelf_tests.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -50,7 +50,7 @@
+     success = True
+     testlog.info("Test file '%s'" % filename)
+     for option in [
+-            '-e', '-d', '-s', '-r', '-x.text', '-p.shstrtab',
++            '-e', '-d', '-s', '-r', '-x.text', '-p.shstrtab', '-V',
+             '--debug-dump=info', '--debug-dump=decodedline',
+             '--debug-dump=frames', '--debug-dump=frames-interp']:
+         if verbose: testlog.info("..option='%s'" % option)
+@@ -90,9 +90,9 @@
+         Note: this function contains some rather horrible hacks to ignore
+         differences which are not important for the verification of pyelftools.
+         This is due to some intricacies of binutils's readelf which pyelftools
+-        doesn't currently implement, or silly inconsistencies in the output of
+-        readelf, which I was reluctant to replicate.
+-        Read the documentation for more details.
++        doesn't currently implement, features that binutils doesn't support,
++        or silly inconsistencies in the output of readelf, which I was reluctant
++        to replicate. Read the documentation for more details.
+     """
+     def prepare_lines(s):
+         return [line for line in s.lower().splitlines() if line.strip() != '']
+@@ -146,6 +146,9 @@
+             elif 'os/abi' in lines1[i]:
+                 if 'unix - gnu' in lines1[i] and 'unix - linux' in lines2[i]:
+                     ok = True
++            elif (  'unknown at value' in lines1[i] and
++                    'dw_at_apple' in lines2[i]):
++                ok = True
+             else:
+                 for s in ('t (tls)', 'l (large)'):
+                     if s in lines1[i] or s in lines2[i]:
+@@ -183,7 +186,7 @@
+     if len(args) > 0:
+         filenames = args
+     else:
+-        filenames = list(discover_testfiles('test/testfiles'))
++        filenames = list(discover_testfiles('test/testfiles_for_readelf'))
+ 
+     success = True
+     for filename in filenames:
+diff -r 249a5ca85159 test/test_arm_support.py
+--- a/test/test_arm_support.py	Wed Apr 17 05:57:58 2013 -0700
++++ b/test/test_arm_support.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -15,7 +15,7 @@
+ 
+ class TestARMSupport(unittest.TestCase):
+     def test_hello(self):
+-        with open(os.path.join('test', 'testfiles',
++        with open(os.path.join('test', 'testfiles_for_unittests',
+                                'simple_gcc.elf.arm'), 'rb') as f:
+             elf = ELFFile(f)
+             self.assertEqual(elf.get_machine_arch(), 'ARM')
+diff -r 249a5ca85159 test/test_gnuversions.py
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/test/test_gnuversions.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -0,0 +1,160 @@
++#------------------------------------------------------------------------------
++# elftools tests
++#
++# Yann Rouillard (yann at pleiades.fr.eu.org)
++# This code is in the public domain
++#------------------------------------------------------------------------------
++try:
++    import unittest2 as unittest
++except ImportError:
++    import unittest
++import os
++
++from utils import setup_syspath
++setup_syspath()
++from elftools.elf.elffile import ELFFile
++from elftools.elf.constants import VER_FLAGS
++from elftools.elf.gnuversions import (
++        GNUVerNeedSection, GNUVerDefSection,
++        GNUVerSymSection)
++
++
++class TestSymbolVersioning(unittest.TestCase):
++
++    versym_reference_data = [
++        {'name': b'', 'ndx': 'VER_NDX_LOCAL'},
++        {'name': b'', 'ndx': 'VER_NDX_LOCAL'},
++        {'name': b'_ITM_deregisterTMCloneTable', 'ndx': 'VER_NDX_LOCAL'},
++        {'name': b'puts', 'ndx': 5},
++        {'name': b'strlcat', 'ndx': 'VER_NDX_LOCAL'},
++        {'name': b'__stack_chk_fail', 'ndx': 6},
++        {'name': b'__gmon_start__', 'ndx': 'VER_NDX_LOCAL'},
++        {'name': b'gzoffset', 'ndx': 7},
++        {'name': b'_Jv_RegisterClasses', 'ndx': 'VER_NDX_LOCAL'},
++        {'name': b'_ITM_registerTMCloneTable', 'ndx': 'VER_NDX_LOCAL'},
++        {'name': b'__cxa_finalize', 'ndx': 5},
++        {'name': b'_edata', 'ndx': 'VER_NDX_GLOBAL'},
++        {'name': b'VER_1.0', 'ndx': 2},
++        {'name': b'function1_ver1_1', 'ndx': 'VER_NDX_GLOBAL'},
++        {'name': b'_end', 'ndx': 'VER_NDX_GLOBAL'},
++        {'name': b'function1', 'ndx': 4 | 0x8000},
++        {'name': b'__bss_start', 'ndx': 'VER_NDX_GLOBAL'},
++        {'name': b'function1', 'ndx': 2},
++        {'name': b'VER_1.1', 'ndx': 3},
++        {'name': b'_init', 'ndx': 'VER_NDX_GLOBAL'},
++        {'name': b'function1_ver1_0', 'ndx': 'VER_NDX_GLOBAL'},
++        {'name': b'_fini', 'ndx': 'VER_NDX_GLOBAL'},
++        {'name': b'VER_1.2', 'ndx': 4},
++        {'name': b'function2', 'ndx': 3},
++    ]
++
++    def test_versym_section(self):
++
++        reference_data = TestSymbolVersioning.versym_reference_data
++
++        with open(os.path.join('test', 'testfiles_for_unittests',
++                               'lib_versioned64.so.1.elf'), 'rb') as f:
++            elf = ELFFile(f)
++            versym_section = None
++            for section in elf.iter_sections():
++                if isinstance(section, GNUVerSymSection):
++                    versym_section = section
++                    break
++
++            self.assertIsNotNone(versym_section)
++
++            for versym, ref_versym in zip(section.iter_symbols(),
++                                                   reference_data):
++                self.assertEqual(versym.name, ref_versym['name'])
++                self.assertEqual(versym['ndx'], ref_versym['ndx'])
++
++    verneed_reference_data = [
++        {'name': b'libz.so.1', 'vn_version': 1, 'vn_cnt': 1,
++         'vernaux': [
++            {'name': b'ZLIB_1.2.3.5', 'vna_flags': 0, 'vna_other': 7}]},
++        {'name': b'libc.so.6', 'vn_version': 1, 'vn_cnt': 2,
++         'vernaux': [
++            {'name': b'GLIBC_2.4', 'vna_flags': 0, 'vna_other': 6},
++            {'name': b'GLIBC_2.2.5', 'vna_flags': 0, 'vna_other': 5}]},
++        ]
++
++    def test_verneed_section(self):
++
++        reference_data = TestSymbolVersioning.verneed_reference_data
++
++        with open(os.path.join('test', 'testfiles_for_unittests',
++                               'lib_versioned64.so.1.elf'), 'rb') as f:
++            elf = ELFFile(f)
++            verneed_section = None
++            for section in elf.iter_sections():
++                if isinstance(section, GNUVerNeedSection):
++                    verneed_section = section
++                    break
++
++            self.assertIsNotNone(verneed_section)
++
++            for (verneed, vernaux_iter), ref_verneed in zip(
++                    section.iter_versions(), reference_data):
++
++                self.assertEqual(verneed.name, ref_verneed['name'])
++                self.assertEqual(verneed['vn_cnt'], ref_verneed['vn_cnt'])
++                self.assertEqual(verneed['vn_version'],
++                                 ref_verneed['vn_version'])
++
++                for vernaux, ref_vernaux in zip(
++                        vernaux_iter, ref_verneed['vernaux']):
++
++                    self.assertEqual(vernaux.name, ref_vernaux['name'])
++                    self.assertEqual(vernaux['vna_flags'],
++                                     ref_vernaux['vna_flags'])
++                    self.assertEqual(vernaux['vna_other'],
++                                     ref_vernaux['vna_other'])
++
++    verdef_reference_data = [
++        {'vd_ndx': 1, 'vd_version': 1, 'vd_flags': VER_FLAGS.VER_FLG_BASE,
++         'vd_cnt': 1,
++         'verdaux': [
++            {'name': b'lib_versioned.so.1'}]},
++        {'vd_ndx': 2, 'vd_version': 1, 'vd_flags': 0, 'vd_cnt': 1,
++         'verdaux': [
++            {'name': b'VER_1.0'}]},
++        {'vd_ndx': 3, 'vd_version': 1, 'vd_flags': 0, 'vd_cnt': 2,
++         'verdaux': [
++            {'name': b'VER_1.1'},
++            {'name': b'VER_1.0'}]},
++        {'vd_ndx': 4, 'vd_version': 1, 'vd_flags': 0, 'vd_cnt': 2,
++         'verdaux': [
++            {'name': b'VER_1.2'},
++            {'name': b'VER_1.1'}]},
++        ]
++
++    def test_verdef_section(self):
++
++        reference_data = TestSymbolVersioning.verdef_reference_data
++
++        with open(os.path.join('test', 'testfiles_for_unittests',
++                               'lib_versioned64.so.1.elf'), 'rb') as f:
++            elf = ELFFile(f)
++            verneed_section = None
++            for section in elf.iter_sections():
++                if isinstance(section, GNUVerDefSection):
++                    verdef_section = section
++                    break
++
++            self.assertIsNotNone(verdef_section)
++
++            for (verdef, verdaux_iter), ref_verdef in zip(
++                    section.iter_versions(), reference_data):
++
++                self.assertEqual(verdef['vd_ndx'], ref_verdef['vd_ndx'])
++                self.assertEqual(verdef['vd_version'],
++                                 ref_verdef['vd_version'])
++                self.assertEqual(verdef['vd_flags'], ref_verdef['vd_flags'])
++                self.assertEqual(verdef['vd_cnt'], ref_verdef['vd_cnt'])
++
++                for verdaux, ref_verdaux in zip(
++                        verdaux_iter, ref_verdef['verdaux']):
++                    self.assertEqual(verdaux.name, ref_verdaux['name'])
++
++if __name__ == '__main__':
++    unittest.main()
+diff -r 249a5ca85159 test/test_solaris_support.py
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/test/test_solaris_support.py	Mon Jun 03 17:52:42 2013 +0200
+@@ -0,0 +1,56 @@
++#-------------------------------------------------------------------------------
++# elftools tests
++#
++# Yann Rouillard (yann at pleiades.fr.eu.org)
++# This code is in the public domain
++#-------------------------------------------------------------------------------
++try:
++    import unittest2 as unittest
++except ImportError:
++    import unittest
++import os
++
++from utils import setup_syspath; setup_syspath()
++from elftools.elf.elffile import ELFFile
++from elftools.elf.constants import SUNW_SYMINFO_FLAGS
++
++
++class TestSolarisSupport(unittest.TestCase):
++
++    def _test_SUNW_syminfo_section_generic(self, testfile):
++        with open(os.path.join('test', 'testfiles_for_unittests',
++                               testfile), 'rb') as f:
++            elf = ELFFile(f)
++            syminfo_section = elf.get_section_by_name(b'.SUNW_syminfo')
++            self.assertIsNotNone(syminfo_section)
++
++            # The test files were compiled against libc.so.1 with
++            # direct binding, hence the libc symbols used
++            # (exit, atexit and _exit) have the direct binding flags
++            # in the syminfo table.
++            # We check that this is properly detected.
++            exit_symbols = [s for s in syminfo_section.iter_symbols()
++                            if b'exit' in s.name]
++            self.assertNotEqual(len(exit_symbols), 0)
++
++            for symbol in exit_symbols:
++                # libc.so.1 has the index 0 in the dynamic table
++                self.assertEqual(symbol['si_boundto'], 0)
++                self.assertEqual(symbol['si_flags'],
++                                 SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECT |
++                                 SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECTBIND)
++
++    def test_SUNW_syminfo_section_x86(self):
++        self._test_SUNW_syminfo_section_generic('exe_solaris32_cc.elf')
++
++    def test_SUNW_syminfo_section_x64(self):
++        self._test_SUNW_syminfo_section_generic('exe_solaris64_cc.elf')
++
++    def test_SUNW_syminfo_section_sparc32(self):
++        self._test_SUNW_syminfo_section_generic('exe_solaris32_cc.elf.sparc')
++
++    def test_SUNW_syminfo_section_sparc64(self):
++        self._test_SUNW_syminfo_section_generic('exe_solaris64_cc.elf.sparc')
++
++if __name__ == '__main__':
++    unittest.main()
+diff -r 249a5ca85159 test/testfiles/exe_simple32.elf
+Binary file test/testfiles/exe_simple32.elf has changed
+diff -r 249a5ca85159 test/testfiles/exe_simple64.elf
+Binary file test/testfiles/exe_simple64.elf has changed
+diff -r 249a5ca85159 test/testfiles/exe_stripped64.elf
+Binary file test/testfiles/exe_stripped64.elf has changed
+diff -r 249a5ca85159 test/testfiles/libelf0_8_13_32bit.so.elf
+Binary file test/testfiles/libelf0_8_13_32bit.so.elf has changed
+diff -r 249a5ca85159 test/testfiles/obj_simple32.o.elf
+Binary file test/testfiles/obj_simple32.o.elf has changed
+diff -r 249a5ca85159 test/testfiles/penalty_32_gcc.o.elf
+Binary file test/testfiles/penalty_32_gcc.o.elf has changed
+diff -r 249a5ca85159 test/testfiles/penalty_64_clang.o.elf
+Binary file test/testfiles/penalty_64_clang.o.elf has changed
+diff -r 249a5ca85159 test/testfiles/penalty_64_gcc.o.elf
+Binary file test/testfiles/penalty_64_gcc.o.elf has changed
+diff -r 249a5ca85159 test/testfiles/simple_gcc.elf.arm
+Binary file test/testfiles/simple_gcc.elf.arm has changed
+diff -r 249a5ca85159 test/testfiles/update32.o.elf
+Binary file test/testfiles/update32.o.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/clang33-simple.o
+Binary file test/testfiles_for_readelf/clang33-simple.o has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/exe_simple32.elf
+Binary file test/testfiles_for_readelf/exe_simple32.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/exe_simple64.elf
+Binary file test/testfiles_for_readelf/exe_simple64.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/exe_stripped64.elf
+Binary file test/testfiles_for_readelf/exe_stripped64.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/gcc48-simple.o
+Binary file test/testfiles_for_readelf/gcc48-simple.o has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/gcc48-simple.src.c
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/test/testfiles_for_readelf/gcc48-simple.src.c	Mon Jun 03 17:52:42 2013 +0200
+@@ -0,0 +1,19 @@
++/* Generated by compiling with gcc 4.8 as follows:
++**
++** gcc-4.8 -O0 -g -fno-dwarf2-cfi-asm -c dwarf4_simple.c -o gcc48-simple.
++**
++** Note: -fno-dwarf2-cfi-asm to tell gcc to generate .dwarf_frames as well
++** as the .eh_frames it generates by default.
++**
++*/
++
++extern int bar(int);
++extern int baz(int);
++
++int foo(int v) {
++    int x = bar(v);
++    int i;
++    for (i = 0; i < v; ++i)
++        x += bar(i) + bar(v) * baz(i);
++    return x;
++}
+diff -r 249a5ca85159 test/testfiles_for_readelf/libelf0_8_13_32bit.so.elf
+Binary file test/testfiles_for_readelf/libelf0_8_13_32bit.so.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/obj_simple32.o.elf
+Binary file test/testfiles_for_readelf/obj_simple32.o.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/penalty_32_gcc.o.elf
+Binary file test/testfiles_for_readelf/penalty_32_gcc.o.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/penalty_64_clang.o.elf
+Binary file test/testfiles_for_readelf/penalty_64_clang.o.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/penalty_64_gcc.o.elf
+Binary file test/testfiles_for_readelf/penalty_64_gcc.o.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_readelf/update32.o.elf
+Binary file test/testfiles_for_readelf/update32.o.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_unittests/exe_solaris32_cc.elf
+Binary file test/testfiles_for_unittests/exe_solaris32_cc.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_unittests/exe_solaris32_cc.elf.sparc
+Binary file test/testfiles_for_unittests/exe_solaris32_cc.elf.sparc has changed
+diff -r 249a5ca85159 test/testfiles_for_unittests/exe_solaris64_cc.elf
+Binary file test/testfiles_for_unittests/exe_solaris64_cc.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_unittests/exe_solaris64_cc.elf.sparc
+Binary file test/testfiles_for_unittests/exe_solaris64_cc.elf.sparc has changed
+diff -r 249a5ca85159 test/testfiles_for_unittests/lib_versioned64.so.1.elf
+Binary file test/testfiles_for_unittests/lib_versioned64.so.1.elf has changed
+diff -r 249a5ca85159 test/testfiles_for_unittests/simple_gcc.elf.arm
+Binary file test/testfiles_for_unittests/simple_gcc.elf.arm has changed

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the devel mailing list