ruby-elf 1.0.3 → 1.0.4

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/bin/elfgrep CHANGED
@@ -18,169 +18,190 @@
18
18
 
19
19
  require 'elf/tools'
20
20
 
21
- Options = [
22
- # Expression to match on the symbol name
23
- ["--regexp", "-e", GetoptLong::REQUIRED_ARGUMENT],
24
- # Append the version information when matching the symbol
25
- # name
26
- ["--match-version", "-V", GetoptLong::NO_ARGUMENT],
27
- # Don't match undefined symbols
28
- ["--no-match-undefined", "-U", GetoptLong::NO_ARGUMENT],
29
- # Don't match defined symbols
30
- ["--no-match-defined", "-D", GetoptLong::NO_ARGUMENT],
31
- # Invert selection, show symbols not matching the
32
- # expression
33
- ["--invert-match", "-v", GetoptLong::NO_ARGUMENT],
34
- # List only files with matches
35
- ["--files-with-matches", "-l", GetoptLong::NO_ARGUMENT],
36
- # List only files without match
37
- ["--files-without-match", "-L", GetoptLong::NO_ARGUMENT],
38
- # Print the name of the file for each match
39
- ["--with-filename", "-H", GetoptLong::NO_ARGUMENT],
40
- # Don't print the name of the file for each match
41
- ["--no-filename", "-h", GetoptLong::NO_ARGUMENT],
42
- # Only output matches' count
43
- ["--count", "-c", GetoptLong::NO_ARGUMENT],
44
- # Match fixed strings and not regular expressions
45
- ["--fixed-strings", "-F", GetoptLong::NO_ARGUMENT],
46
- # Make elfgrep case-insensitive
47
- ["--ignore-case", "-i", GetoptLong::NO_ARGUMENT],
48
- # Use NULLs to terminate filenames
49
- ["--null", "-Z", GetoptLong::NO_ARGUMENT],
50
- ]
51
-
52
- # We define callbacks for some behaviour-changing options as those
53
- # will let us consider them positionally, similar to what grep(1)
54
- # does. If you try -lLl and similar combinations on grep(1), the last
55
- # one passed is the one to be considered.
56
-
57
- def self.fixed_strings_cb
58
- @match = :fixed_strings
59
- end
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
+ ]
56
+
57
+ @invert_match = false
58
+ @show = :full_match
59
+ @match = :regexp
60
+ @match_symbols = nil
61
+
62
+ @patterns = []
63
+ end
60
64
 
61
- def self.files_with_matches_cb
62
- @show = :files_with_matches
63
- end
65
+ # We define callbacks for some behaviour-changing options as those
66
+ # will let us consider them positionally, similar to what grep(1)
67
+ # does. If you try -lLl and similar combinations on grep(1), the last
68
+ # one passed is the one to be considered.
64
69
 
65
- def self.files_without_match_cb
66
- @show = :files_without_match
67
- end
68
-
69
- def self.with_filename_cb
70
- @print_filename = true
71
- end
70
+ def self.match_undefined_cb
71
+ if @match_symbols == :defined
72
+ @match_symbols = :all
73
+ else
74
+ @match_symbols = :undefined
75
+ end
76
+ end
72
77
 
73
- def self.no_filename_cb
74
- @print_filename = false
75
- end
78
+ def self.match_defined_cb
79
+ if @match_symbols == :undefined
80
+ @match_symbols = :all
81
+ else
82
+ @match_symbols = :defined
83
+ end
84
+ end
76
85
 
77
- def self.regexp_cb(pattern)
78
- @patterns << pattern
79
- end
86
+ def self.fixed_strings_cb
87
+ @match = :fixed_strings
88
+ end
80
89
 
81
- def self.before_options
82
- @invert_match = false
83
- @match_undefined = true
84
- @match_defined = true
85
- @show = :full_match
86
- @match = :regexp
90
+ def self.files_with_matches_cb
91
+ @show = :files_with_matches
92
+ end
87
93
 
