elftools 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'elftools/constants'
4
+ require 'elftools/structs'
5
+
6
+ module ELFTools
7
+ # The two tables a file records its versions in.
8
+ #
9
+ # One holds the versions the file needs of the files it is loaded with, the
10
+ # other the versions it defines for what it exports, and a symbol names one
11
+ # of either by the same index. Both are chains, each entry saying how far
12
+ # off the next one is, and both are recorded twice over: the tags point at
13
+ # them, and so do sections.
14
+ class VersionTables
15
+ # The name each index of either table names.
16
+ # @param [Array<ELFTools::VersionTables::Requirement>] requirements The requirements.
17
+ # @param [Array<ELFTools::VersionTables::Definition>] definitions The definitions.
18
+ # @return [Hash{Integer => String}] The names.
19
+ def self.names(requirements, definitions)
20
+ (requirements.flat_map(&:versions) + definitions).to_h { |version| [version.index, version.name] }
21
+ end
22
+
23
+ # The version a symbol records, read against the names of the tables.
24
+ # @param [Integer, nil] recorded
25
+ # What the symbol records, which is an index with the highest bit marking
26
+ # a version asked for by name rather than the default one.
27
+ # @param [Hash{Integer => String}] names What {names} answered.
28
+ # @return [ELFTools::VersionTables::Version, nil]
29
+ # The version, +nil+ where the symbol names none: a symbol of the file
30
+ # itself, a symbol of no version at all, and a name nothing records.
31
+ def self.version(recorded, names)
32
+ return if recorded.nil?
33
+
34
+ index = recorded & ~Constants::VER_NDX_HIDDEN
35
+ return if index <= Constants::VER_NDX_GLOBAL
36
+
37
+ name = names[index]
38
+ Version.new(name, index, hidden: !(recorded & Constants::VER_NDX_HIDDEN).zero?) if name
39
+ end
40
+
41
+ # Instantiate a {ELFTools::VersionTables} object.
42
+ # @param [#pos=, #read] stream Streaming object.
43
+ # @param [#name_at] strtab The table the names are recorded in.
44
+ # @param [Symbol] endian +:little+ or +:big+.
45
+ def initialize(stream, strtab, endian:)
46
+ @stream = stream
47
+ @strtab = strtab
48
+ @endian = endian
49
+ end
50
+
51
+ # Reads the versions a file needs of the files it is loaded with.
52
+ # @param [Integer] at The file offset the table starts at.
53
+ # @param [Integer] count How many entries it has.
54
+ # @return [Array<ELFTools::VersionTables::Requirement>] The requirements.
55
+ def requirements(at, count)
56
+ chain(at, count, Structs::ELF_Verneed, :vn_next) do |need, from|
57
+ versions = chain(from + need.vn_aux.to_i, need.vn_cnt.to_i, Structs::ELF_Vernaux, :vna_next) do |aux, _|
58
+ Version.new(@strtab.name_at(aux.vna_name.to_i), aux.vna_other.to_i)
59
+ end
60
+ Requirement.new(@strtab.name_at(need.vn_file.to_i), versions)
61
+ end
62
+ end
63
+
64
+ # Reads the versions a file defines for what it exports.
65
+ # @param [Integer] at The file offset the table starts at.
66
+ # @param [Integer] count How many entries it has.
67
+ # @return [Array<ELFTools::VersionTables::Definition>] The definitions.
68
+ def definitions(at, count)
69
+ chain(at, count, Structs::ELF_Verdef, :vd_next) do |defn, from|
70
+ names = chain(from + defn.vd_aux.to_i, defn.vd_cnt.to_i, Structs::ELF_Verdaux, :vda_next) do |aux, _|
71
+ @strtab.name_at(aux.vda_name.to_i)
72
+ end
73
+ # The first name is the version's own, the rest are what it descends from.
74
+ Definition.new(names.first, defn.vd_ndx.to_i, names.drop(1),
75
+ base: !(defn.vd_flags.to_i & Constants::VER_FLG_BASE).zero?)
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ # Reads a chain of entries, each saying how far off the one after it is.
82
+ # @return [Array] What the block makes of each entry.
83
+ def chain(at, count, klass, following)
84
+ Array.new(count) do
85
+ entry = klass.new(endian: @endian, offset: at)
86
+ @stream.pos = at
87
+ entry.read(@stream)
88
+ yield(entry, at).tap { at += entry.send(following).to_i }
89
+ end
90
+ end
91
+
92
+ # A version a file needs or defines.
93
+ class Version
94
+ attr_reader :name # @return [String] The name, +GLIBC_2.2.5+ for instance.
95
+ attr_reader :index # @return [Integer] The index the symbols name it with.
96
+
97
+ # Instantiate a {ELFTools::VersionTables::Version} object.
98
+ # @param [String] name The name.
99
+ # @param [Integer] index The index.
100
+ # @param [Boolean] hidden Whether a symbol binds to it as a version that is not the default.
101
+ def initialize(name, index, hidden: false)
102
+ @name = name
103
+ @index = index
104
+ @hidden = hidden
105
+ end
106
+
107
+ # Whether the symbol binding to this version binds to something other
108
+ # than the default, which is what more than one version of a name means.
109
+ # @return [Boolean] The answer.
110
+ def hidden?
111
+ @hidden
112
+ end
113
+ end
114
+
115
+ # The versions a file needs of one of the files it is loaded with.
116
+ class Requirement
117
+ attr_reader :file # @return [String] The name of the file, +libc.so.6+ for instance.
118
+ attr_reader :versions # @return [Array<ELFTools::VersionTables::Version>] The versions needed of it.
119
+
120
+ # Instantiate a {ELFTools::VersionTables::Requirement} object.
121
+ # @param [String] file The name of the file.
122
+ # @param [Array<ELFTools::VersionTables::Version>] versions The versions.
123
+ def initialize(file, versions)
124
+ @file = file
125
+ @versions = versions
126
+ end
127
+ end
128
+
129
+ # A version a file defines for what it exports.
130
+ class Definition
131
+ attr_reader :name # @return [String] The name.
132
+ attr_reader :index # @return [Integer] The index the symbols name it with.
133
+ attr_reader :parents # @return [Array<String>] The names of the versions it descends from.
134
+
135
+ # Instantiate a {ELFTools::VersionTables::Definition} object.
136
+ # @param [String] name The name.
137
+ # @param [Integer] index The index.
138
+ # @param [Array<String>] parents The names it descends from.
139
+ # @param [Boolean] base Whether it names the file rather than a version of it.
140
+ def initialize(name, index, parents, base: false)
141
+ @name = name
142
+ @index = index
143
+ @parents = parents
144
+ @base = base
145
+ end
146
+
147
+ # Whether this names the file itself rather than a version of it, which
148
+ # the first definition of a file does.
149
+ # @return [Boolean] The answer.
150
+ def base?
151
+ @base
152
+ end
153
+ end
154
+ end
155
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elftools
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - david942j
@@ -224,20 +224,26 @@ files:
224
224
  - lib/elftools/dynamic/string_table.rb
