ruby-elf 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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