88
- @patterns = []
89
- end
94
+ def self.files_without_match_cb
95
+ @show = :files_without_match
96
+ end
90
97
 
91
- def self.after_options
92
- if @no_match_undefined and @no_match_defined
93
- puterror "you need to match at least defined or undefined symbols"
94
- exit -1
95
- end
98
+ def self.with_filename_cb
99
+ @print_filename = true
100
+ end
96
101
 
97
- @match_undefined = !@no_match_undefined
98
- @match_defined = !@no_match_defined
102
+ def self.no_filename_cb
103
+ @print_filename = false
104
+ end
99
105
 
100
- # if we don't have listed patterns yet (i.e. no -e option), let's
101
- # check whether we have at least one argument and if that argument
102
- # doesn't start with '@'. If we have no arguments, the targets are
103
- # to be given by stdin, and that won't include the actual pattern,
104
- # if we have an @-prefixed argument, that's a list of targets and
105
- # can't include the pattern either.
106
- if (@patterns.size == 0 and
107
- ARGV.size >= 1 and
108
- ARGV[0] !~ /^@/)
106
+ def self.regexp_cb(pattern)
107
+ @patterns << pattern
108
+ end
109
109
 
110
- @patterns << ARGV.delete_at(0)
111
- end
110
+ def self.after_options
111
+ if @no_match_undefined and @no_match_defined
112
+ puterror "you need to match at least defined or undefined symbols"
113
+ exit -1
114
+ end
112
115
 
113
- if @patterns.size == 0
114
- puterror "you need to provide at least expression"
115
- exit -1
116
- end
116
+ @match_undefined = @match_symbols != :defined
117
+ @match_defined = @match_symbols != :undefined
117
118
 
118
- @print_filename = true if @print_filename.nil? and not single_target?
119
- @file_prefix_fmt = @print_filename ? "%s#{@null ? "\0" : ":"} " : ""
120
- @file_list_fmt = "%s#{@null ? "\0" : "\n"}"
121
-
122
- regexp_options = @ignore_case ? Regexp::IGNORECASE : 0
123
- @regexp = Regexp.union(@patterns.collect { |pattern|
124
- if @match == :fixed_strings
125
- pattern.split(/\r?\n/).collect { |string|
126
- Regexp.new(Regexp.escape(string), regexp_options)
127
- }
128
- else
129
- Regexp.new(pattern, regexp_options)
130
- end
131
- }.flatten)
132
- end
119
+ # if we don't have listed patterns yet (i.e. no -e option), let's
120
+ # check whether we have at least one argument and if that argument
121
+ # doesn't start with '@'. If we have no arguments, the targets are
122
+ # to be given by stdin, and that won't include the actual pattern,
123
+ # if we have an @-prefixed argument, that's a list of targets and
124
+ # can't include the pattern either.
125
+ if (@patterns.size == 0 and
126
+ @targets.size >= 1 and
127
+ @targets[0] !~ /^@/)
133
128
 
134
- def self.analysis(file)
135
- file_prefix = sprintf(@file_prefix_fmt, file)
136
- file_list = sprintf(@file_list_fmt, file)
129
+ @patterns << @targets.delete_at(0)
130
+ end
137
131
 
138
- Elf::File.open(file) do |elf|
139
- table = [".dynsym", ".symtab"].find do |table|
140
- begin
141
- (elf[table].class == Elf::SymbolTable)
142
- rescue Elf::File::MissingSection
143
- false
132
+ if @patterns.size == 0
133
+ puterror "you need to provide at least expression"
134
+ exit -1
144
135
  end
145
- end
146
136
 
