elftools 1.3.1 → 2.1.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 +193 -7
- data/lib/elftools/constants/machine.rb +248 -0
- data/lib/elftools/constants/machine_names.rb +246 -0
- data/lib/elftools/constants/relocation/aarch64.rb +213 -0
- data/lib/elftools/constants/relocation/alpha.rb +47 -0
- data/lib/elftools/constants/relocation/amdgpu.rb +28 -0
- data/lib/elftools/constants/relocation/arm.rb +150 -0
- data/lib/elftools/constants/relocation/avr.rb +51 -0
- data/lib/elftools/constants/relocation/bfin.rb +72 -0
- data/lib/elftools/constants/relocation/bpf.rb +21 -0
- data/lib/elftools/constants/relocation/cr16.rb +46 -0
- data/lib/elftools/constants/relocation/cris.rb +46 -0
- data/lib/elftools/constants/relocation/crx.rb +35 -0
- data/lib/elftools/constants/relocation/csky.rb +79 -0
- data/lib/elftools/constants/relocation/d10v.rb +23 -0
- data/lib/elftools/constants/relocation/d30v.rb +27 -0
- data/lib/elftools/constants/relocation/dlx.rb +24 -0
- data/lib/elftools/constants/relocation/epiphany.rb +28 -0
- data/lib/elftools/constants/relocation/fr30.rb +27 -0
- data/lib/elftools/constants/relocation/frv.rb +57 -0
- data/lib/elftools/constants/relocation/ft32.rb +27 -0
- data/lib/elftools/constants/relocation/h8.rb +69 -0
- data/lib/elftools/constants/relocation/hppa.rb +135 -0
- data/lib/elftools/constants/relocation/i370.rb +26 -0
- data/lib/elftools/constants/relocation/i386.rb +59 -0
- data/lib/elftools/constants/relocation/i860.rb +48 -0
- data/lib/elftools/constants/relocation/i960.rb +22 -0
- data/lib/elftools/constants/relocation/ia64.rb +117 -0
- data/lib/elftools/constants/relocation/ip2k.rb +29 -0
- data/lib/elftools/constants/relocation/iq2000.rb +27 -0
- data/lib/elftools/constants/relocation/kvx.rb +97 -0
- data/lib/elftools/constants/relocation/lm32.rb +32 -0
- data/lib/elftools/constants/relocation/loongarch.rb +144 -0
- data/lib/elftools/constants/relocation/m32c.rb +27 -0
- data/lib/elftools/constants/relocation/m32r.rb +57 -0
- data/lib/elftools/constants/relocation/m68hc11.rb +35 -0
- data/lib/elftools/constants/relocation/m68k.rb +57 -0
- data/lib/elftools/constants/relocation/mcore.rb +27 -0
- data/lib/elftools/constants/relocation/mep.rb +36 -0
- data/lib/elftools/constants/relocation/metag.rb +63 -0
- data/lib/elftools/constants/relocation/microblaze.rb +48 -0
- data/lib/elftools/constants/relocation/mips.rb +125 -0
- data/lib/elftools/constants/relocation/mmix.rb +51 -0
- data/lib/elftools/constants/relocation/mn10200.rb +22 -0
- data/lib/elftools/constants/relocation/mn10300.rb +49 -0
- data/lib/elftools/constants/relocation/moxie.rb +17 -0
- data/lib/elftools/constants/relocation/msp430.rb +27 -0
- data/lib/elftools/constants/relocation/msp430x.rb +37 -0
- data/lib/elftools/constants/relocation/mt.rb +21 -0
- data/lib/elftools/constants/relocation/nds32.rb +167 -0
- data/lib/elftools/constants/relocation/nfp.rb +41 -0
- data/lib/elftools/constants/relocation/nfp3200.rb +46 -0
- data/lib/elftools/constants/relocation/nios2.rb +74 -0
- data/lib/elftools/constants/relocation/or1k.rb +69 -0
- data/lib/elftools/constants/relocation/pj.rb +24 -0
- data/lib/elftools/constants/relocation/ppc.rb +131 -0
- data/lib/elftools/constants/relocation/ppc64.rb +177 -0
- data/lib/elftools/constants/relocation/pru.rb +31 -0
- data/lib/elftools/constants/relocation/riscv.rb +74 -0
- data/lib/elftools/constants/relocation/rl78.rb +70 -0
- data/lib/elftools/constants/relocation/rx.rb +81 -0
- data/lib/elftools/constants/relocation/s12z.rb +22 -0
- data/lib/elftools/constants/relocation/s390.rb +82 -0
- data/lib/elftools/constants/relocation/score.rb +36 -0
- data/lib/elftools/constants/relocation/sh.rb +124 -0
- data/lib/elftools/constants/relocation/sparc.rb +108 -0
- data/lib/elftools/constants/relocation/spu.rb +32 -0
- data/lib/elftools/constants/relocation/tic6x.rb +48 -0
- data/lib/elftools/constants/relocation/tilegx.rb +134 -0
- data/lib/elftools/constants/relocation/tilepro.rb +105 -0
- data/lib/elftools/constants/relocation/v800.rb +101 -0
- data/lib/elftools/constants/relocation/v850.rb +66 -0
- data/lib/elftools/constants/relocation/vax.rb +29 -0
- data/lib/elftools/constants/relocation/visium.rb +30 -0
- data/lib/elftools/constants/relocation/wasm32.rb +16 -0
- data/lib/elftools/constants/relocation/x86_64.rb +68 -0
- data/lib/elftools/constants/relocation/xgate.rb +34 -0
- data/lib/elftools/constants/relocation/xstormy16.rb +29 -0
- data/lib/elftools/constants/relocation/xtensa.rb +75 -0
- data/lib/elftools/constants/relocation/z80.rb +28 -0
- data/lib/elftools/constants/relocation.rb +181 -0
- data/lib/elftools/constants.rb +168 -231
- data/lib/elftools/dynamic/hash_table.rb +232 -0
- data/lib/elftools/dynamic/string_table.rb +30 -0
- data/lib/elftools/dynamic/symbols.rb +174 -0
- data/lib/elftools/dynamic/tag.rb +66 -0
- data/lib/elftools/dynamic/versions.rb +87 -0
- data/lib/elftools/dynamic.rb +119 -62
- data/lib/elftools/elf_file.rb +74 -22
- data/lib/elftools/lazy_array.rb +42 -4
- data/lib/elftools/note.rb +6 -3
- data/lib/elftools/relative_relocations.rb +88 -0
- data/lib/elftools/relocation.rb +144 -0
- data/lib/elftools/sections/dynamic_section.rb +13 -0
- data/lib/elftools/sections/relative_relocation_section.rb +46 -0
- data/lib/elftools/sections/relocation_section.rb +24 -43
- data/lib/elftools/sections/section.rb +35 -4
- data/lib/elftools/sections/sections.rb +8 -0
- data/lib/elftools/sections/sym_tab_section.rb +47 -35
- data/lib/elftools/sections/symbol.rb +202 -0
- 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/segments/dynamic_segment.rb +1 -0
- data/lib/elftools/segments/load_segment.rb +33 -5
- data/lib/elftools/segments/segment.rb +8 -4
- data/lib/elftools/structs.rb +132 -18
- data/lib/elftools/util.rb +69 -12
- data/lib/elftools/version.rb +1 -1
- data/lib/elftools/version_tables.rb +155 -0
- metadata +108 -11
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'elftools/constants'
|
|
4
|
+
require 'elftools/util'
|
|
5
|
+
|
|
6
|
+
module ELFTools
|
|
7
|
+
# A relocation entry.
|
|
8
|
+
#
|
|
9
|
+
# Can be either a REL or RELA relocation.
|
|
10
|
+
class Relocation
|
|
11
|
+
attr_reader :header # @return [ELFTools::Structs::ELF_Rel, ELFTools::Structs::ELF_Rela] Rel(a) header.
|
|
12
|
+
attr_reader :stream # @return [#pos=, #read] Streaming object.
|
|
13
|
+
|
|
14
|
+
# Instantiate a {Relocation} object.
|
|
15
|
+
# @param [ELFTools::Structs::ELF_Rel, ELFTools::Structs::ELF_Rela] header
|
|
16
|
+
# The relocation header.
|
|
17
|
+
# @param [#pos=, #read] stream The streaming object.
|
|
18
|
+
# @param [Integer] machine
|
|
19
|
+
# The machine of the ELF file, which decides what {#type} means and how
|
|
20
|
+
# {#header} records it.
|
|
21
|
+
def initialize(header, stream, machine: nil)
|
|
22
|
+
@header = header
|
|
23
|
+
@stream = stream
|
|
24
|
+
@machine = machine
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Which symbol this relocation is against, as an index into the symbol
|
|
28
|
+
# table.
|
|
29
|
+
# @return [Integer] The symbol index.
|
|
30
|
+
def symbol_index
|
|
31
|
+
sym_and_type.first
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# What this relocation does, which only means something together with the
|
|
35
|
+
# machine of the file. {#type_name} names it.
|
|
36
|
+
# @return [Integer] The relocation type.
|
|
37
|
+
def type
|
|
38
|
+
sym_and_type.last
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Sets which symbol this relocation is against.
|
|
42
|
+
# @param [Integer] index The symbol index.
|
|
43
|
+
# @raise [ArgumentError] If the bits recording it cannot hold it.
|
|
44
|
+
# @example
|
|
45
|
+
# relocation.symbol_index = 3
|
|
46
|
+
def symbol_index=(index)
|
|
47
|
+
header.r_info = info_of(Util.fits!(index, index_bits, 'Symbol index'), type)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Sets what this relocation does.
|
|
51
|
+
# @param [Integer] type The relocation type.
|
|
52
|
+
# @raise [ArgumentError] If the bits recording it cannot hold it.
|
|
53
|
+
# @example
|
|
54
|
+
# relocation.type = ELFTools::Constants::R::X86_64::R_X86_64_JUMP_SLOT
|
|
55
|
+
def type=(type)
|
|
56
|
+
header.r_info = info_of(symbol_index, Util.fits!(type, type_bits, 'Relocation type'))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# The name of {#type}.
|
|
60
|
+
#
|
|
61
|
+
# Every architecture numbers relocation types on its own, so the name is
|
|
62
|
+
# only known when the machine of the file is.
|
|
63
|
+
# @return [String] The name.
|
|
64
|
+
# @example
|
|
65
|
+
# relocation.type_name
|
|
66
|
+
# #=> 'R_X86_64_JUMP_SLOT'
|
|
67
|
+
def type_name
|
|
68
|
+
Constants::R.mapping(@machine, type)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
# The +r_info+ recording a symbol index and a type, laid out the way this
|
|
74
|
+
# file lays it out. The inverse of {#sym_and_type}.
|
|
75
|
+
# @return [Integer] The +r_info+.
|
|
76
|
+
def info_of(index, type)
|
|
77
|
+
return mips64_info_of(index, type) if mips64?
|
|
78
|
+
|
|
79
|
+
(index << mask_bit) | type
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# The +r_info+ as the 64-bit MIPS ABI records it, leaving the bytes the
|
|
83
|
+
# ABI keeps for itself as they were.
|
|
84
|
+
# @return [Integer] The +r_info+.
|
|
85
|
+
def mips64_info_of(index, type)
|
|
86
|
+
info = header.r_info.to_i
|
|
87
|
+
return (index << 32) | (info & 0xffff_ff00) | type if header.class.self_endian == :big
|
|
88
|
+
|
|
89
|
+
(info & 0x00ff_ffff_0000_0000) | (type << 56) | index
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# How many bits record a symbol index.
|
|
93
|
+
# @return [Integer] The number.
|
|
94
|
+
def index_bits
|
|
95
|
+
mips64? ? 32 : (header.elf_class - mask_bit)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# How many bits record a relocation type.
|
|
99
|
+
# @return [Integer] The number.
|
|
100
|
+
def type_bits
|
|
101
|
+
mips64? ? 8 : mask_bit
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# What +r_info+ records, i.e. a symbol index and a relocation type. Most
|
|
105
|
+
# machines split the field in half between the two, one lays it out its
|
|
106
|
+
# own way.
|
|
107
|
+
# @return [Array(Integer, Integer)] The symbol index and the type.
|
|
108
|
+
def sym_and_type
|
|
109
|
+
return mips64_sym_and_type if mips64?
|
|
110
|
+
|
|
111
|
+
[header.r_info >> mask_bit, header.r_info & ((1 << mask_bit) - 1)]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Whether the file records relocations the way the 64-bit MIPS ABI does,
|
|
115
|
+
# which is the one layout that departs from halving +r_info+.
|
|
116
|
+
# @return [Boolean] The answer.
|
|
117
|
+
def mips64?
|
|
118
|
+
@machine == Constants::EM_MIPS && header.elf_class == 64
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Reads +r_info+ as the 64-bit MIPS ABI records it, i.e. a symbol index of
|
|
122
|
+
# four bytes followed by four bytes the ABI keeps for itself, the last of
|
|
123
|
+
# which is the type reported here. Those bytes are ordered as the rest of
|
|
124
|
+
# the file is, which is why the two ends of the field swap places.
|
|
125
|
+
# @example
|
|
126
|
+
# # A big endian file records the symbol index first,
|
|
127
|
+
# # 00 00 00 08 | 00 05 18 07
|
|
128
|
+
# # sym | ssym type3 type2 type
|
|
129
|
+
# 0x0000000800051807 #=> [8, 7]
|
|
130
|
+
# # a little endian one records the very same relocation as
|
|
131
|
+
# 0x0718050000000008 #=> [8, 7]
|
|
132
|
+
# @return [Array(Integer, Integer)] The symbol index and the type.
|
|
133
|
+
def mips64_sym_and_type
|
|
134
|
+
info = header.r_info.to_i
|
|
135
|
+
return [info >> 32, info & 0xff] if header.class.self_endian == :big
|
|
136
|
+
|
|
137
|
+
[info & 0xffff_ffff, info >> 56]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def mask_bit
|
|
141
|
+
header.elf_class == 32 ? 8 : 32
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -12,6 +12,19 @@ module ELFTools
|
|
|
12
12
|
class DynamicSection < Section
|
|
13
13
|
include ELFTools::Dynamic
|
|
14
14
|
|
|
15
|
+
# Instantiate a {DynamicSection} object.
|
|
16
|
+
# @param [ELFTools::Structs::ELF_Shdr] header
|
|
17
|
+
# See {Section#initialize} for more information.
|
|
18
|
+
# @param [#pos=, #read] stream
|
|
19
|
+
# See {Section#initialize} for more information.
|
|
20
|
+
# @param [Integer] machine
|
|
21
|
+
# The machine of the ELF file, which decides what the entries a tag
|
|
22
|
+
# points at mean. This should be +e_machine+ of the ELF header.
|
|
23
|
+
def initialize(header, stream, machine: nil, **_kwargs)
|
|
24
|
+
@machine = machine
|
|
25
|
+
super
|
|
26
|
+
end
|
|
27
|
+
|
|
15
28
|
# Get the start address of tags.
|
|
16
29
|
# @return [Integer] Start address of tags.
|
|
17
30
|
def tag_start
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'elftools/relative_relocations'
|
|
4
|
+
require 'elftools/sections/section'
|
|
5
|
+
|
|
6
|
+
module ELFTools
|
|
7
|
+
module Sections
|
|
8
|
+
# Class of the section packing the relocations that only add the load bias.
|
|
9
|
+
#
|
|
10
|
+
# This section is usually named .relr.dyn, and records the very relocations
|
|
11
|
+
# the +DT_RELR+ tag points at.
|
|
12
|
+
class RelativeRelocationSection < Section
|
|
13
|
+
# Instantiate a {RelativeRelocationSection} object.
|
|
14
|
+
# @param [ELFTools::Structs::ELF_Shdr] header
|
|
15
|
+
# See {Section#initialize} for more information.
|
|
16
|
+
# @param [#pos=, #read] stream
|
|
17
|
+
# See {Section#initialize} for more information.
|
|
18
|
+
# @param [Integer] machine
|
|
19
|
+
# The machine of the ELF file, which decides what these relocations
|
|
20
|
+
# are of. This should be +e_machine+ of the ELF header.
|
|
21
|
+
def initialize(header, stream, machine: nil, **_kwargs)
|
|
22
|
+
@machine = machine
|
|
23
|
+
super
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The relocations the section packs.
|
|
27
|
+
# @return [Array<ELFTools::Relocation>]
|
|
28
|
+
# The relocations, in the ascending order the section records them.
|
|
29
|
+
# @example
|
|
30
|
+
# section.relocations.map(&:type_name).uniq
|
|
31
|
+
# #=> ['R_X86_64_RELATIVE']
|
|
32
|
+
def relocations
|
|
33
|
+
@relocations ||= RelativeRelocations.new(
|
|
34
|
+
stream, header.sh_offset.to_i...(header.sh_offset.to_i + header.sh_size.to_i),
|
|
35
|
+
elf_class: header.elf_class, endian: header.class.self_endian, machine: @machine
|
|
36
|
+
).to_a
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# How many relocations the section packs.
|
|
40
|
+
# @return [Integer] The number.
|
|
41
|
+
def num_relocations
|
|
42
|
+
relocations.size
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'elftools/constants'
|
|
4
|
+
require 'elftools/relocation'
|
|
4
5
|
require 'elftools/sections/section'
|
|
5
6
|
require 'elftools/structs'
|
|
6
7
|
|
|
7
8
|
module ELFTools
|
|
8
9
|
module Sections
|
|
9
|
-
# Class of
|
|
10
|
-
#
|
|
10
|
+
# Class of relocation section.
|
|
11
|
+
# Usually for sections .rel.* and .rela.*,
|
|
12
|
+
# which record relocations in ELF file.
|
|
11
13
|
class RelocationSection < Section
|
|
14
|
+
# Instantiate a {RelocationSection} object.
|
|
15
|
+
# @param [ELFTools::Structs::ELF_Shdr] header
|
|
16
|
+
# See {Section#initialize} for more information.
|
|
17
|
+
# @param [#pos=, #read] stream
|
|
18
|
+
# See {Section#initialize} for more information.
|
|
19
|
+
# @param [Integer] machine
|
|
20
|
+
# The machine of the ELF file, which decides what a relocation type
|
|
21
|
+
# means. This should be +e_machine+ of the ELF header.
|
|
22
|
+
def initialize(header, stream, machine: nil, **_kwargs)
|
|
23
|
+
@machine = machine
|
|
24
|
+
super
|
|
25
|
+
end
|
|
26
|
+
|
|
12
27
|
# Is this relocation a RELA or REL type.
|
|
13
28
|
# @return [Boolean] If is RELA.
|
|
14
29
|
def rela?
|
|
@@ -42,19 +57,22 @@ module ELFTools
|
|
|
42
57
|
# @return [Enumerator<ELFTools::Relocation>, Array<ELFTools::Relocation>]
|
|
43
58
|
# If block is not given, an enumerator will be returned.
|
|
44
59
|
# Otherwise, the whole relocations will be returned.
|
|
45
|
-
def
|
|
46
|
-
return enum_for(:
|
|
60
|
+
def each_relocation(&block)
|
|
61
|
+
return enum_for(:each_relocation) unless block_given?
|
|
47
62
|
|
|
48
63
|
Array.new(num_relocations) do |i|
|
|
49
64
|
relocation_at(i).tap(&block)
|
|
50
65
|
end
|
|
51
66
|
end
|
|
52
67
|
|
|
68
|
+
# The name this used to go by, kept so that it keeps working.
|
|
69
|
+
alias each_relocations each_relocation
|
|
70
|
+
|
|
53
71
|
# Simply use {#relocations} to get all relocations.
|
|
54
72
|
# @return [Array<ELFTools::Relocation>]
|
|
55
73
|
# Whole relocations.
|
|
56
74
|
def relocations
|
|
57
|
-
|
|
75
|
+
each_relocation.to_a
|
|
58
76
|
end
|
|
59
77
|
|
|
60
78
|
private
|
|
@@ -65,45 +83,8 @@ module ELFTools
|
|
|
65
83
|
rel = klass.new(endian: header.class.self_endian, offset: stream.pos)
|
|
66
84
|
rel.elf_class = header.elf_class
|
|
67
85
|
rel.read(stream)
|
|
68
|
-
Relocation.new(rel, stream)
|
|
86
|
+
Relocation.new(rel, stream, machine: @machine)
|
|
69
87
|
end
|
|
70
88
|
end
|
|
71
89
|
end
|
|
72
|
-
|
|
73
|
-
# A relocation entry.
|
|
74
|
-
#
|
|
75
|
-
# Can be either a REL or RELA relocation.
|
|
76
|
-
# XXX: move this to an independent file?
|
|
77
|
-
class Relocation
|
|
78
|
-
attr_reader :header # @return [ELFTools::Structs::ELF_Rel, ELFTools::Structs::ELF_Rela] Rel(a) header.
|
|
79
|
-
attr_reader :stream # @return [#pos=, #read] Streaming object.
|
|
80
|
-
|
|
81
|
-
# Instantiate a {Relocation} object.
|
|
82
|
-
def initialize(header, stream)
|
|
83
|
-
@header = header
|
|
84
|
-
@stream = stream
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# +r_info+ contains sym and type, use two methods
|
|
88
|
-
# to access them easier.
|
|
89
|
-
# @return [Integer] sym infor.
|
|
90
|
-
def r_info_sym
|
|
91
|
-
header.r_info >> mask_bit
|
|
92
|
-
end
|
|
93
|
-
alias symbol_index r_info_sym
|
|
94
|
-
|
|
95
|
-
# +r_info+ contains sym and type, use two methods
|
|
96
|
-
# to access them easier.
|
|
97
|
-
# @return [Integer] type infor.
|
|
98
|
-
def r_info_type
|
|
99
|
-
header.r_info & ((1 << mask_bit) - 1)
|
|
100
|
-
end
|
|
101
|
-
alias type r_info_type
|
|
102
|
-
|
|
103
|
-
private
|
|
104
|
-
|
|
105
|
-
def mask_bit
|
|
106
|
-
header.elf_class == 32 ? 8 : 32
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
90
|
end
|
|
@@ -13,16 +13,16 @@ module ELFTools
|
|
|
13
13
|
# The section header object.
|
|
14
14
|
# @param [#pos=, #read] stream
|
|
15
15
|
# The streaming object for further dump.
|
|
16
|
-
# @param [ELFTools::Sections::StrTabSection, Proc]
|
|
16
|
+
# @param [ELFTools::Sections::StrTabSection, Proc] section_name_table
|
|
17
17
|
# The string table object. For fetching section names.
|
|
18
18
|
# If +Proc+ if given, it will call at the first
|
|
19
19
|
# time access +#name+.
|
|
20
20
|
# @param [Method] offset_from_vma
|
|
21
21
|
# The method to get offset of file, given virtual memory address.
|
|
22
|
-
def initialize(header, stream, offset_from_vma: nil,
|
|
22
|
+
def initialize(header, stream, offset_from_vma: nil, section_name_table: nil, **_kwargs)
|
|
23
23
|
@header = header
|
|
24
24
|
@stream = stream
|
|
25
|
-
@
|
|
25
|
+
@section_name_table = section_name_table
|
|
26
26
|
@offset_from_vma = offset_from_vma
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -36,7 +36,7 @@ module ELFTools
|
|
|
36
36
|
# Get name of this section.
|
|
37
37
|
# @return [String] The name.
|
|
38
38
|
def name
|
|
39
|
-
@name ||= @
|
|
39
|
+
@name ||= @section_name_table.call.name_at(header.sh_name)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
# Fetch data of this section.
|
|
@@ -46,6 +46,37 @@ module ELFTools
|
|
|
46
46
|
stream.read(header.sh_size)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
# Is this section written to while the file runs?
|
|
50
|
+
# @return [Boolean] True or false.
|
|
51
|
+
# @example
|
|
52
|
+
# elf.section_by_name('.data').writable?
|
|
53
|
+
# #=> true
|
|
54
|
+
def writable?
|
|
55
|
+
header.sh_flags.allbits?(Constants::SHF_WRITE)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Is this section executed?
|
|
59
|
+
# @return [Boolean] True or false.
|
|
60
|
+
# @example
|
|
61
|
+
# elf.section_by_name('.text').executable?
|
|
62
|
+
# #=> true
|
|
63
|
+
def executable?
|
|
64
|
+
header.sh_flags.allbits?(Constants::SHF_EXECINSTR)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Does this section take memory while the file runs?
|
|
68
|
+
#
|
|
69
|
+
# The ones that do are what a file is loaded by, the rest being what is
|
|
70
|
+
# recorded about it, its symbol names and its debugging information
|
|
71
|
+
# among them.
|
|
72
|
+
# @return [Boolean] True or false.
|
|
73
|
+
# @example
|
|
74
|
+
# elf.section_by_name('.symtab').allocated?
|
|
75
|
+
# #=> false
|
|
76
|
+
def allocated?
|
|
77
|
+
header.sh_flags.allbits?(Constants::SHF_ALLOC)
|
|
78
|
+
end
|
|
79
|
+
|
|
49
80
|
# Is this a null section?
|
|
50
81
|
# @return [Boolean] No it's not.
|
|
51
82
|
def null?
|
|
@@ -7,9 +7,13 @@ require 'elftools/sections/section'
|
|
|
7
7
|
require 'elftools/sections/dynamic_section'
|
|
8
8
|
require 'elftools/sections/note_section'
|
|
9
9
|
require 'elftools/sections/null_section'
|
|
10
|
+
require 'elftools/sections/relative_relocation_section'
|
|
10
11
|
require 'elftools/sections/relocation_section'
|
|
11
12
|
require 'elftools/sections/str_tab_section'
|
|
12
13
|
require 'elftools/sections/sym_tab_section'
|
|
14
|
+
require 'elftools/sections/version_definition_section'
|
|
15
|
+
require 'elftools/sections/version_need_section'
|
|
16
|
+
require 'elftools/sections/version_section'
|
|
13
17
|
|
|
14
18
|
module ELFTools
|
|
15
19
|
# Defines different types of sections in this module.
|
|
@@ -27,6 +31,10 @@ module ELFTools
|
|
|
27
31
|
when Constants::SHT_NULL then NullSection
|
|
28
32
|
when Constants::SHT_NOTE then NoteSection
|
|
29
33
|
when Constants::SHT_RELA, Constants::SHT_REL then RelocationSection
|
|
34
|
+
when Constants::SHT_RELR then RelativeRelocationSection
|
|
35
|
+
when Constants::SHT_GNU_versym then VersionSection
|
|
36
|
+
when Constants::SHT_GNU_verneed then VersionNeedSection
|
|
37
|
+
when Constants::SHT_GNU_verdef then VersionDefinitionSection
|
|
30
38
|
when Constants::SHT_STRTAB then StrTabSection
|
|
31
39
|
when Constants::SHT_SYMTAB, Constants::SHT_DYNSYM then SymTabSection
|
|
32
40
|
else Section
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'elftools/sections/section'
|
|
4
|
+
require 'elftools/sections/symbol'
|
|
5
|
+
require 'elftools/version_tables'
|
|
4
6
|
|
|
5
7
|
module ELFTools
|
|
6
8
|
module Sections
|
|
@@ -15,11 +17,16 @@ module ELFTools
|
|
|
15
17
|
# See {Section#initialize} for more information.
|
|
16
18
|
# @param [#pos=, #read] stream
|
|
17
19
|
# See {Section#initialize} for more information.
|
|
18
|
-
# @param [Proc]
|
|
19
|
-
# The method for fetching
|
|
20
|
-
# This lambda should be
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
# @param [Proc] sections
|
|
21
|
+
# The method for fetching the sections, which is where the names and
|
|
22
|
+
# the versions of these symbols are recorded. This lambda should be
|
|
23
|
+
# {ELFTools::ELFFile#sections}.
|
|
24
|
+
# @param [Integer] machine
|
|
25
|
+
# The machine of the ELF file, which decides what the fields of a
|
|
26
|
+
# symbol mean. This should be +e_machine+ of the ELF header.
|
|
27
|
+
def initialize(header, stream, sections: nil, machine: nil, **_kwargs)
|
|
28
|
+
@sections = sections
|
|
29
|
+
@machine = machine
|
|
23
30
|
# For faster #symbol_by_name
|
|
24
31
|
super
|
|
25
32
|
end
|
|
@@ -56,19 +63,22 @@ module ELFTools
|
|
|
56
63
|
# @return [Enumerator<ELFTools::Sections::Symbol>, Array<ELFTools::Sections::Symbol>]
|
|
57
64
|
# If block is not given, an enumerator will be returned.
|
|
58
65
|
# Otherwise return array of symbols.
|
|
59
|
-
def
|
|
60
|
-
return enum_for(:
|
|
66
|
+
def each_symbol(&block)
|
|
67
|
+
return enum_for(:each_symbol) unless block_given?
|
|
61
68
|
|
|
62
69
|
Array.new(num_symbols) do |i|
|
|
63
70
|
symbol_at(i).tap(&block)
|
|
64
71
|
end
|
|
65
72
|
end
|
|
66
73
|
|
|
74
|
+
# The name this used to go by, kept so that it keeps working.
|
|
75
|
+
alias each_symbols each_symbol
|
|
76
|
+
|
|
67
77
|
# Simply use {#symbols} to get all symbols.
|
|
68
78
|
# @return [Array<ELFTools::Sections::Symbol>]
|
|
69
79
|
# The whole symbols.
|
|
70
80
|
def symbols
|
|
71
|
-
|
|
81
|
+
each_symbol.to_a
|
|
72
82
|
end
|
|
73
83
|
|
|
74
84
|
# Get symbol by its name.
|
|
@@ -76,14 +86,14 @@ module ELFTools
|
|
|
76
86
|
# The name of symbol.
|
|
77
87
|
# @return [ELFTools::Sections::Symbol] Desired symbol.
|
|
78
88
|
def symbol_by_name(name)
|
|
79
|
-
|
|
89
|
+
each_symbol.find { |symbol| symbol.name == name }
|
|
80
90
|
end
|
|
81
91
|
|
|
82
92
|
# Return the symbol string section.
|
|
83
93
|
# Lazy loaded.
|
|
84
94
|
# @return [ELFTools::Sections::StrTabSection] The string table section.
|
|
85
95
|
def symstr
|
|
86
|
-
@symstr ||= @
|
|
96
|
+
@symstr ||= @sections.call[header.sh_link]
|
|
87
97
|
end
|
|
88
98
|
|
|
89
99
|
private
|
|
@@ -92,35 +102,37 @@ module ELFTools
|
|
|
92
102
|
stream.pos = header.sh_offset + n * header.sh_entsize
|
|
93
103
|
sym = Structs::ELF_sym[header.elf_class].new(endian: header.class.self_endian, offset: stream.pos)
|
|
94
104
|
sym.read(stream)
|
|
95
|
-
Symbol.new(sym, stream, symstr: method(:symstr))
|
|
105
|
+
Symbol.new(sym, stream, symstr: method(:symstr), machine: @machine, version: -> { version_at(n) })
|
|
96
106
|
end
|
|
97
|
-
end
|
|
98
107
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
@
|
|
116
|
-
|
|
117
|
-
|
|
108
|
+
# The version the +n+-th symbol binds to.
|
|
109
|
+
# @return [ELFTools::VersionTables::Version, nil]
|
|
110
|
+
# The version, +nil+ unless this is the table a file is loaded by and
|
|
111
|
+
# the file records versions at all.
|
|
112
|
+
def version_at(n)
|
|
113
|
+
return if versions.nil?
|
|
114
|
+
|
|
115
|
+
VersionTables.version(versions.version_at(n), versions_by_index)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# The section recording which version each of these symbols binds to,
|
|
119
|
+
# which is the one naming this table.
|
|
120
|
+
# @return [ELFTools::Sections::VersionSection, nil] The section.
|
|
121
|
+
def versions
|
|
122
|
+
return @versions if defined?(@versions)
|
|
123
|
+
|
|
124
|
+
@versions = @sections&.call&.find do |sec|
|
|
125
|
+
sec.is_a?(VersionSection) && @sections.call[sec.header.sh_link].equal?(self)
|
|
126
|
+
end
|
|
118
127
|
end
|
|
119
128
|
|
|
120
|
-
#
|
|
121
|
-
# @return [String] The
|
|
122
|
-
def
|
|
123
|
-
@
|
|
129
|
+
# The name each index the symbols record names.
|
|
130
|
+
# @return [Hash{Integer => String}] The names.
|
|
131
|
+
def versions_by_index
|
|
132
|
+
@versions_by_index ||= VersionTables.names(
|
|
133
|
+
@sections.call.grep(VersionNeedSection).flat_map(&:requirements),
|
|
134
|
+
@sections.call.grep(VersionDefinitionSection).flat_map(&:definitions)
|
|
135
|
+
)
|
|
124
136
|
end
|
|
125
137
|
end
|
|
126
138
|
end
|