ruby-elf 1.0.7 → 1.0.8
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.
- data/README.md +64 -0
- data/lib/elf.rb +1 -1
- data/ruby-elf.gemspec +29 -0
- metadata +38 -74
- data/bin/cowstats +0 -266
- data/bin/elfgrep +0 -246
- data/bin/missingstatic +0 -113
- data/bin/rbelf-nm +0 -113
- data/bin/rbelf-read +0 -146
- data/bin/rbelf-size +0 -184
- data/bin/verify-lfs +0 -125
- data/extras/README.extras +0 -5
- data/extras/bindings-parsers.rb +0 -157
- data/manpages/cowstats.1.xml +0 -234
- data/manpages/elfgrep.1.xml +0 -423
- data/manpages/missingstatic.1.xml +0 -290
- data/manpages/rbelf-nm.1.xml +0 -339
- data/manpages/rbelf-size.1.xml +0 -345
- data/manpages/verify-lfs.1.xml +0 -136
- data/tools/link-collisions/known-broken +0 -154
- data/tools/link-collisions/multimplementations +0 -170
- data/tools/link-collisions/suppressions +0 -287
data/bin/elfgrep
DELETED
@@ -1,246 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# -*- mode: ruby; coding: utf-8 -*-
|
3
|
-
# Copyright © 2011 Diego Elio Pettenò <flameeyes@flameeyes.eu>
|
4
|
-
#
|
5
|
-
# This program is free software; you can redistribute it and/or modify
|
6
|
-
# it under the terms of the GNU General Public License as published by
|
7
|
-
# the Free Software Foundation; either version 2 of the License, or
|
8
|
-
# (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This program is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
-
# GNU General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU General Public License
|
16
|
-
# along with this generator; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
require 'elf/tools'
|
20
|
-
|
21
|
-
module Elf::Tools
|
22
|
-
class ElfGrep < Elf::Tool
|
23
|
-
def self.initialize
|
24
|
-
super
|
25
|
-
|
26
|
-
@options |= [
|
27
|
-
# Expression to match on the symbol name
|
28
|
-
["--regexp", "-e", GetoptLong::REQUIRED_ARGUMENT],
|
29
|
-
# Append the version information when matching the symbol
|
30
|
-
# name
|
31
|
-
["--match-version", "-V", GetoptLong::NO_ARGUMENT],
|
32
|
-
# Don't match undefined symbols
|
33
|
-
["--match-undefined", "-U", GetoptLong::NO_ARGUMENT],
|
34
|
-
# Don't match defined symbols
|
35
|
-
["--match-defined", "-D", GetoptLong::NO_ARGUMENT],
|
36
|
-
# Invert selection, show symbols not matching the
|
37
|
-
# expression
|
38
|
-
["--invert-match", "-v", GetoptLong::NO_ARGUMENT],
|
39
|
-
# List only files with matches
|
40
|
-
["--files-with-matches", "-l", GetoptLong::NO_ARGUMENT],
|
41
|
-
# List only files without match
|
42
|
-
["--files-without-match", "-L", GetoptLong::NO_ARGUMENT],
|
43
|
-
# Print the name of the file for each match
|
44
|
-
["--with-filename", "-H", GetoptLong::NO_ARGUMENT],
|
45
|
-
# Don't print the name of the file for each match
|
46
|
-
["--no-filename", "-h", GetoptLong::NO_ARGUMENT],
|
47
|
-
# Only output matches' count
|
48
|
-
["--count", "-c", GetoptLong::NO_ARGUMENT],
|
49
|
-
# Match fixed strings and not regular expressions
|
50
|
-
["--fixed-strings", "-F", GetoptLong::NO_ARGUMENT],
|
51
|
-
# Make elfgrep case-insensitive
|
52
|
-
["--ignore-case", "-i", GetoptLong::NO_ARGUMENT],
|
53
|
-
# Use NULLs to terminate filenames
|
54
|
-
["--null", "-Z", GetoptLong::NO_ARGUMENT],
|
55
|
-
# read the list of patterns from the given file
|
56
|
-
["--file", "-f", GetoptLong::REQUIRED_ARGUMENT],
|
57
|
-
# match the whole symbol
|
58
|
-
["--symbol-regexp", "-s", GetoptLong::NO_ARGUMENT],
|
59
|
-
]
|
60
|
-
|
61
|
-
@invert_match = false
|
62
|
-
@show = :full_match
|
63
|
-
@match = :regexp
|
64
|
-
@match_symbols = nil
|
65
|
-
|
66
|
-
@patterns = []
|
67
|
-
@pattern_is_first = true
|
68
|
-
end
|
69
|
-
|
70
|
-
# We define callbacks for some behaviour-changing options as those
|
71
|
-
# will let us consider them positionally, similar to what grep(1)
|
72
|
-
# does. If you try -lLl and similar combinations on grep(1), the last
|
73
|
-
# one passed is the one to be considered.
|
74
|
-
|
75
|
-
def self.match_undefined_cb
|
76
|
-
if @match_symbols == :defined
|
77
|
-
@match_symbols = :all
|
78
|
-
else
|
79
|
-
@match_symbols = :undefined
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def self.match_defined_cb
|
84
|
-
if @match_symbols == :undefined
|
85
|
-
@match_symbols = :all
|
86
|
-
else
|
87
|
-
@match_symbols = :defined
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def self.fixed_strings_cb
|
92
|
-
@match = :fixed_strings
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.files_with_matches_cb
|
96
|
-
@show = :files_with_matches
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.files_without_match_cb
|
100
|
-
@show = :files_without_match
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.with_filename_cb
|
104
|
-
@print_filename = true
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.no_filename_cb
|
108
|
-
@print_filename = false
|
109
|
-
end
|
110
|
-
|
111
|
-
def self.regexp_cb(pattern)
|
112
|
-
@pattern_is_first = false
|
113
|
-
|
114
|
-
@patterns << pattern
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.file_cb(filename)
|
118
|
-
@pattern_is_first = false
|
119
|
-
|
120
|
-
@patterns += File.readlines(filename).
|
121
|
-
each { |l| l.strip! }.
|
122
|
-
reject { |l| l.empty? }
|
123
|
-
end
|
124
|
-
|
125
|
-
def self.after_options
|
126
|
-
if @no_match_undefined and @no_match_defined
|
127
|
-
puterror "you need to match at least defined or undefined symbols"
|
128
|
-
exit -1
|
129
|
-
end
|
130
|
-
|
131
|
-
@match_undefined = @match_symbols != :defined
|
132
|
-
@match_defined = @match_symbols != :undefined
|
133
|
-
|
134
|
-
# if we don't have listed patterns yet (i.e. no -e option), let's
|
135
|
-
# check whether we have at least one argument and if that argument
|
136
|
-
# doesn't start with '@'. If we have no arguments, the targets are
|
137
|
-
# to be given by stdin, and that won't include the actual pattern,
|
138
|
-
# if we have an @-prefixed argument, that's a list of targets and
|
139
|
-
# can't include the pattern either.
|
140
|
-
if (@pattern_is_first and
|
141
|
-
@targets.size >= 1 and
|
142
|
-
@targets[0] !~ /^@/)
|
143
|
-
|
144
|
-
@patterns << @targets.delete_at(0)
|
145
|
-
end
|
146
|
-
|
147
|
-
if @patterns.size == 0
|
148
|
-
puterror "you need to provide at least expression"
|
149
|
-
exit -1
|
150
|
-
end
|
151
|
-
|
152
|
-
@print_filename = (@recursive or @targets.size > 1) if @print_filename.nil?
|
153
|
-
@file_prefix_fmt = @print_filename ? "%s#{@null ? "\0" : ":"} " : ""
|
154
|
-
@file_list_fmt = "%s#{@null ? "\0" : "\n"}"
|
155
|
-
|
156
|
-
regexp_options = @ignore_case ? Regexp::IGNORECASE : 0
|
157
|
-
regexps = @patterns.collect { |pattern|
|
158
|
-
if @match == :fixed_strings
|
159
|
-
pattern.split(/\r?\n/).collect { |string|
|
160
|
-
Regexp.new(Regexp.escape(string), regexp_options)
|
161
|
-
}
|
162
|
-
else
|
163
|
-
Regexp.new(pattern, regexp_options)
|
164
|
-
end
|
165
|
-
}.flatten
|
166
|
-
|
167
|
-
if @symbol_regexp
|
168
|
-
# if we're matching a whole symbol name we need the longest
|
169
|
-
# match, and Ruby's union of regexp does _not_ enforce that,
|
170
|
-
# so we have to do it the long way.
|
171
|
-
|
172
|
-
@match_lambda = proc { |symbol|
|
173
|
-
longest_match = ""
|
174
|
-
|
175
|
-
regexps.each { |re|
|
176
|
-
m = re.match(symbol)
|
177
|
-
longest_match = m[0] unless (m.nil? or m[0].length < longest_match.length)
|
178
|
-
}
|
179
|
-
|
180
|
-
(longest_match != symbol) == @invert_match
|
181
|
-
}
|
182
|
-
else
|
183
|
-
# if we're just doing a loose match, unite the regexps and do
|
184
|
-
# it the fast way.
|
185
|
-
regexp = Regexp.union(regexps)
|
186
|
-
|
187
|
-
@match_lambda = proc { |symbol|
|
188
|
-
regexp.match(symbol).nil? == @invert_match
|
189
|
-
}
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def self.analysis(file)
|
194
|
-
file_prefix = sprintf(@file_prefix_fmt, file)
|
195
|
-
file_list = sprintf(@file_list_fmt, file)
|
196
|
-
|
197
|
-
Elf::File.open(file) do |elf|
|
198
|
-
table = [".dynsym", ".symtab"].find do |table|
|
199
|
-
begin
|
200
|
-
(elf[table].class == Elf::SymbolTable)
|
201
|
-
rescue Elf::File::MissingSection, Elf::File::MissingStringTable
|
202
|
-
false
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
if table.nil?
|
207
|
-
putnotice "#{file}: unable to find symbol table"
|
208
|
-
return
|
209
|
-
end
|
210
|
-
|
211
|
-
matches = 0
|
212
|
-
elf[table].each do |symbol|
|
213
|
-
next if
|
214
|
-
(symbol.section == Elf::Section::Abs) or
|
215
|
-
(symbol.name == '') or
|
216
|
-
(symbol.section == Elf::Section::Undef and
|
217
|
-
not @match_undefined) or
|
218
|
-
(symbol.section != Elf::Section::Undef and
|
219
|
-
not @match_defined)
|
220
|
-
|
221
|
-
symname = symbol.name
|
222
|
-
symname += "@#{symbol.version}" if @match_version
|
223
|
-
|
224
|
-
if (@match_lambda.call(symname))
|
225
|
-
matches = matches+1
|
226
|
-
|
227
|
-
break unless @show == :full_match
|
228
|
-
next if @count
|
229
|
-
|
230
|
-
printf("%s%#{elf.address_print_size}s %s %s\n",
|
231
|
-
file_prefix, symbol.address_string,
|
232
|
-
(symbol.nm_code rescue '?'), symname)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
if @show == :files_with_matches
|
237
|
-
puts file_list if matches > 0
|
238
|
-
elsif @show == :files_without_match
|
239
|
-
puts file_list if matches == 0
|
240
|
-
elsif @count
|
241
|
-
puts "#{file_prefix}#{matches}"
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
data/bin/missingstatic
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# -*- mode: ruby; coding: utf-8 -*-
|
3
|
-
# Copyright © 2008-2010 Diego Elio Pettenò <flameeyes@flameeyes.eu>
|
4
|
-
#
|
5
|
-
# This program is free software; you can redistribute it and/or modify
|
6
|
-
# it under the terms of the GNU General Public License as published by
|
7
|
-
# the Free Software Foundation; either version 2 of the License, or
|
8
|
-
# (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This program is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
-
# GNU General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU General Public License
|
16
|
-
# along with this generator; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
# check for functions that are not used but in their translation unit
|
20
|
-
|
21
|
-
require 'elf/tools'
|
22
|
-
|
23
|
-
module Elf::Tools
|
24
|
-
class MissingStatic < Elf::Tool
|
25
|
-
def self.initialize
|
26
|
-
super
|
27
|
-
@options |= [
|
28
|
-
# Exclude functions with a given prefix (exported functions)
|
29
|
-
["--exclude-regexp", "-x", GetoptLong::REQUIRED_ARGUMENT],
|
30
|
-
# Only scan hidden symbols, ignore exported ones
|
31
|
-
["--hidden-only", "-h", GetoptLong::NO_ARGUMENT],
|
32
|
-
# Show the type of symbol (function, variable, constant)
|
33
|
-
["--show-type", "-t", GetoptLong::NO_ARGUMENT],
|
34
|
-
# Exclude symbols present in a tags file (from exuberant-ctags)
|
35
|
-
["--exclude-tags", "-X", GetoptLong::REQUIRED_ARGUMENT]
|
36
|
-
]
|
37
|
-
|
38
|
-
# List of patterns to exclude; this include all the used
|
39
|
-
# symbols, the entrypoints to the system's dynamic loader, and
|
40
|
-
# those provided by the user as to be ignored.
|
41
|
-
#
|
42
|
-
# For technical limits, we have two arrays, one includes all the
|
43
|
-
# regular expressions given by the user, the other is a list of
|
44
|
-
# full strings matching.
|
45
|
-
@exclude_patterns = []
|
46
|
-
@exclude_symbols = Set.new([ "main" ])
|
47
|
-
|
48
|
-
@hidden_only = false
|
49
|
-
@show_type = false
|
50
|
-
|
51
|
-
@all_defined = []
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.exclude_tags_cb(arg)
|
55
|
-
@exclude_symbols |= File.readlines(arg).delete_if do |line|
|
56
|
-
line[0..0] == '!' # Internal exuberant-ctags symbol
|
57
|
-
end.collect do |line|
|
58
|
-
line.split[0]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.exclude_regexp_cb(arg)
|
63
|
-
@exclude_patterns << Regexp.new(arg)
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.analysis(filename)
|
67
|
-
Elf::File.open(filename) do |elf|
|
68
|
-
if elf.type != Elf::File::Type::Rel
|
69
|
-
putnotice "#{file}: not an object file"
|
70
|
-
next
|
71
|
-
end
|
72
|
-
unless elf.has_section?('.symtab')
|
73
|
-
putnotice "#{file}: no .symtab section found"
|
74
|
-
next
|
75
|
-
end
|
76
|
-
|
77
|
-
# Gather all the symbols, defined and missing in the translation unit
|
78
|
-
elf['.symtab'].each do |sym|
|
79
|
-
if sym.section == Elf::Section::Undef
|
80
|
-
@exclude_symbols << sym.name
|
81
|
-
elsif sym.bind == Elf::Symbol::Binding::Local
|
82
|
-
next
|
83
|
-
elsif (sym.section.is_a? Elf::Section) or
|
84
|
-
(sym.section == Elf::Section::Common)
|
85
|
-
next if @hidden_only and
|
86
|
-
sym.visibility != Elf::Symbol::Visibility::Hidden
|
87
|
-
|
88
|
-
@all_defined << sym
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.results
|
95
|
-
@exclude_patterns << Regexp.union(@exclude_symbols.collect { |sym| /^#{Regexp.escape(sym)}$/ })
|
96
|
-
exclusions = Regexp.union(@exclude_patterns)
|
97
|
-
|
98
|
-
@all_defined.each do |symbol|
|
99
|
-
next if symbol.name =~ exclusions
|
100
|
-
|
101
|
-
if @show_type
|
102
|
-
begin
|
103
|
-
prefix = "#{symbol.nm_code} "
|
104
|
-
rescue Elf::Symbol::UnknownNMCode => e
|
105
|
-
puterror e.message
|
106
|
-
prefix = "? "
|
107
|
-
end
|
108
|
-
end
|
109
|
-
puts "#{prefix}#{symbol.name} (#{symbol.file.path})"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
data/bin/rbelf-nm
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
# Copyright © 2007-2010 Diego Elio Pettenò <flameeyes@flameeyes.eu>
|
4
|
-
#
|
5
|
-
# This program is free software; you can redistribute it and/or modify
|
6
|
-
# it under the terms of the GNU General Public License as published by
|
7
|
-
# the Free Software Foundation; either version 2 of the License, or
|
8
|
-
# (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This program is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
-
# GNU General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU General Public License
|
16
|
-
# along with this generator; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
|
19
|
-
# bsd-nm implementation based on elf.rb (very limited)
|
20
|
-
|
21
|
-
require 'elf/tools'
|
22
|
-
require 'getoptlong'
|
23
|
-
|
24
|
-
module Elf::Tools
|
25
|
-
class NM < Elf::Tool
|
26
|
-
|
27
|
-
def self.initialize
|
28
|
-
super
|
29
|
-
@options |= [
|
30
|
-
["--dynamic", "-D", GetoptLong::NO_ARGUMENT],
|
31
|
-
["--demangle", "-C", GetoptLong::NO_ARGUMENT],
|
32
|
-
["--sort-by", "-S", GetoptLong::REQUIRED_ARGUMENT],
|
33
|
-
["--show-version", "-V", GetoptLong::NO_ARGUMENT],
|
34
|
-
]
|
35
|
-
|
36
|
-
@scan_section = '.symtab'
|
37
|
-
@demangle = false
|
38
|
-
@exitval = 0
|
39
|
-
@show_version = false
|
40
|
-
|
41
|
-
@sort = :name
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.dynamic_cb
|
45
|
-
@scan_section = '.dynsym'
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.sort_by_cb(attr)
|
49
|
-
case attr
|
50
|
-
when 'address'
|
51
|
-
@sort = :address
|
52
|
-
when 'name'
|
53
|
-
@sort = :name
|
54
|
-
when 'none'
|
55
|
-
@sort = nil
|
56
|
-
else
|
57
|
-
puterror "invalid sort attribute: #{attr}"
|
58
|
-
exit -1
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.analysis(file)
|
63
|
-
symbols = []
|
64
|
-
|
65
|
-
Elf::File.open(file) do |elf|
|
66
|
-
if not elf.has_section? @scan_section
|
67
|
-
puterror "No symbols"
|
68
|
-
@exitval = 1
|
69
|
-
return
|
70
|
-
end
|
71
|
-
|
72
|
-
elf[@scan_section].each do |sym|
|
73
|
-
next if sym.name == ''
|
74
|
-
begin
|
75
|
-
code = sym.nm_code
|
76
|
-
rescue Elf::Symbol::UnknownNMCode => e
|
77
|
-
puterror(e.message)
|
78
|
-
code = "?"
|
79
|
-
end
|
80
|
-
|
81
|
-
name = @demangle ? sym.demangle : sym.name
|
82
|
-
|
83
|
-
if @show_version and sym.version
|
84
|
-
name = sprintf("%s@%s%s",
|
85
|
-
name,
|
86
|
-
sym.version_default? ? '@' : '',
|
87
|
-
sym.version)
|
88
|
-
end
|
89
|
-
|
90
|
-
symbols << {
|
91
|
-
:address => sym.address_string,
|
92
|
-
:code => code,
|
93
|
-
:name => name
|
94
|
-
}
|
95
|
-
end
|
96
|
-
|
97
|
-
symbols.sort! { |x, y| x[@sort] <=> y[@sort] } unless @sort.nil?
|
98
|
-
|
99
|
-
format_sym = "%#{elf.address_print_size}s %s %s\n"
|
100
|
-
@output_mutex.synchronize {
|
101
|
-
symbols.each do |sym|
|
102
|
-
printf(format_sym,
|
103
|
-
sym[:address], sym[:code], sym[:name])
|
104
|
-
end
|
105
|
-
}
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def self.results
|
110
|
-
exit @exitval
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|