147
- if table.nil?
148
- putnotice "#{file}: unable to find symbol table"
149
- return
137
+ @print_filename = (@recursive or @targets.size > 1) if @print_filename.nil?
138
+ @file_prefix_fmt = @print_filename ? "%s#{@null ? "\0" : ":"} " : ""
139
+ @file_list_fmt = "%s#{@null ? "\0" : "\n"}"
140
+
141
+ regexp_options = @ignore_case ? Regexp::IGNORECASE : 0
142
+ @regexp = Regexp.union(@patterns.collect { |pattern|
143
+ if @match == :fixed_strings
144
+ pattern.split(/\r?\n/).collect { |string|
145
+ Regexp.new(Regexp.escape(string), regexp_options)
146
+ }
147
+ else
148
+ Regexp.new(pattern, regexp_options)
149
+ end
150
+ }.flatten)
150
151
  end
151
152
 
152
- matches = 0
153
- elf[table].each do |symbol|
154
- next if
155
- (symbol.section == Elf::Section::Abs) or
156
- (symbol.name == '') or
157
- (symbol.section == Elf::Section::Undef and
158
- not @match_undefined) or
159
- (symbol.section != Elf::Section::Undef and
160
- not @match_defined)
161
-
162
- symname = symbol.name
163
- symname += "@#{symbol.version}" if @match_version
164
-
165
- # We don't care where it matches, but we do care that it matches
166
- # or not; we use an invert match since we have to further compare
167
- # that to @invert_match
168
- if (@invert_match == (@regexp =~ symname).nil?)
169
- matches = matches+1
170
-
171
- break unless @show == :full_match
172
- next if @count
173
-
174
- puts "#{file_prefix}#{symbol.address_string} #{symbol.nm_code rescue '?'} #{symname}"
153
+ def self.analysis(file)
154
+ file_prefix = sprintf(@file_prefix_fmt, file)
155
+ file_list = sprintf(@file_list_fmt, file)
156
+
157
+ Elf::File.open(file) do |elf|
158
+ table = [".dynsym", ".symtab"].find do |table|
159
+ begin
160
+ (elf[table].class == Elf::SymbolTable)
161
+ rescue Elf::File::MissingSection, Elf::File::MissingStringTable
162
+ false
163
+ end
164
+ end
165
+
166
+ if table.nil?
167
+ putnotice "#{file}: unable to find symbol table"
168
+ return
169
+ end
170
+
171
+ matches = 0
172
+ elf[table].each do |symbol|
173
+ next if
174
+ (symbol.section == Elf::Section::Abs) or
175
+ (symbol.name == '') or
176
+ (symbol.section == Elf::Section::Undef and
177
+ not @match_undefined) or
178
+ (symbol.section != Elf::Section::Undef and
179
+ not @match_defined)
180
+
181
+ symname = symbol.name
182
+ symname += "@#{symbol.version}" if @match_version
183
+
184
+ # We don't care where it matches, but we do care that it matches
185
+ # or not; we use an invert match since we have to further compare
186
+ # that to @invert_match
187
+ if (@invert_match == (@regexp =~ symname).nil?)
188
+ matches = matches+1
189
+
190
+ break unless @show == :full_match
191
+ next if @count
192
+
193
+ puts "#{file_prefix}#{symbol.address_string} #{symbol.nm_code rescue '?'} #{symname}"
194
+ end
195
+ end
196
+
197
+ if @show == :files_with_matches
198
+ puts file_list if matches > 0
199
+ elsif @show == :files_without_match
200
+ puts file_list if matches == 0
201
+ elsif @count
202
+ puts "#{file_prefix}#{matches}"
203
+ end
175
204
  end
176
205
  end
177
-
178
- if @show == :files_with_matches
179
- puts file_list if matches > 0
180
- elsif @show == :files_without_match
181
- puts file_list if matches == 0
182
- elsif @count
183
- puts "#{file_prefix}#{matches}"
184
- end
185
206
  end
186
207
  end
data/bin/missingstatic CHANGED
@@ -20,93 +20,94 @@
20
20
 
21
21
  require 'elf/tools'
22
22
 
