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.
- checksums.yaml +4 -4
- data/README.md +82 -0
- data/lib/elftools/constants.rb +53 -0
- data/lib/elftools/dynamic/hash_table.rb +16 -0
- data/lib/elftools/dynamic/symbols.rb +54 -19
- data/lib/elftools/dynamic/tag.rb +28 -6
- data/lib/elftools/dynamic/versions.rb +87 -0
- data/lib/elftools/dynamic.rb +33 -35
- data/lib/elftools/elf_file.rb +61 -11
- data/lib/elftools/relative_relocations.rb +87 -0
- data/lib/elftools/relocation.rb +72 -9
- data/lib/elftools/sections/relative_relocation_section.rb +46 -0
- data/lib/elftools/sections/relocation_section.rb +16 -5
- data/lib/elftools/sections/section.rb +31 -0
- data/lib/elftools/sections/sections.rb +8 -0
- data/lib/elftools/sections/sym_tab_section.rb +64 -10
- data/lib/elftools/sections/symbol.rb +112 -10
- data/lib/elftools/sections/version_definition_section.rb +40 -0
- data/lib/elftools/sections/version_need_section.rb +40 -0
- data/lib/elftools/sections/version_section.rb +44 -0
- data/lib/elftools/structs.rb +373 -17
- data/lib/elftools/util.rb +68 -11
- data/lib/elftools/version.rb +1 -1
- data/lib/elftools/version_tables.rb +155 -0
- metadata +9 -2
|
@@ -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.
|
|
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.
|
|
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
|