Class: ELFTools::VersionTables

Inherits:
Object
  • Object
show all
Defined in:
lib/elftools/version_tables.rb

Overview

The two tables a file records its versions in.

One holds the versions the file needs of the files it is loaded with, the other the versions it defines for what it exports, and a symbol names one of either by the same index. Both are chains, each entry saying how far off the next one is, and both are recorded twice over: the tags point at them, and so do sections.

Defined Under Namespace

Classes: Definition, Requirement, Version

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stream, strtab, endian:) ⇒ VersionTables

Instantiate a ELFTools::VersionTables object.

Parameters:

  • stream (#pos=, #read)

    Streaming object.

  • strtab (#name_at)

    The table the names are recorded in.

  • endian (Symbol)

    :little or :big.



45
46
47
48
49
# File 'lib/elftools/version_tables.rb', line 45

def initialize(stream, strtab, endian:)
  @stream = stream
  @strtab = strtab
  @endian = endian
end

Class Method Details

.names(requirements, definitions) ⇒ Hash{Integer => String}

The name each index of either table names.

Parameters:

Returns:

  • (Hash{Integer => String})

    The names.



19
20
21
# File 'lib/elftools/version_tables.rb', line 19

def self.names(requirements, definitions)
  (requirements.flat_map(&:versions) + definitions).to_h { |version| [version.index, version.name] }
end

.version(recorded, names) ⇒ ELFTools::VersionTables::Version?

The version a symbol records, read against the names of the tables.

Parameters:

  • recorded (Integer, nil)

    What the symbol records, which is an index with the highest bit marking a version asked for by name rather than the default one.

  • names (Hash{Integer => String})

    What names answered.

Returns:

  • (ELFTools::VersionTables::Version, nil)

    The version, nil where the symbol names none: a symbol of the file itself, a symbol of no version at all, and a name nothing records.



31
32
33
34
35
36
37
38
39
# File 'lib/elftools/version_tables.rb', line 31

def self.version(recorded, names)
  return if recorded.nil?

  index = recorded & ~Constants::VER_NDX_HIDDEN
  return if index <= Constants::VER_NDX_GLOBAL

  name = names[index]
  Version.new(name, index, hidden: !(recorded & Constants::VER_NDX_HIDDEN).zero?) if name
end

Instance Method Details

#definitions(at, count) ⇒ Array<ELFTools::VersionTables::Definition>

Reads the versions a file defines for what it exports.

Parameters:

  • at (Integer)

    The file offset the table starts at.

  • count (Integer)

    How many entries it has.

Returns:



68
69
70
71
72
73
74
75
76
77
# File 'lib/elftools/version_tables.rb', line 68

def definitions(at, count)
  chain(at, count, Structs::ELF_Verdef, :vd_next) do |defn, from|
    names = chain(from + defn.vd_aux.to_i, defn.vd_cnt.to_i, Structs::ELF_Verdaux, :vda_next) do |aux, _|
      @strtab.name_at(aux.vda_name.to_i)
    end
    # The first name is the version's own, the rest are what it descends from.
    Definition.new(names.first, defn.vd_ndx.to_i, names.drop(1),
                   base: !(defn.vd_flags.to_i & Constants::VER_FLG_BASE).zero?)
  end
end

#requirements(at, count) ⇒ Array<ELFTools::VersionTables::Requirement>

Reads the versions a file needs of the files it is loaded with.

Parameters:

  • at (Integer)

    The file offset the table starts at.

  • count (Integer)

    How many entries it has.

Returns:



55
56
57
58
59
60
61
62
# File 'lib/elftools/version_tables.rb', line 55

def requirements(at, count)
  chain(at, count, Structs::ELF_Verneed, :vn_next) do |need, from|
    versions = chain(from + need.vn_aux.to_i, need.vn_cnt.to_i, Structs::ELF_Vernaux, :vna_next) do |aux, _|
      Version.new(@strtab.name_at(aux.vna_name.to_i), aux.vna_other.to_i)
    end
    Requirement.new(@strtab.name_at(need.vn_file.to_i), versions)
  end
end