23
- Options = [
24
- # Exclude functions with a given prefix (exported functions)
25
- ["--exclude-regexp", "-x", GetoptLong::REQUIRED_ARGUMENT],
26
- # Only scan hidden symbols, ignore exported ones
27
- ["--hidden-only", "-h", GetoptLong::NO_ARGUMENT],
28
- # Show the type of symbol (function, variable, constant)
29
- ["--show-type", "-t", GetoptLong::NO_ARGUMENT],
30
- # Exclude symbols present in a tags file (from exuberant-ctags)
31
- ["--exclude-tags", "-X", GetoptLong::REQUIRED_ARGUMENT]
32
- ]
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
+ ]
33
37
 
34
- def self.exclude_tags_cb(arg)
35
- @exclude_names += File.readlines(arg).delete_if do |line|
36
- line[0..0] == '!' # Internal exuberant-ctags symbol
37
- end.collect do |line|
38
- line.split[0]
39
- end
40
- end
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" ])
41
47
 
42
- def self.exclude_regexp_cb(arg)
43
- @exclude_regexps << Regexp.new(arg)
44
- end
48
+ @hidden_only = false
49
+ @show_type = false
45
50
 
46
- def self.before_options
47
- # The main symbol is used by all the standalone executables,
48
- # reporting it is pointless as it will always be a false
49
- # positive. It cannot be marked static.
50
- #
51
- # The excluded_names variable will contain also all the used symbols
52
- @exclude_names = ["main"]
53
- @exclude_regexps = []
54
- @hidden_only = false
55
- @show_type = false
56
- end
57
-
58
- def self.after_options
59
- @all_defined = []
60
- end
51
+ @all_defined = []
52
+ end
61
53
 
62
- def self.analysis(filename)
63
- Elf::File.open(filename) do |elf|
64
- if elf.type != Elf::File::Type::Rel
65
- putnotice "#{file}: not an object file"
66
- next
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
67
60
  end
68
- unless elf.has_section?('.symtab')
69
- putnotice "#{file}: no .symtab section found"
70
- next
61
+
62
+ def self.exclude_regexp_cb(arg)
63
+ @exclude_patterns << Regexp.new(arg)
71
64
  end
72
65
 
73
- # Gather all the symbols, defined and missing in the translation unit
74
- elf['.symtab'].each do |sym|
75
- if sym.section == Elf::Section::Undef
76
- @exclude_names << sym.name
77
- elsif sym.bind == Elf::Symbol::Binding::Local
78
- next
79
- elsif (sym.section.is_a? Elf::Section) or
80
- (sym.section == Elf::Section::Common)
81
- next if @hidden_only and
82
- sym.visibility != Elf::Symbol::Visibility::Hidden
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
83
76
 
84
- @all_defined << sym
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
85
91
  end
86
92
  end
87
- end
88
- end
89
-
90
- def self.results
91
- @exclude_names.uniq!
92
93
 
93
- @all_defined.each do |symbol|
94
- next if @exclude_names.include? symbol.name
94
+ def self.results
95
+ @exclude_patterns << Regexp.union(@exclude_symbols.collect { |sym| /^#{Regexp.escape(sym)}$/ })
96
+ exclusions = Regexp.union(@exclude_patterns)
95
97
 
96
- excluded = false
97
- @exclude_regexps.each do |exclude_sym|
98
- break if excluded = exclude_sym.match(symbol.name)
99
- end
100
- next if excluded
98
+ @all_defined.each do |symbol|
99
+ next if symbol.name =~ exclusions
101
100
 
102
- if @show_type
103
- begin
104
- prefix = "#{symbol.nm_code} "
105
- rescue Elf::Symbol::UnknownNMCode => e
106
- puterror e.message
107
- prefix = "? "
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})"
108
110
  end
109
111
  end
110
- puts "#{prefix}#{symbol.name} (#{symbol.file.path})"
111
112
  end
112
113
  end