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.
@@ -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
@@ -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
@@ -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