elftools 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -15
- data/lib/elftools/constants.rb +91 -84
- data/lib/elftools/dynamic.rb +23 -24
- data/lib/elftools/elf_file.rb +25 -30
- data/lib/elftools/exceptions.rb +1 -0
- data/lib/elftools/lazy_array.rb +4 -3
- data/lib/elftools/note.rb +28 -20
- data/lib/elftools/sections/relocation_section.rb +6 -8
- data/lib/elftools/sections/section.rb +2 -2
- data/lib/elftools/sections/sections.rb +1 -1
- data/lib/elftools/sections/sym_tab_section.rb +23 -23
- data/lib/elftools/segments/segment.rb +2 -2
- data/lib/elftools/segments/segments.rb +1 -1
- data/lib/elftools/structs.rb +4 -1
- data/lib/elftools/util.rb +4 -4
- data/lib/elftools/version.rb +2 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b27e4fd08cf348de961dde3f2c606719558c031
|
4
|
+
data.tar.gz: b7822186925f38be8a76aeb9961a0484ee0cc2bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a0d0993f509e82c87c97776282057fe61ff8076018714da50ecc9c928e8b3863e7481a2ababf7ae56cb02d75dc03d5783f8d2bdf4b890b535075bed00f53bac
|
7
|
+
data.tar.gz: 591568c22193ada4c48874c276bde8cdb5c5587268f67e440c48b8968db395d9730888bd5d452e6f002e383e65e0a0dfb9bc7b6682b6e960bc84daa80f1cab15
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
[![Build Status](https://travis-ci.org/david942j/rbelftools.svg?branch=master)](https://travis-ci.org/david942j/rbelftools)
|
2
|
+
[![Build Status](https://ci.appveyor.com/api/projects/status/sq5c4gli8ir95h6k?svg=true&retina=true)](https://ci.appveyor.com/project/david942j/rbelftools)
|
2
3
|
[![Code Climate](https://codeclimate.com/github/david942j/rbelftools/badges/gpa.svg)](https://codeclimate.com/github/david942j/rbelftools)
|
3
4
|
[![Issue Count](https://codeclimate.com/github/david942j/rbelftools/badges/issue_count.svg)](https://codeclimate.com/github/david942j/rbelftools)
|
4
5
|
[![Test Coverage](https://codeclimate.com/github/david942j/rbelftools/badges/coverage.svg)](https://codeclimate.com/github/david942j/rbelftools/coverage)
|
@@ -11,7 +12,7 @@ ELF parser in pure ruby implementation. This work is inspired by [pyelftools](ht
|
|
11
12
|
|
12
13
|
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
|
|
14
|
-
**rbelftools**'s target is to create a nice ELF parser library in ruby. More features
|
15
|
+
**rbelftools**'s target is to create a nice ELF parser library in ruby. More features remain a work in progress.
|
15
16
|
|
16
17
|
# Install
|
17
18
|
|
@@ -70,7 +71,7 @@ symtab_section.num_symbols
|
|
70
71
|
|
71
72
|
symtab_section.symbol_by_name('puts@@GLIBC_2.2.5')
|
72
73
|
#=>
|
73
|
-
# #<ELFTools::Symbol:0x00560b14af67a0
|
74
|
+
# #<ELFTools::Sections::Symbol:0x00560b14af67a0
|
74
75
|
# @header={:st_name=>348, :st_info=>18, :st_other=>0, :st_shndx=>0, :st_value=>0, :st_size=>0},
|
75
76
|
# @name="puts@@GLIBC_2.2.5">
|
76
77
|
|
@@ -115,26 +116,21 @@ relocations.map { |r| symtab.symbol_at(r.symbol_index).name }
|
|
115
116
|
|
116
117
|
# Why rbelftools
|
117
118
|
|
118
|
-
1. Fully documented
|
119
|
-
|
119
|
+
1. Fully documented
|
120
120
|
Always important for an Open-Source project. Online document is [here](http://www.rubydoc.info/github/david942j/rbelftools/master/frames)
|
121
|
-
2. Fully tested
|
122
|
-
|
121
|
+
2. Fully tested
|
123
122
|
Of course.
|
124
|
-
3. Lazy loading on everything
|
125
|
-
|
123
|
+
3. Lazy loading on everything
|
126
124
|
To use **rbelftools**, only need to pass the stream object of ELF file.
|
127
125
|
**rbelftools** will read the stream object **as least times as possible** when parsing
|
128
126
|
the file. Most information will not be fetched until you need it, which makes
|
129
127
|
**rbelftools** efficient.
|
130
|
-
4. To be a library
|
131
|
-
|
132
|
-
**rbelftools** is designed to be a library for furthur usage.
|
128
|
+
4. To be a library
|
129
|
+
**rbelftools** is designed to be a library for further usage.
|
133
130
|
It will _not_ add any too trivial features.
|
134
131
|
For example, to check if NX disabled, you can use
|
135
132
|
`!elf.segment_by_type(:gnu_stack).executable?` but not `elf.nx?`
|
136
|
-
5. Section and segment parser
|
137
|
-
|
133
|
+
5. Section and segment parser
|
138
134
|
Providing common sections and segments parser. For example, .symtab, .shstrtab
|
139
135
|
.dynamic sections and INTERP, DYNAMIC segments, etc.
|
140
136
|
|
@@ -143,12 +139,12 @@ relocations.map { |r| symtab.symbol_at(r.symbol_index).name }
|
|
143
139
|
git clone https://github.com/david942j/rbelftools.git
|
144
140
|
cd rbelftools
|
145
141
|
bundle
|
146
|
-
rake
|
142
|
+
bundle exec rake
|
147
143
|
```
|
148
144
|
Any comments or suggestions are welcome!
|
149
145
|
|
150
146
|
# Cross Platform
|
151
|
-
**rbelftools** can be used
|
147
|
+
**rbelftools** can be used and has been fully tested on all platforms include Linux, OSX, and Windows!
|
152
148
|
|
153
149
|
# License
|
154
150
|
MIT License
|
data/lib/elftools/constants.rb
CHANGED
@@ -8,110 +8,117 @@ module ELFTools
|
|
8
8
|
|
9
9
|
# Section header types, records in +sh_type+.
|
10
10
|
module SHT
|
11
|
-
SHT_NULL = 0
|
12
|
-
SHT_PROGBITS = 1
|
13
|
-
SHT_SYMTAB = 2
|
14
|
-
SHT_STRTAB = 3
|
15
|
-
SHT_RELA = 4
|
16
|
-
SHT_HASH = 5
|
17
|
-
SHT_DYNAMIC = 6
|
18
|
-
SHT_NOTE = 7
|
19
|
-
SHT_NOBITS = 8
|
20
|
-
SHT_REL = 9
|
21
|
-
SHT_SHLIB = 10
|
22
|
-
SHT_DYNSYM = 11
|
23
|
-
|
11
|
+
SHT_NULL = 0 # null section
|
12
|
+
SHT_PROGBITS = 1 # information defined by program itself
|
13
|
+
SHT_SYMTAB = 2 # symbol table section
|
14
|
+
SHT_STRTAB = 3 # string table section
|
15
|
+
SHT_RELA = 4 # relocation with addends
|
16
|
+
SHT_HASH = 5 # symbol hash table
|
17
|
+
SHT_DYNAMIC = 6 # information of dynamic linking
|
18
|
+
SHT_NOTE = 7 # note section
|
19
|
+
SHT_NOBITS = 8 # section occupies no space
|
20
|
+
SHT_REL = 9 # relocation
|
21
|
+
SHT_SHLIB = 10 # reserved
|
22
|
+
SHT_DYNSYM = 11 # symbols for dynamic
|
23
|
+
# Values between {SHT_LOPROC} and {SHT_HIPROC} are reserved for processor-specific semantics.
|
24
24
|
SHT_LOPROC = 0x70000000
|
25
|
-
SHT_HIPROC = 0x7fffffff
|
25
|
+
SHT_HIPROC = 0x7fffffff # see {SHT_LOPROC}
|
26
|
+
# Values between {SHT_LOUSER} and {SHT_HIUSER} are reserved for application programs.
|
26
27
|
SHT_LOUSER = 0x80000000
|
27
|
-
SHT_HIUSER = 0xffffffff
|
28
|
+
SHT_HIUSER = 0xffffffff # see {SHT_LOUSER}
|
28
29
|
end
|
29
30
|
include SHT
|
30
31
|
|
31
32
|
# Program header types, records in +p_type+.
|
32
33
|
module PT
|
33
|
-
PT_NULL = 0
|
34
|
-
PT_LOAD = 1
|
35
|
-
PT_DYNAMIC = 2
|
36
|
-
PT_INTERP = 3
|
37
|
-
PT_NOTE = 4
|
38
|
-
PT_SHLIB = 5
|
39
|
-
PT_PHDR = 6
|
40
|
-
PT_TLS = 7 #
|
34
|
+
PT_NULL = 0 # null segment
|
35
|
+
PT_LOAD = 1 # segment to be load
|
36
|
+
PT_DYNAMIC = 2 # dynamic tags
|
37
|
+
PT_INTERP = 3 # interpreter, same as .interp section
|
38
|
+
PT_NOTE = 4 # same as .note* section
|
39
|
+
PT_SHLIB = 5 # reserved
|
40
|
+
PT_PHDR = 6 # where program header starts
|
41
|
+
PT_TLS = 7 # thread local storage segment
|
41
42
|
PT_LOOS = 0x60000000 # OS-specific
|
42
43
|
PT_HIOS = 0x6fffffff # OS-specific
|
44
|
+
# Values between {PT_LOPROC} and {PT_HIPROC} are reserved for processor-specific semantics.
|
43
45
|
PT_LOPROC = 0x70000000
|
44
|
-
PT_HIPROC = 0x7fffffff
|
45
|
-
PT_GNU_EH_FRAME = 0x6474e550
|
46
|
-
PT_GNU_STACK = 0x6474e551
|
47
|
-
PT_GNU_RELRO = 0x6474e552 #
|
46
|
+
PT_HIPROC = 0x7fffffff # see {PT_LOPROC}
|
47
|
+
PT_GNU_EH_FRAME = 0x6474e550 # for exception handler
|
48
|
+
PT_GNU_STACK = 0x6474e551 # permission of stack
|
49
|
+
PT_GNU_RELRO = 0x6474e552 # read only after relocation
|
48
50
|
end
|
49
51
|
include PT
|
50
52
|
|
51
53
|
# Dynamic table types, records in +d_tag+.
|
52
54
|
module DT
|
53
|
-
DT_NULL = 0
|
54
|
-
DT_NEEDED = 1
|
55
|
-
DT_PLTRELSZ = 2
|
56
|
-
DT_PLTGOT = 3
|
57
|
-
DT_HASH = 4
|
58
|
-
DT_STRTAB = 5
|
59
|
-
DT_SYMTAB = 6
|
60
|
-
DT_RELA = 7
|
61
|
-
DT_RELASZ = 8
|
62
|
-
DT_RELAENT = 9
|
63
|
-
DT_STRSZ = 10
|
64
|
-
DT_SYMENT = 11
|
65
|
-
DT_INIT = 12
|
66
|
-
DT_FINI = 13
|
67
|
-
DT_SONAME = 14
|
68
|
-
DT_RPATH = 15
|
69
|
-
DT_SYMBOLIC = 16
|
70
|
-
DT_REL = 17
|
71
|
-
DT_RELSZ = 18
|
72
|
-
DT_RELENT = 19
|
73
|
-
DT_PLTREL = 20
|
74
|
-
DT_DEBUG = 21
|
75
|
-
DT_TEXTREL = 22
|
76
|
-
DT_JMPREL = 23
|
77
|
-
DT_BIND_NOW = 24
|
78
|
-
DT_INIT_ARRAY = 25
|
79
|
-
DT_FINI_ARRAY = 26
|
80
|
-
DT_INIT_ARRAYSZ = 27
|
81
|
-
DT_FINI_ARRAYSZ = 28
|
82
|
-
DT_RUNPATH = 29
|
83
|
-
DT_FLAGS = 30
|
84
|
-
DT_ENCODING = 32
|
55
|
+
DT_NULL = 0 # marks the end of the _DYNAMIC array
|
56
|
+
DT_NEEDED = 1 # libraries need to be linked by loader
|
57
|
+
DT_PLTRELSZ = 2 # total size of relocation entries
|
58
|
+
DT_PLTGOT = 3 # address of procedure linkage table or global offset table
|
59
|
+
DT_HASH = 4 # address of symbol hash table
|
60
|
+
DT_STRTAB = 5 # address of string table
|
61
|
+
DT_SYMTAB = 6 # address of symbol table
|
62
|
+
DT_RELA = 7 # address of a relocation table
|
63
|
+
DT_RELASZ = 8 # total size of the {DT_RELA} table
|
64
|
+
DT_RELAENT = 9 # size of each entry in the {DT_RELA} table
|
65
|
+
DT_STRSZ = 10 # total size of {DT_STRTAB}
|
66
|
+
DT_SYMENT = 11 # size of each entry in {DT_SYMTAB}
|
67
|
+
DT_INIT = 12 # where the initialization function is
|
68
|
+
DT_FINI = 13 # where the termination function is
|
69
|
+
DT_SONAME = 14 # the shared object name
|
70
|
+
DT_RPATH = 15 # has been superseded by {DT_RUNPATH}
|
71
|
+
DT_SYMBOLIC = 16 # has been superseded by the DF_SYMBOLIC flag
|
72
|
+
DT_REL = 17 # similar to {DT_RELA}
|
73
|
+
DT_RELSZ = 18 # total size of the {DT_REL} table
|
74
|
+
DT_RELENT = 19 # size of each entry in the {DT_REL} table
|
75
|
+
DT_PLTREL = 20 # type of relocation entry, either {DT_REL} or {DT_RELA}
|
76
|
+
DT_DEBUG = 21 # for debugging
|
77
|
+
DT_TEXTREL = 22 # has been superseded by the DF_TEXTREL flag
|
78
|
+
DT_JMPREL = 23 # address of relocation entries that are associated solely with the procedure linkage table
|
79
|
+
DT_BIND_NOW = 24 # if the loader needs to do relocate now, superseded by the DF_BIND_NOW flag
|
80
|
+
DT_INIT_ARRAY = 25 # address init array
|
81
|
+
DT_FINI_ARRAY = 26 # address of fini array
|
82
|
+
DT_INIT_ARRAYSZ = 27 # total size of init array
|
83
|
+
DT_FINI_ARRAYSZ = 28 # total size of fini array
|
84
|
+
DT_RUNPATH = 29 # path of libraries for searching
|
85
|
+
DT_FLAGS = 30 # flags
|
86
|
+
DT_ENCODING = 32 # just a lower bound
|
87
|
+
# Values between {DT_LOOS} and {DT_HIOS} are reserved for operating system-specific semantics.
|
85
88
|
DT_LOOS = 0x6000000d
|
86
|
-
DT_HIOS = 0x6ffff000
|
89
|
+
DT_HIOS = 0x6ffff000 # see {DT_LOOS}
|
90
|
+
# Values between {DT_VALRNGLO} and {DT_VALRNGHI} use the +d_un.d_val+ field of the dynamic structure.
|
87
91
|
DT_VALRNGLO = 0x6ffffd00
|
88
|
-
DT_VALRNGHI = 0x6ffffdff
|
92
|
+
DT_VALRNGHI = 0x6ffffdff # see {DT_VALRNGLO}
|
93
|
+
# Values between {DT_ADDRRNGLO} and {DT_ADDRRNGHI} use the +d_un.d_ptr+ field of the dynamic structure.
|
89
94
|
DT_ADDRRNGLO = 0x6ffffe00
|
90
|
-
|
91
|
-
|
92
|
-
DT_RELACOUNT = 0x6ffffff9
|
93
|
-
DT_RELCOUNT = 0x6ffffffa
|
94
|
-
DT_FLAGS_1 = 0x6ffffffb
|
95
|
-
DT_VERDEF = 0x6ffffffc
|
96
|
-
DT_VERDEFNUM = 0x6ffffffd
|
97
|
-
DT_VERNEED = 0x6ffffffe
|
98
|
-
DT_VERNEEDNUM = 0x6fffffff
|
95
|
+
DT_GNU_HASH = 0x6ffffef5 # the gnu hash
|
96
|
+
DT_ADDRRNGHI = 0x6ffffeff # see {DT_ADDRRNGLO}
|
97
|
+
DT_RELACOUNT = 0x6ffffff9 # relative relocation count
|
98
|
+
DT_RELCOUNT = 0x6ffffffa # relative relocation count
|
99
|
+
DT_FLAGS_1 = 0x6ffffffb # flags
|
100
|
+
DT_VERDEF = 0x6ffffffc # address of version definition table
|
101
|
+
DT_VERDEFNUM = 0x6ffffffd # number of entries in {DT_VERDEF}
|
102
|
+
DT_VERNEED = 0x6ffffffe # address of version dependency table
|
103
|
+
DT_VERNEEDNUM = 0x6fffffff # number of entries in {DT_VERNEED}
|
104
|
+
# Values between {DT_LOPROC} and {DT_HIPROC} are reserved for processor-specific semantics.
|
99
105
|
DT_LOPROC = 0x70000000
|
100
|
-
DT_HIPROC = 0x7fffffff
|
106
|
+
DT_HIPROC = 0x7fffffff # see {DT_LOPROC}
|
101
107
|
end
|
102
108
|
include DT
|
103
109
|
|
104
110
|
# These constants define the various ELF target machines.
|
105
111
|
module EM
|
106
|
-
EM_NONE = 0
|
107
|
-
EM_M32 = 1
|
108
|
-
EM_SPARC = 2
|
109
|
-
EM_386 = 3
|
110
|
-
EM_68K = 4
|
111
|
-
EM_88K = 5
|
112
|
-
EM_486 = 6 #
|
113
|
-
EM_860 = 7
|
112
|
+
EM_NONE = 0 # none
|
113
|
+
EM_M32 = 1 # AT&T WE 32100
|
114
|
+
EM_SPARC = 2 # SPARC
|
115
|
+
EM_386 = 3 # Intel 80386
|
116
|
+
EM_68K = 4 # Motorola 68000
|
117
|
+
EM_88K = 5 # Motorola 88000
|
118
|
+
EM_486 = 6 # Intel 80486
|
119
|
+
EM_860 = 7 # Intel 80860
|
114
120
|
EM_MIPS = 8 # MIPS R3000 (officially, big-endian only)
|
121
|
+
|
115
122
|
# Next two are historical and binaries and
|
116
123
|
# modules of these types will be rejected by Linux.
|
117
124
|
EM_MIPS_RS3_LE = 10 # MIPS R3000 little-endian
|
@@ -190,11 +197,11 @@ module ELFTools
|
|
190
197
|
|
191
198
|
# This module defines elf file types.
|
192
199
|
module ET
|
193
|
-
ET_NONE = 0
|
194
|
-
ET_REL = 1
|
195
|
-
ET_EXEC = 2
|
196
|
-
ET_DYN = 3
|
197
|
-
ET_CORE = 4
|
200
|
+
ET_NONE = 0 # no file type
|
201
|
+
ET_REL = 1 # relocatable file
|
202
|
+
ET_EXEC = 2 # executable file
|
203
|
+
ET_DYN = 3 # shared object
|
204
|
+
ET_CORE = 4 # core file
|
198
205
|
# Return the type name according to +e_type+ in ELF file header.
|
199
206
|
# @return [String] Type in string format.
|
200
207
|
def self.mapping(type)
|
data/lib/elftools/dynamic.rb
CHANGED
@@ -1,28 +1,26 @@
|
|
1
1
|
module ELFTools
|
2
|
-
# Define common methods for dynamic sections and
|
3
|
-
# dynamic segments.
|
2
|
+
# Define common methods for dynamic sections and dynamic segments.
|
4
3
|
#
|
5
|
-
#
|
6
|
-
# {ELFTools::Sections::DynamicSection}
|
7
|
-
# {ELFTools::Segments::DynamicSegment} because
|
8
|
-
#
|
4
|
+
# @note
|
5
|
+
# This module can only be included by {ELFTools::Sections::DynamicSection}
|
6
|
+
# and {ELFTools::Segments::DynamicSegment} because methods here assume some
|
7
|
+
# attributes exist.
|
9
8
|
module Dynamic
|
10
9
|
# Iterate all tags.
|
11
10
|
#
|
12
|
-
#
|
13
|
-
# already exist:
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# @
|
11
|
+
# @note
|
12
|
+
# This method assume the following methods already exist:
|
13
|
+
# header
|
14
|
+
# tag_start
|
15
|
+
# @yieldparam [ELFTools::Dynamic::Tag] tag
|
17
16
|
# @return [Enumerator<ELFTools::Dynamic::Tag>, Array<ELFTools::Dynamic::Tag>]
|
18
17
|
# If block is not given, an enumerator will be returned.
|
19
18
|
# Otherwise, return array of tags.
|
20
|
-
def each_tags
|
19
|
+
def each_tags(&block)
|
21
20
|
return enum_for(:each_tags) unless block_given?
|
22
21
|
arr = []
|
23
22
|
0.step do |i|
|
24
|
-
tag = tag_at(i)
|
25
|
-
yield tag
|
23
|
+
tag = tag_at(i).tap(&block)
|
26
24
|
arr << tag
|
27
25
|
break if tag.header.d_tag == ELFTools::Constants::DT_NULL
|
28
26
|
end
|
@@ -68,13 +66,13 @@ module ELFTools
|
|
68
66
|
# Get the +n+-th tag.
|
69
67
|
#
|
70
68
|
# Tags are lazy loaded.
|
71
|
-
#
|
72
|
-
# already exist:
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
69
|
+
# @note
|
70
|
+
# This method assume the following methods already exist:
|
71
|
+
# header
|
72
|
+
# tag_start
|
73
|
+
# @note
|
74
|
+
# We cannot do bound checking of +n+ here since the only way to get size
|
75
|
+
# of tags is calling +tags.size+.
|
78
76
|
# @param [Integer] n The index.
|
79
77
|
# @return [ELFTools::Dynamic::Tag] The desired tag.
|
80
78
|
def tag_at(n)
|
@@ -102,11 +100,11 @@ module ELFTools
|
|
102
100
|
# A tag class.
|
103
101
|
class Tag
|
104
102
|
attr_reader :header # @return [ELFTools::Structs::ELF_Dyn] The dynamic tag header.
|
105
|
-
attr_reader :stream # @return [
|
103
|
+
attr_reader :stream # @return [#pos=, #read] Streaming object.
|
106
104
|
|
107
105
|
# Instantiate a {ELFTools::Dynamic::Tag} object.
|
108
106
|
# @param [ELF_Dyn] header The dynamic tag header.
|
109
|
-
# @param [
|
107
|
+
# @param [#pos=, #read] stream Streaming object.
|
110
108
|
# @param [Method] str_offset
|
111
109
|
# Call this method to get the string offset related
|
112
110
|
# to file.
|
@@ -116,6 +114,7 @@ module ELFTools
|
|
116
114
|
@str_offset = str_offset
|
117
115
|
end
|
118
116
|
|
117
|
+
# Some dynamic have name.
|
119
118
|
TYPE_WITH_NAME = [Constants::DT_NEEDED,
|
120
119
|
Constants::DT_SONAME,
|
121
120
|
Constants::DT_RPATH,
|
@@ -150,7 +149,7 @@ module ELFTools
|
|
150
149
|
#
|
151
150
|
# Only tags with name would return a name.
|
152
151
|
# Others would return +nil+.
|
153
|
-
# @return [String,
|
152
|
+
# @return [String, nil] The name.
|
154
153
|
def name
|
155
154
|
return nil unless name?
|
156
155
|
Util.cstring(stream, @str_offset.call + header.d_val.to_i)
|
data/lib/elftools/elf_file.rb
CHANGED
@@ -8,13 +8,13 @@ require 'elftools/structs'
|
|
8
8
|
module ELFTools
|
9
9
|
# The main class for using elftools.
|
10
10
|
class ELFFile
|
11
|
-
attr_reader :stream # @return [
|
11
|
+
attr_reader :stream # @return [#pos=, #read] The +File+ object.
|
12
12
|
attr_reader :elf_class # @return [Integer] 32 or 64.
|
13
13
|
attr_reader :endian # @return [Symbol] +:little+ or +:big+.
|
14
14
|
|
15
15
|
# Instantiate an {ELFFile} object.
|
16
16
|
#
|
17
|
-
# @param [
|
17
|
+
# @param [#pos=, #read] stream
|
18
18
|
# The +File+ object to be fetch information from.
|
19
19
|
# @example
|
20
20
|
# ELFFile.new(File.open('/bin/cat'))
|
@@ -27,7 +27,7 @@ module ELFTools
|
|
27
27
|
# Return the file header.
|
28
28
|
#
|
29
29
|
# Lazy loading.
|
30
|
-
# @
|
30
|
+
# @return [ELFTools::Structs::ELF_Ehdr] The header.
|
31
31
|
def header
|
32
32
|
return @header if defined?(@header)
|
33
33
|
stream.pos = 0
|
@@ -37,7 +37,7 @@ module ELFTools
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# Return the BuildID of ELF.
|
40
|
-
# @return [String,
|
40
|
+
# @return [String, nil]
|
41
41
|
# BuildID in hex form will be returned.
|
42
42
|
# +nil+ is returned if the .note.gnu.build-id section
|
43
43
|
# is not found.
|
@@ -52,7 +52,7 @@ module ELFTools
|
|
52
52
|
note.desc.unpack('H*').first
|
53
53
|
end
|
54
54
|
|
55
|
-
# Get
|
55
|
+
# Get machine architecture.
|
56
56
|
#
|
57
57
|
# Mappings of architecture can be found
|
58
58
|
# in {ELFTools::Constants::EM.mapping}.
|
@@ -89,7 +89,7 @@ module ELFTools
|
|
89
89
|
|
90
90
|
# Acquire the section named as +name+.
|
91
91
|
# @param [String] name The desired section name.
|
92
|
-
# @return [ELFTools::Sections::Section,
|
92
|
+
# @return [ELFTools::Sections::Section, nil] The target section.
|
93
93
|
# @example
|
94
94
|
# elf.section_by_name('.note.gnu.build-id')
|
95
95
|
# #=> #<ELFTools::Sections::Section:0x005647b1282428>
|
@@ -107,17 +107,15 @@ module ELFTools
|
|
107
107
|
# only be created whenever accessing it.
|
108
108
|
# This method is useful for {#section_by_name}
|
109
109
|
# since not all sections need to be created.
|
110
|
-
# @
|
111
|
-
#
|
110
|
+
# @yieldparam [ELFTools::Sections::Section] section A section.
|
111
|
+
# @yieldreturn [void]
|
112
112
|
# @return [Enumerator<ELFTools::Sections::Section>, Array<ELFTools::Sections::Section>]
|
113
113
|
# As +Array#each+, if block is not given, a enumerator will be returned,
|
114
114
|
# otherwise, the whole sections will be returned.
|
115
|
-
def each_sections
|
115
|
+
def each_sections(&block)
|
116
116
|
return enum_for(:each_sections) unless block_given?
|
117
117
|
Array.new(num_sections) do |i|
|
118
|
-
|
119
|
-
yield sec
|
120
|
-
sec
|
118
|
+
section_at(i).tap(&block)
|
121
119
|
end
|
122
120
|
end
|
123
121
|
|
@@ -132,7 +130,7 @@ module ELFTools
|
|
132
130
|
#
|
133
131
|
# Sections are lazy loaded.
|
134
132
|
# @param [Integer] n The index.
|
135
|
-
# @return [ELFTools::Sections::Section,
|
133
|
+
# @return [ELFTools::Sections::Section, nil]
|
136
134
|
# The target section.
|
137
135
|
# If +n+ is out of bound, +nil+ is returned.
|
138
136
|
def section_at(n)
|
@@ -142,13 +140,12 @@ module ELFTools
|
|
142
140
|
|
143
141
|
# Fetch all sections with specific type.
|
144
142
|
#
|
145
|
-
# The available types are listed in {ELFTools::Constants}
|
146
|
-
# start with +SHT_+.
|
143
|
+
# The available types are listed in {ELFTools::Constants::PT}.
|
147
144
|
# This method accept giving block.
|
148
145
|
# @param [Integer, Symbol, String] type
|
149
146
|
# The type needed, similar format as {#segment_by_type}.
|
150
|
-
# @
|
151
|
-
#
|
147
|
+
# @yieldparam [ELFTools::Sections::Section] section A section in specific type.
|
148
|
+
# @yieldreturn [void]
|
152
149
|
# @return [Array<ELFTools::Sections::section>] The target sections.
|
153
150
|
# @example
|
154
151
|
# elf = ELFTools::ELFFile.new(File.open('spec/files/amd64.elf'))
|
@@ -183,16 +180,14 @@ module ELFTools
|
|
183
180
|
# only be created whenever accessing it.
|
184
181
|
# This method is useful for {#segment_by_type}
|
185
182
|
# since not all segments need to be created.
|
186
|
-
# @
|
187
|
-
#
|
183
|
+
# @yieldparam [ELFTools::Segments::Segment] segment A segment.
|
184
|
+
# @yieldreturn [void]
|
188
185
|
# @return [Array<ELFTools::Segments::Segment>]
|
189
186
|
# Whole segments will be returned.
|
190
|
-
def each_segments
|
187
|
+
def each_segments(&block)
|
191
188
|
return enum_for(:each_segments) unless block_given?
|
192
189
|
Array.new(num_segments) do |i|
|
193
|
-
|
194
|
-
yield seg
|
195
|
-
seg
|
190
|
+
segment_at(i).tap(&block)
|
196
191
|
end
|
197
192
|
end
|
198
193
|
|
@@ -204,11 +199,11 @@ module ELFTools
|
|
204
199
|
end
|
205
200
|
|
206
201
|
# Get the first segment with +p_type=type+.
|
207
|
-
# The available types are listed in {ELFTools::Constants}
|
208
|
-
# start with +PT_+.
|
202
|
+
# The available types are listed in {ELFTools::Constants::PT}.
|
209
203
|
#
|
210
|
-
#
|
211
|
-
#
|
204
|
+
# @note
|
205
|
+
# This method will return the first segment found,
|
206
|
+
# to found all segments with specific type you can use {#segments_by_type}.
|
212
207
|
# @param [Integer, Symbol, String] type
|
213
208
|
# See examples for clear usage.
|
214
209
|
# @return [ELFTools::Segments::Segment] The target segment.
|
@@ -256,8 +251,8 @@ module ELFTools
|
|
256
251
|
# This method accept giving block.
|
257
252
|
# @param [Integer, Symbol, String] type
|
258
253
|
# The type needed, same format as {#segment_by_type}.
|
259
|
-
# @
|
260
|
-
#
|
254
|
+
# @yieldparam [ELFTools::Segments::Segment] segment A segment in specific type.
|
255
|
+
# @yieldreturn [void]
|
261
256
|
# @return [Array<ELFTools::Segments::Segment>] The target segments.
|
262
257
|
def segments_by_type(type, &block)
|
263
258
|
type = Util.to_constant(Constants::PT, type)
|
@@ -268,7 +263,7 @@ module ELFTools
|
|
268
263
|
#
|
269
264
|
# Segments are lazy loaded.
|
270
265
|
# @param [Integer] n The index.
|
271
|
-
# @return [ELFTools::Segments::Segment,
|
266
|
+
# @return [ELFTools::Segments::Segment, nil]
|
272
267
|
# The target segment.
|
273
268
|
# If +n+ is out of bound, +nil+ is returned.
|
274
269
|
def segment_at(n)
|
data/lib/elftools/exceptions.rb
CHANGED
data/lib/elftools/lazy_array.rb
CHANGED
@@ -7,9 +7,10 @@ module ELFTools
|
|
7
7
|
# Instantiate a {LazyArray} object.
|
8
8
|
# @param [Integer] size
|
9
9
|
# The size of array.
|
10
|
-
# @
|
11
|
-
#
|
12
|
-
#
|
10
|
+
# @yieldparam [Integer] i
|
11
|
+
# Needs +i+-th element.
|
12
|
+
# @yieldreturn [Object]
|
13
|
+
# Value of the +i+-th element.
|
13
14
|
# @example
|
14
15
|
# arr = LazyArray.new(10) { |i| p i; i * i }
|
15
16
|
# p arr[2]
|
data/lib/elftools/note.rb
CHANGED
@@ -2,17 +2,18 @@ require 'elftools/structs'
|
|
2
2
|
require 'elftools/util'
|
3
3
|
|
4
4
|
module ELFTools
|
5
|
-
# Since both note sections and note segments
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# Since both note sections and note segments refer to notes, this module
|
6
|
+
# defines common methods for {ELFTools::Sections::NoteSection} and
|
7
|
+
# {ELFTools::Segments::NoteSegment}.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
9
|
+
# @note
|
10
|
+
# This module can only be included in {ELFTools::Sections::NoteSection} and
|
11
|
+
# {ELFTools::Segments::NoteSegment} since some methods here assume some
|
12
|
+
# attributes already exist.
|
12
13
|
module Note
|
13
|
-
# Since size of {ELFTools::Structs::ELF_Nhdr} will not change no
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# Since size of {ELFTools::Structs::ELF_Nhdr} will not change no matter in
|
15
|
+
# what endian and what arch, we can do this here. This value should equal
|
16
|
+
# to 12.
|
16
17
|
SIZE_OF_NHDR = Structs::ELF_Nhdr.new(endian: :little).num_bytes
|
17
18
|
|
18
19
|
# Iterate all notes in a note section or segment.
|
@@ -30,13 +31,16 @@ module ELFTools
|
|
30
31
|
# | ... |
|
31
32
|
# +---------------+
|
32
33
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
34
|
+
# @note
|
35
|
+
# This method assume following methods exist:
|
36
|
+
# stream
|
37
|
+
# note_start
|
38
|
+
# note_total_size
|
39
|
+
# @return [Enumerator<ELFTools::Note::Note>, Array<ELFTools::Note::Note>]
|
40
|
+
# If block is not given, an enumerator will be returned.
|
41
|
+
# Otherwise, return the array of notes.
|
39
42
|
def each_notes
|
43
|
+
return enum_for(:each_notes) unless block_given?
|
40
44
|
@notes_offset_map ||= {}
|
41
45
|
cur = note_start
|
42
46
|
notes = []
|
@@ -49,19 +53,23 @@ module ELFTools
|
|
49
53
|
desc_size = Util.align(note.header.n_descsz, 2)
|
50
54
|
cur += SIZE_OF_NHDR + name_size + desc_size
|
51
55
|
notes << note
|
52
|
-
yield note
|
56
|
+
yield note
|
53
57
|
end
|
54
58
|
notes
|
55
59
|
end
|
56
60
|
|
57
61
|
# Simply +#notes+ to get all notes.
|
58
|
-
|
62
|
+
# @return [Array<ELFTools::Note::Note>]
|
63
|
+
# Whole notes.
|
64
|
+
def notes
|
65
|
+
each_notes.to_a
|
66
|
+
end
|
59
67
|
|
60
68
|
private
|
61
69
|
|
62
70
|
# Get the endian.
|
63
71
|
#
|
64
|
-
#
|
72
|
+
# @note This method assume method +header+ exists.
|
65
73
|
# @return [Symbol] +:little+ or +:big+.
|
66
74
|
def endian
|
67
75
|
header.class.self_endian
|
@@ -75,12 +83,12 @@ module ELFTools
|
|
75
83
|
# Class of a note.
|
76
84
|
class Note
|
77
85
|
attr_reader :header # @return [ELFTools::Structs::ELF_Nhdr] Note header.
|
78
|
-
attr_reader :stream # @return [
|
86
|
+
attr_reader :stream # @return [#pos=, #read] Streaming object.
|
79
87
|
attr_reader :offset # @return [Integer] Address of this note start, includes note header.
|
80
88
|
|
81
89
|
# Instantiate a {ELFTools::Note::Note} object.
|
82
90
|
# @param [ELF_Nhdr] header The note header.
|
83
|
-
# @param [
|
91
|
+
# @param [#pos=, #read] stream Streaming object.
|
84
92
|
# @param [Integer] offset
|
85
93
|
# Start address of this note, includes the header.
|
86
94
|
def initialize(header, stream, offset)
|
@@ -23,7 +23,7 @@ module ELFTools
|
|
23
23
|
#
|
24
24
|
# relocations are lazy loaded.
|
25
25
|
# @param [Integer] n The index.
|
26
|
-
# @return [ELFTools::Relocation,
|
26
|
+
# @return [ELFTools::Relocation, nil]
|
27
27
|
# The target relocation.
|
28
28
|
# If +n+ is out of bound, +nil+ is returned.
|
29
29
|
def relocation_at(n)
|
@@ -35,17 +35,15 @@ module ELFTools
|
|
35
35
|
#
|
36
36
|
# All relocations are lazy loading, the relocation
|
37
37
|
# only be created whenever accessing it.
|
38
|
-
# @
|
39
|
-
#
|
38
|
+
# @yieldparam [ELFTools::Relocation] rel A relocation object.
|
39
|
+
# @yieldreturn [void]
|
40
40
|
# @return [Enumerator<ELFTools::Relocation>, Array<ELFTools::Relocation>]
|
41
41
|
# If block is not given, an enumerator will be returned.
|
42
42
|
# Otherwise, the whole relocations will be returned.
|
43
|
-
def each_relocations
|
43
|
+
def each_relocations(&block)
|
44
44
|
return enum_for(:each_relocations) unless block_given?
|
45
45
|
Array.new(num_relocations) do |i|
|
46
|
-
|
47
|
-
yield rel
|
48
|
-
rel
|
46
|
+
relocation_at(i).tap(&block)
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -75,7 +73,7 @@ module ELFTools
|
|
75
73
|
# XXX: move this to an independent file?
|
76
74
|
class Relocation
|
77
75
|
attr_reader :header # @return [ELFTools::Structs::ELF_Rel, ELFTools::Structs::ELF_Rela] Rel(a) header.
|
78
|
-
attr_reader :stream # @return [
|
76
|
+
attr_reader :stream # @return [#pos=, #read] Streaming object.
|
79
77
|
|
80
78
|
# Instantiate a {Relocation} object.
|
81
79
|
def initialize(header, stream)
|
@@ -4,12 +4,12 @@ module ELFTools
|
|
4
4
|
# Base class of sections.
|
5
5
|
class Section
|
6
6
|
attr_reader :header # @return [ELFTools::Structs::ELF_Shdr] Section header.
|
7
|
-
attr_reader :stream # @return [
|
7
|
+
attr_reader :stream # @return [#pos=, #read] Streaming object.
|
8
8
|
|
9
9
|
# Instantiate a {Section} object.
|
10
10
|
# @param [ELFTools::Structs::ELF_Shdr] header
|
11
11
|
# The section header object.
|
12
|
-
# @param [
|
12
|
+
# @param [#pos=, #read] stream
|
13
13
|
# The streaming object for further dump.
|
14
14
|
# @param [ELFTools::Sections::StrTabSection, Proc] strtab
|
15
15
|
# The string table object. For fetching section names.
|
@@ -16,7 +16,7 @@ module ELFTools
|
|
16
16
|
class << Section
|
17
17
|
# Use different class according to +header.sh_type+.
|
18
18
|
# @param [ELFTools::Structs::ELF_Shdr] header Section header.
|
19
|
-
# @param [
|
19
|
+
# @param [#pos=, #read] stream Streaming object.
|
20
20
|
# @return [ELFTools::Sections::Section]
|
21
21
|
# Return object dependes on +header.sh_type+.
|
22
22
|
def create(header, stream, *args)
|
@@ -11,15 +11,14 @@ module ELFTools
|
|
11
11
|
# to easily fetch other sections.
|
12
12
|
# @param [ELFTools::Structs::ELF_Shdr] header
|
13
13
|
# See {Section#initialize} for more information.
|
14
|
-
# @param [
|
14
|
+
# @param [#pos=, #read] stream
|
15
15
|
# See {Section#initialize} for more information.
|
16
16
|
# @param [Proc] section_at
|
17
17
|
# The method for fetching other sections by index.
|
18
18
|
# This lambda should be {ELFTools::ELFFile#section_at}.
|
19
|
-
def initialize(header, stream, section_at: nil, **
|
19
|
+
def initialize(header, stream, section_at: nil, **_kwargs)
|
20
20
|
@section_at = section_at
|
21
21
|
# For faster #symbol_by_name
|
22
|
-
@symbol_name_map = {}
|
23
22
|
super
|
24
23
|
end
|
25
24
|
|
@@ -36,7 +35,7 @@ module ELFTools
|
|
36
35
|
#
|
37
36
|
# Symbols are lazy loaded.
|
38
37
|
# @param [Integer] n The index.
|
39
|
-
# @return [ELFTools::Symbol,
|
38
|
+
# @return [ELFTools::Sections::Symbol, nil]
|
40
39
|
# The target symbol.
|
41
40
|
# If +n+ is out of bound, +nil+ is returned.
|
42
41
|
def symbol_at(n)
|
@@ -50,30 +49,31 @@ module ELFTools
|
|
50
49
|
# only be created whenever accessing it.
|
51
50
|
# This method is useful for {#symbol_by_name}
|
52
51
|
# since not all symbols need to be created.
|
53
|
-
# @
|
54
|
-
#
|
55
|
-
# @return [Array<ELFTools::
|
56
|
-
#
|
57
|
-
|
52
|
+
# @yieldparam [ELFTools::Sections::Symbol] sym A symbol object.
|
53
|
+
# @yieldreturn [void]
|
54
|
+
# @return [Enumerator<ELFTools::Sections::Symbol>, Array<ELFTools::Sections::Symbol>]
|
55
|
+
# If block is not given, an enumerator will be returned.
|
56
|
+
# Otherwise return array of symbols.
|
57
|
+
def each_symbols(&block)
|
58
|
+
return enum_for(:each_symbols) unless block_given?
|
58
59
|
Array.new(num_symbols) do |i|
|
59
|
-
|
60
|
-
block_given? ? yield(sym) : sym
|
60
|
+
symbol_at(i).tap(&block)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
|
64
|
+
# Simply use {#symbols} to get all symbols.
|
65
|
+
# @return [Array<ELFTools::Sections::Symbol>]
|
66
|
+
# The whole symbols.
|
67
|
+
def symbols
|
68
|
+
each_symbols.to_a
|
69
|
+
end
|
65
70
|
|
66
|
-
# Get symbol by
|
71
|
+
# Get symbol by its name.
|
67
72
|
# @param [String] name
|
68
73
|
# The name of symbol.
|
69
|
-
# @return [ELFTools::Symbol] Desired symbol.
|
74
|
+
# @return [ELFTools::Sections::Symbol] Desired symbol.
|
70
75
|
def symbol_by_name(name)
|
71
|
-
|
72
|
-
each_symbols do |symbol|
|
73
|
-
@symbol_name_map[symbol.name] = symbol
|
74
|
-
return symbol if symbol.name == name
|
75
|
-
end
|
76
|
-
nil
|
76
|
+
each_symbols.find { |symbol| symbol.name == name }
|
77
77
|
end
|
78
78
|
|
79
79
|
# Return the symbol string section.
|
@@ -98,12 +98,12 @@ module ELFTools
|
|
98
98
|
# XXX: Should this class be defined in an independent file?
|
99
99
|
class Symbol
|
100
100
|
attr_reader :header # @return [ELFTools::Structs::ELF32_sym, ELFTools::Structs::ELF64_sym] Section header.
|
101
|
-
attr_reader :stream # @return [
|
101
|
+
attr_reader :stream # @return [#pos=, #read] Streaming object.
|
102
102
|
|
103
|
-
# Instantiate a {ELFTools::Symbol} object.
|
103
|
+
# Instantiate a {ELFTools::Sections::Symbol} object.
|
104
104
|
# @param [ELFTools::Structs::ELF32_sym, ELFTools::Structs::ELF64_sym] header
|
105
105
|
# The symbol header.
|
106
|
-
# @param [
|
106
|
+
# @param [#pos=, #read] stream The streaming object.
|
107
107
|
# @param [ELFTools::Sections::StrTabSection, Proc] symstr
|
108
108
|
# The symbol string section.
|
109
109
|
# If +Proc+ is given, it will be called at the first time
|
@@ -3,12 +3,12 @@ module ELFTools
|
|
3
3
|
# Base class of segments.
|
4
4
|
class Segment
|
5
5
|
attr_reader :header # @return [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] Program header.
|
6
|
-
attr_reader :stream # @return [
|
6
|
+
attr_reader :stream # @return [#pos=, #read] Streaming object.
|
7
7
|
|
8
8
|
# Instantiate a {Segment} object.
|
9
9
|
# @param [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] header
|
10
10
|
# Program header.
|
11
|
-
# @param [
|
11
|
+
# @param [#pos=, #read] stream
|
12
12
|
# Streaming object.
|
13
13
|
# @param [Method] offset_from_vma
|
14
14
|
# The method to get offset of file, given virtual memory address.
|
@@ -13,7 +13,7 @@ module ELFTools
|
|
13
13
|
class << Segment
|
14
14
|
# Use different class according to +header.p_type+.
|
15
15
|
# @param [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] header Program header of a segment.
|
16
|
-
# @param [
|
16
|
+
# @param [#pos=, #read] stream Streaming object.
|
17
17
|
# @return [ELFTools::Segments::Segment]
|
18
18
|
# Return object dependes on +header.p_type+.
|
19
19
|
def create(header, stream, *args)
|
data/lib/elftools/structs.rb
CHANGED
@@ -8,6 +8,7 @@ module ELFTools
|
|
8
8
|
module Structs
|
9
9
|
# The base structure to define common methods.
|
10
10
|
class ELFStruct < BinData::Record
|
11
|
+
# DRY. Many fields have different type in different arch.
|
11
12
|
CHOICE_SIZE_T = {
|
12
13
|
selection: :elf_class, choices: { 32 => :uint32, 64 => :uint64 }
|
13
14
|
}.freeze
|
@@ -15,7 +16,7 @@ module ELFTools
|
|
15
16
|
attr_accessor :elf_class # @return [Integer] 32 or 64.
|
16
17
|
|
17
18
|
# Hacking to get endian of current class
|
18
|
-
# @return [Symbol,
|
19
|
+
# @return [Symbol, nil] +:little+ or +:big+.
|
19
20
|
def self.self_endian
|
20
21
|
bindata_name[-2..-1] == 'ge' ? :big : :little
|
21
22
|
end
|
@@ -89,6 +90,7 @@ module ELFTools
|
|
89
90
|
uint64 :p_memsz
|
90
91
|
uint64 :p_align
|
91
92
|
end
|
93
|
+
# Get program header class according to bits.
|
92
94
|
ELF_Phdr = {
|
93
95
|
32 => ELF32_Phdr,
|
94
96
|
64 => ELF64_Phdr
|
@@ -115,6 +117,7 @@ module ELFTools
|
|
115
117
|
uint64 :st_value # Value of the symbol
|
116
118
|
uint64 :st_size # Associated symbol size
|
117
119
|
end
|
120
|
+
# Get symbol header class according to bits.
|
118
121
|
ELF_sym = {
|
119
122
|
32 => ELF32_sym,
|
120
123
|
64 => ELF64_sym
|
data/lib/elftools/util.rb
CHANGED
@@ -47,7 +47,7 @@ module ELFTools
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# Read from stream until reach a null-byte.
|
50
|
-
# @param [
|
50
|
+
# @param [#pos=, #read] stream Streaming object
|
51
51
|
# @param [Integer] offset Start from here.
|
52
52
|
# @return [String] Result string will never contain null byte.
|
53
53
|
# @example
|
@@ -80,9 +80,9 @@ module ELFTools
|
|
80
80
|
# The return value will be objects in +enum+ with attribute
|
81
81
|
# +.type+ equals to +type+.
|
82
82
|
def select_by_type(enum, type)
|
83
|
-
enum.select do |
|
84
|
-
if
|
85
|
-
yield
|
83
|
+
enum.select do |obj|
|
84
|
+
if obj.type == type
|
85
|
+
yield obj if block_given?
|
86
86
|
true
|
87
87
|
end
|
88
88
|
end
|
data/lib/elftools/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elftools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- david942j
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bindata
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.6'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.9'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.9'
|
97
111
|
description: |2
|
98
112
|
A light weight ELF parser. elftools is designed to be a low-level ELF parser.
|
99
113
|
Inspired by https://github.com/eliben/pyelftools.
|