225
225
  - lib/elftools/dynamic/symbols.rb
226
226
  - lib/elftools/dynamic/tag.rb
227
+ - lib/elftools/dynamic/versions.rb
227
228
  - lib/elftools/elf_file.rb
228
229
  - lib/elftools/exceptions.rb
229
230
  - lib/elftools/lazy_array.rb
230
231
  - lib/elftools/note.rb
232
+ - lib/elftools/relative_relocations.rb
231
233
  - lib/elftools/relocation.rb
232
234
  - lib/elftools/sections/dynamic_section.rb
233
235
  - lib/elftools/sections/note_section.rb
234
236
  - lib/elftools/sections/null_section.rb
237
+ - lib/elftools/sections/relative_relocation_section.rb
235
238
  - lib/elftools/sections/relocation_section.rb
236
239
  - lib/elftools/sections/section.rb
237
240
  - lib/elftools/sections/sections.rb
238
241
  - lib/elftools/sections/str_tab_section.rb
239
242
  - lib/elftools/sections/sym_tab_section.rb
240
243
  - lib/elftools/sections/symbol.rb
244
+ - lib/elftools/sections/version_definition_section.rb
245
+ - lib/elftools/sections/version_need_section.rb
246
+ - lib/elftools/sections/version_section.rb
241
247
  - lib/elftools/segments/dynamic_segment.rb
242
248
  - lib/elftools/segments/interp_segment.rb
243
249
  - lib/elftools/segments/load_segment.rb
@@ -247,12 +253,13 @@ files:
247
253
  - lib/elftools/structs.rb
248
254
  - lib/elftools/util.rb
249
255
  - lib/elftools/version.rb
256
+ - lib/elftools/version_tables.rb
250
257
  homepage: https://github.com/david942j/rbelftools
251
258
  licenses:
252
259
  - MIT
253
260
  metadata:
254
261
  rubygems_mfa_required: 'true'
255
- changelog_uri: https://github.com/david942j/rbelftools/blob/v2.0.0/CHANGELOG.md
262
+ changelog_uri: https://github.com/david942j/rbelftools/blob/v2.2.0/CHANGELOG.md
256
263
  rdoc_options: []
257
264
  require_paths:
258
265
  - lib