From: Yann Rouillard Date: Fri, 31 May 2013 20:15:09 +0000 (+0200) Subject: Create a common parent class for Version (Definition|Dependency) section to share... X-Git-Tag: v0.22~40 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f9b7ea006471bc2d6e4bf257ca6c4c03b071e1c8;p=pyelftools.git Create a common parent class for Version (Definition|Dependency) section to share common code --- diff --git a/elftools/elf/gnuversions.py b/elftools/elf/gnuversions.py index 5965659..4a4473f 100644 --- a/elftools/elf/gnuversions.py +++ b/elftools/elf/gnuversions.py @@ -51,110 +51,132 @@ class VersionAuxiliary(object): return self.entry[name] -class GNUVerNeedSection(Section): - """ ELF SUNW or GNU Version Needed table section. - Has an associated StringTableSection that's passed in the constructor. +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): - super(GNUVerNeedSection, self).__init__(header, name, stream) + + 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.elfstructs = self.elffile.structs self.stringtable = stringtable - self._has_indexes = None + self.field_prefix = field_prefix + self.version_struct = version_struct + self.version_auxiliaries_struct = version_auxiliaries_struct def num_versions(self): - """ Number of version dependency in the table + """ Number of version entries in the section """ return self['sh_info'] - 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 + def _field_name(self, name, auxiliary=False): + """ Return the real field's name of version or a version auxiliary + entry """ - 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 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 + 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 dependency + """ 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.elfstructs.Elf_Vernaux, + self.version_auxiliaries_struct, self.stream, stream_pos=entry_offset) - name = self.stringtable.get_string(entry['vna_name']) + name = self.stringtable.get_string(entry[name_field]) version_aux = VersionAuxiliary(entry, name) yield version_aux - if not entry['vna_next']: - break - - entry_offset += entry['vna_next'] + entry_offset += entry[next_field] def iter_versions(self): - """ Yield all the version dependencies entries in the table - Each time it returns the main version dependency structure + """ 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.elfstructs.Elf_Verneed, + self.version_struct, self.stream, stream_pos=entry_offset) - name = self.stringtable.get_string(entry['vn_file']) - elf_assert(entry['vn_cnt'] > 0, - 'Expected number of version names to be > 0 for' - 'version definition %s' % name) + 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))) - verneed = Version(entry, name) - aux_entries_offset = entry_offset + entry['vn_aux'] - vernaux_iter = self._iter_version_auxiliaries(aux_entries_offset, - entry['vn_cnt']) - yield verneed, vernaux_iter + version = Version(entry) + aux_entries_offset = entry_offset + entry[aux_field] + version_auxiliaries_iter = self._iter_version_auxiliaries( + aux_entries_offset, entry[count_field]) - if not entry['vn_next']: - break + yield version, version_auxiliaries_iter - entry_offset += entry['vn_next'] + entry_offset += entry[next_field] -class GNUVerDefSection(Section): - """ ELF SUNW or GNU Version Definition table section. +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(GNUVerDefSection, self).__init__(header, name, stream) - self.elffile = elffile - self.elfstructs = self.elffile.structs - self.stringtable = stringtable + super(GNUVerNeedSection, self).__init__( + header, name, stream, elffile, stringtable, 'vn', + elffile.structs.Elf_Verneed, elffile.structs.Elf_Vernaux) + self._has_indexes = None - def num_versions(self): - """ Number of version definitions in the table + 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 """ - return self['sh_info'] + 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 @@ -168,51 +190,6 @@ class GNUVerDefSection(Section): return None - def _iter_version_auxiliaries(self, entry_offset, count): - """ Yield all auxiliary entries of a version definition - """ - for _ in range(count): - entry = struct_parse( - self.elfstructs.Elf_Verdaux, - self.stream, - stream_pos=entry_offset) - - name = self.stringtable.get_string(entry['vda_name']) - vernaux = VersionAuxiliary(entry, name) - yield vernaux - - if not entry['vda_next']: - break - - entry_offset += entry['vda_next'] - - def iter_versions(self): - """ Yield all the version definition entries in the table - Each time it returns the main version definition structure - and an iterator to walk through its auxiliaries entries - """ - entry_offset = self['sh_offset'] - for _ in range(self.num_versions()): - entry = struct_parse( - self.elfstructs.Elf_Verdef, - self.stream, - stream_pos=entry_offset) - - elf_assert(entry['vd_cnt'] > 0, - 'Expected number of version names to be > 0' - 'for version definition at index %i' % entry['vd_ndx']) - - verdef = Version(entry) - aux_entries_offset = entry_offset + entry['vd_aux'] - verdaux_iter = self._iter_version_auxiliaries(aux_entries_offset, - entry['vd_cnt']) - yield verdef, verdaux_iter - - if not entry['vd_next']: - break - - entry_offset += entry['vd_next'] - class GNUVerSymSection(Section): """ ELF SUNW or GNU Versym table section.