elftools 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +139 -0
- data/lib/elftools/constants.rb +182 -0
- data/lib/elftools/dynamic.rb +106 -0
- data/lib/elftools/elf_file.rb +277 -0
- data/lib/elftools/exceptions.rb +3 -0
- data/lib/elftools/lazy_array.rb +43 -0
- data/lib/elftools/note.rb +112 -0
- data/lib/elftools/sections/dynamic_section.rb +20 -0
- data/lib/elftools/sections/note_section.rb +25 -0
- data/lib/elftools/sections/null_section.rb +16 -0
- data/lib/elftools/sections/section.rb +44 -0
- data/lib/elftools/sections/sections.rb +34 -0
- data/lib/elftools/sections/str_tab_section.rb +27 -0
- data/lib/elftools/sections/sym_tab_section.rb +123 -0
- data/lib/elftools/segments/dynamic_segment.rb +18 -0
- data/lib/elftools/segments/interp_segment.rb +18 -0
- data/lib/elftools/segments/note_segment.rb +24 -0
- data/lib/elftools/segments/segment.rb +44 -0
- data/lib/elftools/segments/segments.rb +30 -0
- data/lib/elftools/structures.rb +133 -0
- data/lib/elftools/util.rb +51 -0
- data/lib/elftools/version.rb +3 -0
- data/lib/elftools.rb +9 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c59b0333aab08b885d294a4d0295d6bac48eb11c
|
4
|
+
data.tar.gz: 79ce95770fcf3911db8c7260bc6009d8e3cf2839
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f1bf67e49c1d910509199fd1c4276760ecc022a9e88a1045ddd3aeccab62f258a176bc57b059b71eec3b74bde3d652d666b53284a701785df5c79a385dbfc8aa
|
7
|
+
data.tar.gz: e5b41464b5b6d092bbb0cf752b73594a8771d5c91840ee471fd0744ed7259d994c25a3a46d2e2d509907aef12b1e0c817a77b1d544f3c5bd01c350e2f3b4cd0a
|
data/README.md
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/david942j/rbelftools.svg?branch=master)](https://travis-ci.org/david942j/rbelftools)
|
2
|
+
[![Code Climate](https://codeclimate.com/github/david942j/rbelftools/badges/gpa.svg)](https://codeclimate.com/github/david942j/rbelftools)
|
3
|
+
[![Issue Count](https://codeclimate.com/github/david942j/rbelftools/badges/issue_count.svg)](https://codeclimate.com/github/david942j/rbelftools)
|
4
|
+
[![Test Coverage](https://codeclimate.com/github/david942j/rbelftools/badges/coverage.svg)](https://codeclimate.com/github/david942j/rbelftools/coverage)
|
5
|
+
[![Inline docs](https://inch-ci.org/github/david942j/rbelftools.svg?branch=master)](https://inch-ci.org/github/david942j/rbelftools)
|
6
|
+
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](http://choosealicense.com/licenses/mit/)
|
7
|
+
|
8
|
+
# Introduction
|
9
|
+
|
10
|
+
ELF parser in pure ruby implementation. This work is inspired by [pyelftools](https://github.com/eliben/pyelftools) by [Eli Bendersky](https://github.com/eliben).
|
11
|
+
|
12
|
+
The motivation to create this repository is want to be a dependency of [pwntools-ruby](https://github.com/peter50216/pwntools-ruby). Since ELF parser is a big work, it should not be implemented directly in pwntools.
|
13
|
+
|
14
|
+
**rbelftools**'s target is to create a nice ELF parser library in ruby. More features are work in progress.
|
15
|
+
|
16
|
+
# Install
|
17
|
+
|
18
|
+
Available on RubyGems.org!
|
19
|
+
```bash
|
20
|
+
gem install elftools
|
21
|
+
```
|
22
|
+
|
23
|
+
# Example Usage
|
24
|
+
|
25
|
+
## Start from file object
|
26
|
+
```ruby
|
27
|
+
require 'elftools'
|
28
|
+
elf = ELFTools::ELFFile.new(File.open('spec/files/amd64.elf'))
|
29
|
+
#=> #<ELFTools::ELFFile:0x00560b147f8328 @elf_class=64, @endian=:little, @stream=#<File:spec/files/amd64>>
|
30
|
+
|
31
|
+
elf.machine
|
32
|
+
#=> 'Advanced Micro Devices X86-64'
|
33
|
+
|
34
|
+
elf.build_id
|
35
|
+
#=> '73ab62cb7bc9959ce053c2b711322158708cdc07'
|
36
|
+
```
|
37
|
+
|
38
|
+
## Sections
|
39
|
+
```ruby
|
40
|
+
elf.section_by_name('.dynstr')
|
41
|
+
#=>
|
42
|
+
# #<ELFTools::Sections::StrTabSection:0x00560b148cef40
|
43
|
+
# @header=
|
44
|
+
# {:sh_name=>86,
|
45
|
+
# :sh_type=>3,
|
46
|
+
# :sh_flags=>2,
|
47
|
+
# :sh_addr=>4195224,
|
48
|
+
# :sh_offset=>920,
|
49
|
+
# :sh_size=>113,
|
50
|
+
# :sh_link=>0,
|
51
|
+
# :sh_info=>0,
|
52
|
+
# :sh_addralign=>1,
|
53
|
+
# :sh_entsize=>0},
|
54
|
+
# @name=".dynstr">
|
55
|
+
```
|
56
|
+
```ruby
|
57
|
+
elf.sections.map(&:name).join(' ')
|
58
|
+
#=> " .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss .comment .shstrtab .symtab .strtab"
|
59
|
+
```
|
60
|
+
```ruby
|
61
|
+
elf.section_by_name('.note.gnu.build-id').data
|
62
|
+
#=> "\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00s\xABb\xCB{\xC9\x95\x9C\xE0S\xC2\xB7\x112!Xp\x8C\xDC\a"
|
63
|
+
```
|
64
|
+
|
65
|
+
## Symbols
|
66
|
+
```ruby
|
67
|
+
symtab_section = elf.section_by_name('.symtab')
|
68
|
+
symtab_section.num_symbols
|
69
|
+
#=> 75
|
70
|
+
|
71
|
+
symtab_section.symbol_by_name('puts@@GLIBC_2.2.5')
|
72
|
+
#=>
|
73
|
+
# #<ELFTools::Symbol:0x00560b14af67a0
|
74
|
+
# @header={:st_name=>348, :st_info=>18, :st_other=>0, :st_shndx=>0, :st_value=>0, :st_size=>0},
|
75
|
+
# @name="puts@@GLIBC_2.2.5">
|
76
|
+
|
77
|
+
symbols = symtab_section.symbols # Array of symbols
|
78
|
+
symbols.map(&:name).reject(&:empty?).first(5).join(' ')
|
79
|
+
#=> "crtstuff.c __JCR_LIST__ deregister_tm_clones register_tm_clones __do_global_dtors_aux"
|
80
|
+
```
|
81
|
+
|
82
|
+
## Segments
|
83
|
+
```ruby
|
84
|
+
elf.segment_by_type(:note)
|
85
|
+
#=>
|
86
|
+
# #<ELFTools::Segments::NoteSegment:0x00555beaafe218
|
87
|
+
# @header=
|
88
|
+
# {:p_type=>4,
|
89
|
+
# :p_flags=>4,
|
90
|
+
# :p_offset=>624,
|
91
|
+
# :p_vaddr=>624,
|
92
|
+
# :p_paddr=>624,
|
93
|
+
# :p_filesz=>68,
|
94
|
+
# :p_memsz=>68,
|
95
|
+
# :p_align=>4}>
|
96
|
+
|
97
|
+
elf.segment_by_type(:interp).interp_name
|
98
|
+
#=> "/lib64/ld-linux-x86-64.so.2"
|
99
|
+
```
|
100
|
+
|
101
|
+
# Why rbelftools
|
102
|
+
|
103
|
+
1. Fully documented
|
104
|
+
|
105
|
+
Always important for an Open-Source project. Online document is [here](http://www.rubydoc.info/github/david942j/rbelftools/master/frames)
|
106
|
+
2. Fully tested
|
107
|
+
|
108
|
+
Of course.
|
109
|
+
3. Lazy loading on everything
|
110
|
+
|
111
|
+
To use **rbelftools**, only need to pass the stream object of ELF file.
|
112
|
+
**rbelftools** will read the stream object **as least times as possible** when parsing
|
113
|
+
the file. Most information will not be fetched until you need it, which makes
|
114
|
+
**rbelftools** efficient.
|
115
|
+
4. To be a library
|
116
|
+
|
117
|
+
**rbelftools** is designed to be a library for furthur usage.
|
118
|
+
It will _not_ add any too trivial features.
|
119
|
+
For example, to check if NX disabled, you can use
|
120
|
+
`elf.segment_by_type(:gnu_stack).executable?` but not `elf.nx?`
|
121
|
+
5. Section and segment parser
|
122
|
+
|
123
|
+
Providing common sections and segments parser. For example, .symtab, .shstrtab
|
124
|
+
.dynamic sections and INTERP, DYNAMIC segments, etc.
|
125
|
+
|
126
|
+
# Development
|
127
|
+
```bash
|
128
|
+
git clone https://github.com/david942j/rbelftools.git
|
129
|
+
cd rbelftools
|
130
|
+
bundle
|
131
|
+
rake
|
132
|
+
```
|
133
|
+
Any comments or suggestions are welcome!
|
134
|
+
|
135
|
+
# Cross Platform
|
136
|
+
**rbelftools** can be used on Linux and OSX. Should also work on Windows but not tested.
|
137
|
+
|
138
|
+
# License
|
139
|
+
MIT License
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module ELFTools
|
2
|
+
# Define constants from elf.h.
|
3
|
+
# Mostly refer from https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h.
|
4
|
+
module Constants
|
5
|
+
# ELF magic header
|
6
|
+
ELFMAG = "\x7FELF".freeze
|
7
|
+
|
8
|
+
# Section header types, records in +sh_type+.
|
9
|
+
module SHT
|
10
|
+
SHT_NULL = 0
|
11
|
+
SHT_PROGBITS = 1
|
12
|
+
SHT_SYMTAB = 2
|
13
|
+
SHT_STRTAB = 3
|
14
|
+
SHT_RELA = 4
|
15
|
+
SHT_HASH = 5
|
16
|
+
SHT_DYNAMIC = 6
|
17
|
+
SHT_NOTE = 7
|
18
|
+
SHT_NOBITS = 8
|
19
|
+
SHT_REL = 9
|
20
|
+
SHT_SHLIB = 10
|
21
|
+
SHT_DYNSYM = 11
|
22
|
+
SHT_NUM = 12
|
23
|
+
SHT_LOPROC = 0x70000000
|
24
|
+
SHT_HIPROC = 0x7fffffff
|
25
|
+
SHT_LOUSER = 0x80000000
|
26
|
+
SHT_HIUSER = 0xffffffff
|
27
|
+
end
|
28
|
+
include SHT
|
29
|
+
|
30
|
+
# Program header types, records in +p_type+.
|
31
|
+
module PT
|
32
|
+
PT_NULL = 0
|
33
|
+
PT_LOAD = 1
|
34
|
+
PT_DYNAMIC = 2
|
35
|
+
PT_INTERP = 3
|
36
|
+
PT_NOTE = 4
|
37
|
+
PT_SHLIB = 5
|
38
|
+
PT_PHDR = 6
|
39
|
+
PT_TLS = 7 # Thread local storage segment
|
40
|
+
PT_LOOS = 0x60000000 # OS-specific
|
41
|
+
PT_HIOS = 0x6fffffff # OS-specific
|
42
|
+
PT_LOPROC = 0x70000000
|
43
|
+
PT_HIPROC = 0x7fffffff
|
44
|
+
PT_GNU_EH_FRAME = 0x6474e550
|
45
|
+
PT_GNU_STACK = (PT_LOOS + 0x474e551)
|
46
|
+
end
|
47
|
+
include PT
|
48
|
+
|
49
|
+
# Dynamic table types, records in +d_tag+.
|
50
|
+
module DT
|
51
|
+
DT_NULL = 0
|
52
|
+
DT_NEEDED = 1
|
53
|
+
DT_PLTRELSZ = 2
|
54
|
+
DT_PLTGOT = 3
|
55
|
+
DT_HASH = 4
|
56
|
+
DT_STRTAB = 5
|
57
|
+
DT_SYMTAB = 6
|
58
|
+
DT_RELA = 7
|
59
|
+
DT_RELASZ = 8
|
60
|
+
DT_RELAENT = 9
|
61
|
+
DT_STRSZ = 10
|
62
|
+
DT_SYMENT = 11
|
63
|
+
DT_INIT = 12
|
64
|
+
DT_FINI = 13
|
65
|
+
DT_SONAME = 14
|
66
|
+
DT_RPATH = 15
|
67
|
+
DT_SYMBOLIC = 16
|
68
|
+
DT_REL = 17
|
69
|
+
DT_RELSZ = 18
|
70
|
+
DT_RELENT = 19
|
71
|
+
DT_PLTREL = 20
|
72
|
+
DT_DEBUG = 21
|
73
|
+
DT_TEXTREL = 22
|
74
|
+
DT_JMPREL = 23
|
75
|
+
DT_ENCODING = 32
|
76
|
+
DT_LOOS = 0x6000000d
|
77
|
+
DT_HIOS = 0x6ffff000
|
78
|
+
DT_VALRNGLO = 0x6ffffd00
|
79
|
+
DT_VALRNGHI = 0x6ffffdff
|
80
|
+
DT_ADDRRNGLO = 0x6ffffe00
|
81
|
+
DT_ADDRRNGHI = 0x6ffffeff
|
82
|
+
DT_VERSYM = 0x6ffffff0
|
83
|
+
DT_RELACOUNT = 0x6ffffff9
|
84
|
+
DT_RELCOUNT = 0x6ffffffa
|
85
|
+
DT_FLAGS_1 = 0x6ffffffb
|
86
|
+
DT_VERDEF = 0x6ffffffc
|
87
|
+
DT_VERDEFNUM = 0x6ffffffd
|
88
|
+
DT_VERNEED = 0x6ffffffe
|
89
|
+
DT_VERNEEDNUM = 0x6fffffff
|
90
|
+
DT_LOPROC = 0x70000000
|
91
|
+
DT_HIPROC = 0x7fffffff
|
92
|
+
end
|
93
|
+
include DT
|
94
|
+
|
95
|
+
# These constants define the various ELF target machines.
|
96
|
+
module EM
|
97
|
+
EM_NONE = 0
|
98
|
+
EM_M32 = 1
|
99
|
+
EM_SPARC = 2
|
100
|
+
EM_386 = 3
|
101
|
+
EM_68K = 4
|
102
|
+
EM_88K = 5
|
103
|
+
EM_486 = 6 # Perhaps disused
|
104
|
+
EM_860 = 7
|
105
|
+
EM_MIPS = 8 # MIPS R3000 (officially, big-endian only)
|
106
|
+
# Next two are historical and binaries and
|
107
|
+
# modules of these types will be rejected by Linux.
|
108
|
+
EM_MIPS_RS3_LE = 10 # MIPS R3000 little-endian
|
109
|
+
EM_MIPS_RS4_BE = 10 # MIPS R4000 big-endian
|
110
|
+
|
111
|
+
EM_PARISC = 15 # HPPA
|
112
|
+
EM_SPARC32PLUS = 18 # Sun's "v8plus"
|
113
|
+
EM_PPC = 20 # PowerPC
|
114
|
+
EM_PPC64 = 21 # PowerPC64
|
115
|
+
EM_SPU = 23 # Cell BE SPU
|
116
|
+
EM_ARM = 40 # ARM 32 bit
|
117
|
+
EM_SH = 42 # SuperH
|
118
|
+
EM_SPARCV9 = 43 # SPARC v9 64-bit
|
119
|
+
EM_H8_300 = 46 # Renesas H8/300
|
120
|
+
EM_IA_64 = 50 # HP/Intel IA-64
|
121
|
+
EM_X86_64 = 62 # AMD x86-64
|
122
|
+
EM_S390 = 22 # IBM S/390
|
123
|
+
EM_CRIS = 76 # Axis Communications 32-bit embedded processor
|
124
|
+
EM_M32R = 88 # Renesas M32R
|
125
|
+
EM_MN10300 = 89 # Panasonic/MEI MN10300, AM33
|
126
|
+
EM_OPENRISC = 92 # OpenRISC 32-bit embedded processor
|
127
|
+
EM_BLACKFIN = 106 # ADI Blackfin Processor
|
128
|
+
EM_ALTERA_NIOS2 = 113 # Altera Nios II soft-core processor
|
129
|
+
EM_TI_C6000 = 140 # TI C6X DSPs
|
130
|
+
EM_AARCH64 = 183 # ARM 64 bit
|
131
|
+
EM_TILEPRO = 188 # Tilera TILEPro
|
132
|
+
EM_MICROBLAZE = 189 # Xilinx MicroBlaze
|
133
|
+
EM_TILEGX = 191 # Tilera TILE-Gx
|
134
|
+
EM_BPF = 247 # Linux BPF - in-kernel virtual machine
|
135
|
+
EM_FRV = 0x5441 # Fujitsu FR-V
|
136
|
+
EM_AVR32 = 0x18ad # Atmel AVR32
|
137
|
+
|
138
|
+
# This is an interim value that we will use until the committee comes up with a final number.
|
139
|
+
EM_ALPHA = 0x9026
|
140
|
+
|
141
|
+
# Bogus old m32r magic number, used by old tools.
|
142
|
+
EM_CYGNUS_M32R = 0x9041
|
143
|
+
# This is the old interim value for S/390 architecture
|
144
|
+
EM_S390_OLD = 0xA390
|
145
|
+
# Also Panasonic/MEI MN10300, AM33
|
146
|
+
EM_CYGNUS_MN10300 = 0xbeef
|
147
|
+
|
148
|
+
# Return the architecture name according to +val+.
|
149
|
+
# Used by {ELFTools::ELFFile#machine}.
|
150
|
+
#
|
151
|
+
# Only supports famous archs.
|
152
|
+
# @param [Integer] val Value of +e_machine+.
|
153
|
+
# @return [String]
|
154
|
+
# Name of architecture.
|
155
|
+
# @example
|
156
|
+
# mapping(3)
|
157
|
+
# #=> 'Intel 80386'
|
158
|
+
# mapping(6)
|
159
|
+
# #=> 'Intel 80386'
|
160
|
+
# mapping(62)
|
161
|
+
# #=> 'Advanced Micro Devices X86-64'
|
162
|
+
# mapping(1337)
|
163
|
+
# #=> '<unknown>: 0x539'
|
164
|
+
def self.mapping(val)
|
165
|
+
case val
|
166
|
+
when EM_NONE then 'None'
|
167
|
+
when EM_386, EM_486 then 'Intel 80386'
|
168
|
+
when EM_860 then 'Intel 80860'
|
169
|
+
when EM_MIPS then 'MIPS R3000'
|
170
|
+
when EM_PPC then 'PowerPC'
|
171
|
+
when EM_PPC64 then 'PowerPC64'
|
172
|
+
when EM_ARM then 'ARM'
|
173
|
+
when EM_IA_64 then 'Intel IA-64'
|
174
|
+
when EM_AARCH64 then 'AArch64'
|
175
|
+
when EM_X86_64 then 'Advanced Micro Devices X86-64'
|
176
|
+
else format('<unknown>: 0x%x', val)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
include EM
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module ELFTools
|
2
|
+
# Define common methods for dynamic sections and
|
3
|
+
# dynamic segments.
|
4
|
+
#
|
5
|
+
# Notice: this module can only be included by
|
6
|
+
# {ELFTools::Sections::DynamicSection} and
|
7
|
+
# {ELFTools::Segments::DynamicSegment} because
|
8
|
+
# methods here assume some attributes exist.
|
9
|
+
module Dynamic
|
10
|
+
# Iterate all tags.
|
11
|
+
#
|
12
|
+
# Notice: this method assume the following methods
|
13
|
+
# already exist:
|
14
|
+
# header
|
15
|
+
# tag_start
|
16
|
+
# @param [Block] block You can give a block.
|
17
|
+
# @return [Array<ELFTools::Dynamic::Tag>] Array of tags.
|
18
|
+
def each_tags
|
19
|
+
arr = []
|
20
|
+
0.step do |i|
|
21
|
+
tag = tag_at(i)
|
22
|
+
yield tag if block_given?
|
23
|
+
arr << tag
|
24
|
+
break if tag.header.d_tag == ELFTools::Constants::DT_NULL
|
25
|
+
end
|
26
|
+
arr
|
27
|
+
end
|
28
|
+
alias tags each_tags
|
29
|
+
|
30
|
+
# Get a tag of specific type.
|
31
|
+
# @param [Integer, Symbol, String] type
|
32
|
+
# Constant value, symbol, or string of type
|
33
|
+
# is acceptable. See examples for more information.
|
34
|
+
# @return [ELFTools::Dynamic::Tag] The desired tag.
|
35
|
+
# @example
|
36
|
+
# dynamic = elf.segment_by_type(:dynamic)
|
37
|
+
# # type as integer
|
38
|
+
# dynamic.tag_by_type(0) # the null tag
|
39
|
+
# #=> #<ELFTools::Dynamic::Tag:0x0055b5a5ecad28 @header={:d_tag=>0, :d_val=>0}>
|
40
|
+
# dynamic.tag_by_type(ELFTools::Constants::DT_NULL)
|
41
|
+
# #=> #<ELFTools::Dynamic::Tag:0x0055b5a5ecad28 @header={:d_tag=>0, :d_val=>0}>
|
42
|
+
#
|
43
|
+
# # symbol
|
44
|
+
# dynamic.tag_by_type(:null)
|
45
|
+
# #=> #<ELFTools::Dynamic::Tag:0x0055b5a5ecad28 @header={:d_tag=>0, :d_val=>0}>
|
46
|
+
# dynamic.tag_by_type(:pltgot)
|
47
|
+
# #=> #<ELFTools::Dynamic::Tag:0x0055d3d2d91b28 @header={:d_tag=>3, :d_val=>6295552}>
|
48
|
+
#
|
49
|
+
# # string
|
50
|
+
# dynamic.tag_by_type('null')
|
51
|
+
# #=> #<ELFTools::Dynamic::Tag:0x0055b5a5ecad28 @header={:d_tag=>0, :d_val=>0}>
|
52
|
+
# dynamic.tag_by_type('DT_PLTGOT')
|
53
|
+
# #=> #<ELFTools::Dynamic::Tag:0x0055d3d2d91b28 @header={:d_tag=>3, :d_val=>6295552}>
|
54
|
+
def tag_by_type(type)
|
55
|
+
type = Util.to_constant(Constants::DT, type)
|
56
|
+
each_tags do |tag|
|
57
|
+
return tag if tag.header.d_tag == type
|
58
|
+
end
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Get the +n+-th tag.
|
63
|
+
#
|
64
|
+
# Tags are lazy loaded.
|
65
|
+
# Notice: this method assume the following methods
|
66
|
+
# already exist:
|
67
|
+
# header
|
68
|
+
# tag_start
|
69
|
+
#
|
70
|
+
# Notice: we cannot do bound checking of +n+ here since
|
71
|
+
# the only way to get size of tags is calling +tags.size+.
|
72
|
+
# @param [Integer] n The index.
|
73
|
+
# @return [ELFTools::Dynamic::Tag] The desired tag.
|
74
|
+
def tag_at(n)
|
75
|
+
return if n < 0
|
76
|
+
@tag_at_map ||= {}
|
77
|
+
return @tag_at_map[n] if @tag_at_map[n]
|
78
|
+
dyn = ELF_Dyn.new(endian: endian)
|
79
|
+
dyn.elf_class = header.elf_class
|
80
|
+
stream.pos = tag_start + n * dyn.num_bytes
|
81
|
+
@tag_at_map[n] = Tag.new(dyn.read(stream), stream)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def endian
|
87
|
+
header.class.self_endian
|
88
|
+
end
|
89
|
+
|
90
|
+
# A tag class.
|
91
|
+
class Tag
|
92
|
+
attr_reader :header # @return [ELFTools::ELF_Dyn] The dynamic tag header.
|
93
|
+
attr_reader :stream # @return [File] Streaming object.
|
94
|
+
|
95
|
+
# Instantiate a {ELFTools::Dynamic::Tag} object.
|
96
|
+
# @param [ELF_Dyn] header The dynamic tag header.
|
97
|
+
# @param [File] stream Streaming object.
|
98
|
+
def initialize(header, stream)
|
99
|
+
@header = header
|
100
|
+
@stream = stream
|
101
|
+
end
|
102
|
+
# TODO: Get the name of tags, e.g. SONAME
|
103
|
+
# TODO: Handle (non)-PIE ELF correctly.
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|