ruby-elf 1.0.0
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/COPYING +339 -0
- data/DONATING +42 -0
- data/bin/cowstats +264 -0
- data/bin/elfgrep +185 -0
- data/bin/missingstatic +112 -0
- data/bin/rbelf-size +123 -0
- data/bin/verify-lfs +120 -0
- data/extras/README.extras +5 -0
- data/extras/bindings-parsers.rb +157 -0
- data/lib/bytestream-reader.rb +271 -0
- data/lib/elf.rb +248 -0
- data/lib/elf/dynamic.rb +392 -0
- data/lib/elf/file.rb +366 -0
- data/lib/elf/gnu.rb +174 -0
- data/lib/elf/section.rb +321 -0
- data/lib/elf/stringtable.rb +49 -0
- data/lib/elf/sunw.rb +158 -0
- data/lib/elf/symbol.rb +368 -0
- data/lib/elf/symbol/demangler_gcc3.rb +1952 -0
- data/lib/elf/symboltable.rb +90 -0
- data/lib/elf/tools.rb +228 -0
- data/lib/elf/utils/loader.rb +112 -0
- data/lib/elf/utils/pool.rb +37 -0
- data/lib/elf/value.rb +128 -0
- data/manpages/cowstats.1 +180 -0
- data/manpages/elfgrep.1 +188 -0
- data/manpages/missingstatic.1 +176 -0
- data/manpages/rbelf-size.1 +186 -0
- data/manpages/verify-lfs.1 +95 -0
- data/tools/assess_duplicate_save.rb +105 -0
- data/tools/link-collisions/analyse.rb +57 -0
- data/tools/link-collisions/harvest.rb +367 -0
- data/tools/link-collisions/known-broken +165 -0
- data/tools/link-collisions/multimplementations +125 -0
- data/tools/link-collisions/suppress.rb +84 -0
- data/tools/link-collisions/suppressions +279 -0
- data/tools/nm.rb +78 -0
- data/tools/rbelf-lddtree.rb +49 -0
- data/tools/readelf-d.rb +76 -0
- metadata +114 -0
data/bin/elfgrep
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
3
|
+
# Copyright © 2011 Diego E. "Flameeyes" Pettenò <flameeyes@gmail.com>
|
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
|
+
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
|
60
|
+
|
61
|
+
def self.files_with_matches_cb
|
62
|
+
@show = :files_with_matches
|
63
|
+
end
|
64
|
+
|
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
|
72
|
+
|
73
|
+
def self.no_filename_cb
|
74
|
+
@print_filename = false
|
75
|
+
end
|
76
|
+
|
77
|
+
# we make this a method so that we don't have to worry about deciding
|
78
|
+
# on the base of how many targets we have; we have to do this
|
79
|
+
# because we cannot know, in after_options, whether the user passed
|
80
|
+
# @-file lists.
|
81
|
+
def self.print_filename
|
82
|
+
@print_filename = !@single_target if @print_filename.nil?
|
83
|
+
|
84
|
+
@print_filename
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.regexp_cb(pattern)
|
88
|
+
@patterns << pattern
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.before_options
|
92
|
+
@invert_match = false
|
93
|
+
@match_undefined = true
|
94
|
+
@match_defined = true
|
95
|
+
@show = :full_match
|
96
|
+
@match = :regexp
|
97
|
+
|
98
|
+
@patterns = []
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.after_options
|
102
|
+
if @patterns.size ==0
|
103
|
+
puterror "you need to provide at least expression"
|
104
|
+
exit -1
|
105
|
+
end
|
106
|
+
|
107
|
+
if @no_match_undefined and @no_match_defined
|
108
|
+
puterror "you need to match at least defined or undefined symbols"
|
109
|
+
exit -1
|
110
|
+
end
|
111
|
+
|
112
|
+
@match_undefined = !@no_match_undefined
|
113
|
+
@match_defined = !@no_match_defined
|
114
|
+
|
115
|
+
regexp_options = @ignore_case ? Regexp::IGNORECASE : 0
|
116
|
+
@regexp = Regexp.union(@patterns.collect { |pattern|
|
117
|
+
# escape the pattern, so that it works like
|
118
|
+
# it was a fixed string.
|
119
|
+
pattern = Regexp.escape(pattern) if @match == :fixed_strings
|
120
|
+
|
121
|
+
Regexp.new(pattern, regexp_options)
|
122
|
+
})
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.analysis(file)
|
126
|
+
if not @print_filename
|
127
|
+
file_prefix = ""
|
128
|
+
else
|
129
|
+
file_prefix = sprintf("%s%s ",
|
130
|
+
file,
|
131
|
+
@null ? "\0" : ":")
|
132
|
+
end
|
133
|
+
file_list = sprintf("%s%s",
|
134
|
+
file,
|
135
|
+
@null ? "\0" : "\n")
|
136
|
+
|
137
|
+
Elf::File.open(file) do |elf|
|
138
|
+
table = [".dynsym", ".symtab"].find do |table|
|
139
|
+
begin
|
140
|
+
(elf[table].class == Elf::SymbolTable)
|
141
|
+
rescue Elf::File::MissingSection
|
142
|
+
false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
if table.nil?
|
147
|
+
putnotice "#{file}: unable to find symbol table"
|
148
|
+
return
|
149
|
+
end
|
150
|
+
|
151
|
+
matches = 0
|
152
|
+
elf[table].each do |symbol|
|
153
|
+
next if
|
154
|
+
(symbol.section == Elf::Section::Abs) or
|
155
|
+
(symbol.name == '') or
|
156
|
+
(symbol.section == Elf::Section::Undef and
|
157
|
+
not @match_undefined) or
|
158
|
+
(symbol.section != Elf::Section::Undef and
|
159
|
+
not @match_defined)
|
160
|
+
|
161
|
+
symname = symbol.name
|
162
|
+
symname += "@#{symbol.version}" if @match_version
|
163
|
+
|
164
|
+
# We don't care where it matches, but we do care that it matches
|
165
|
+
# or not; we use an invert match since we have to further compare
|
166
|
+
# that to @invert_match
|
167
|
+
if (@invert_match == (@regexp =~ symname).nil?)
|
168
|
+
matches = matches+1
|
169
|
+
|
170
|
+
break unless @show == :full_match
|
171
|
+
next if @count
|
172
|
+
|
173
|
+
puts "#{file_prefix}#{symbol.address_string} #{symbol.nm_code rescue '?'} #{symname}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
if @show == :files_with_matches
|
178
|
+
puts file_list if matches > 0
|
179
|
+
elsif @show == :files_without_match
|
180
|
+
puts file_list if matches == 0
|
181
|
+
elsif @count
|
182
|
+
puts "#{file_prefix}#{matches}"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/bin/missingstatic
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
3
|
+
# Copyright © 2008-2010 Diego E. "Flameeyes" Pettenò <flameeyes@gmail.com>
|
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
|
+
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
|
+
]
|
33
|
+
|
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
|
41
|
+
|
42
|
+
def self.exclude_regexp_cb(arg)
|
43
|
+
@exclude_regexps << Regexp.new(arg)
|
44
|
+
end
|
45
|
+
|
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
|
61
|
+
|
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
|
67
|
+
end
|
68
|
+
unless elf.has_section?('.symtab')
|
69
|
+
putnotice "#{file}: no .symtab section found"
|
70
|
+
next
|
71
|
+
end
|
72
|
+
|
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
|
83
|
+
|
84
|
+
@all_defined << sym
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.results
|
91
|
+
@exclude_names.uniq!
|
92
|
+
|
93
|
+
@all_defined.each do |symbol|
|
94
|
+
next if @exclude_names.include? symbol.name
|
95
|
+
|
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
|
101
|
+
|
102
|
+
if @show_type
|
103
|
+
begin
|
104
|
+
prefix = "#{symbol.nm_code} "
|
105
|
+
rescue Elf::Symbol::UnknownNMCode => e
|
106
|
+
puterror e.message
|
107
|
+
prefix = "? "
|
108
|
+
end
|
109
|
+
end
|
110
|
+
puts "#{prefix}#{symbol.name} (#{symbol.file.path})"
|
111
|
+
end
|
112
|
+
end
|
data/bin/rbelf-size
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
3
|
+
# Copyright © 2008-2010 Diego E. "Flameeyes" Pettenò <flameeyes@gmail.com>
|
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
|
+
# replacement for size(1) utility that takes into consideration .rodata sections
|
20
|
+
|
21
|
+
require 'elf/tools'
|
22
|
+
|
23
|
+
Options = [
|
24
|
+
# Give relocation data for shared object assesment
|
25
|
+
["--relocation-stats", "-r", GetoptLong::NO_ARGUMENT],
|
26
|
+
# Use deciBel scale for the shared-to-relocated ratio
|
27
|
+
["--decibel", "-d", GetoptLong::NO_ARGUMENT]
|
28
|
+
]
|
29
|
+
|
30
|
+
def self.before_options
|
31
|
+
@relocation_stats = false
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.after_options
|
35
|
+
@header = true
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.analysis(file)
|
39
|
+
Elf::File.open(file) do |elf|
|
40
|
+
results = {
|
41
|
+
:exec => 0,
|
42
|
+
:data => 0,
|
43
|
+
:rodata => 0,
|
44
|
+
:relro => 0,
|
45
|
+
:bss => 0,
|
46
|
+
:total => 0
|
47
|
+
}
|
48
|
+
|
49
|
+
# Get the size of each section, and then, depending on its type,
|
50
|
+
# flags and eventually name, decide what to sum it to.
|
51
|
+
elf.each_section do |section|
|
52
|
+
case
|
53
|
+
# When the section is NoBits, it is not allocated in the file,
|
54
|
+
# and is only allocated in ram, this is the case of .bss and
|
55
|
+
# .tbss sections.
|
56
|
+
when section.type == Elf::Section::Type::NoBits
|
57
|
+
sectype = :bss
|
58
|
+
# If the section contains executable code, count it separately;
|
59
|
+
# size(1) will count it all as text, but we don't need to do
|
60
|
+
# that.
|
61
|
+
when section.flags.include?(Elf::Section::Flags::ExecInstr)
|
62
|
+
sectype = :exec
|
63
|
+
# If the section is going to be allocated and writeable at
|
64
|
+
# runtime, it is usually a data section, of some kind.
|
65
|
+
#
|
66
|
+
# We check further though since we might want to count it
|
67
|
+
# separately.
|
68
|
+
when (section.flags.include?(Elf::Section::Flags::Write) and
|
69
|
+
section.flags.include?(Elf::Section::Flags::Alloc))
|
70
|
+
|
71
|
+
# This makes it GCC-specific but that's just because I
|
72
|
+
# cannot find anything in ELF specs that gives an easy way
|
73
|
+
# to deal with this.
|
74
|
+
#
|
75
|
+
# By all means, .data.rel.ro is just the same as .data, with
|
76
|
+
# the exception of prelinking, where this area can then
|
77
|
+
# become mostly read-only and thus not creating dirty pages.
|
78
|
+
sectype = (section.name =~ /^\.data\.rel\.ro(\..+)?/) ? :relro : :data
|
79
|
+
when section.flags.include?(Elf::Section::Flags::Alloc)
|
80
|
+
sectype = :rodata
|
81
|
+
end
|
82
|
+
|
83
|
+
results[sectype] += section.size unless sectype.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
results[:total] = results.values.inject { |sum, val| sum += val }
|
87
|
+
|
88
|
+
if @relocation_stats
|
89
|
+
relocation_stats(results, file)
|
90
|
+
else
|
91
|
+
standard_size(results, file)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.relocation_stats(results, file)
|
97
|
+
if @header
|
98
|
+
puts " shared private relocated ratio filename"
|
99
|
+
@header = false
|
100
|
+
end
|
101
|
+
|
102
|
+
size_shared = results[:exec] + results[:rodata]
|
103
|
+
size_private = results[:data] + results[:bss]
|
104
|
+
size_relocated = results[:relro]
|
105
|
+
|
106
|
+
ratio = size_shared.to_f/size_relocated
|
107
|
+
ratio = 10 * Math::log10(ratio) if @decibel
|
108
|
+
|
109
|
+
printf "% 12s % 12s % 12s % 12.2f %s\n", size_shared, size_private, size_relocated, ratio, file
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.standard_size(results, file)
|
113
|
+
if @header
|
114
|
+
puts " exec data rodata relro bss total filename"
|
115
|
+
@header = false
|
116
|
+
end
|
117
|
+
|
118
|
+
results.each_pair do |key, val|
|
119
|
+
results[key] = val.to_s.rjust(9)
|
120
|
+
end
|
121
|
+
|
122
|
+
puts "#{results[:exec]} #{results[:data]} #{results[:rodata]} #{results[:relro]} #{results[:bss]} #{results[:total]} #{file}"
|
123
|
+
end
|
data/bin/verify-lfs
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
3
|
+
# Copyright © 2010 Diego E. "Flameeyes" Pettenò <flameeyes@gmail.com>
|
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
|
+
# This script verifies whether a file or a tree of files is using
|
20
|
+
# non-LFS interfaces, or mixing non-LFS and LFS interfaces.
|
21
|
+
|
22
|
+
require 'elf/tools'
|
23
|
+
|
24
|
+
Options = [
|
25
|
+
# Scan only object files (rather than non-object files)
|
26
|
+
["--objects", "-o", GetoptLong::NO_ARGUMENT]
|
27
|
+
]
|
28
|
+
|
29
|
+
SymbolNamesList = [
|
30
|
+
"__[fl]?xstat",
|
31
|
+
"statv?fs",
|
32
|
+
"(|_IO_)f[gs]etpos",
|
33
|
+
"(read|scan)dir",
|
34
|
+
"getdirentries",
|
35
|
+
"mko?stemp",
|
36
|
+
"(|__)p(read|write)",
|
37
|
+
"p(read|write)v",
|
38
|
+
"(send|tmp)file",
|
39
|
+
"[gs]etrlimit",
|
40
|
+
"versionsort",
|
41
|
+
"f?truncate",
|
42
|
+
"(|f(|re))open",
|
43
|
+
"openat",
|
44
|
+
"fseeko",
|
45
|
+
"ftello",
|
46
|
+
"lseek",
|
47
|
+
"glob(|free)",
|
48
|
+
"ftw",
|
49
|
+
"lockf"
|
50
|
+
]
|
51
|
+
|
52
|
+
SymbolNames = "(#{SymbolNamesList.join("|")})"
|
53
|
+
|
54
|
+
def self.before_options
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.after_options
|
58
|
+
@files_mixing = []
|
59
|
+
@files_nolfs = []
|
60
|
+
|
61
|
+
if @objects
|
62
|
+
@elftypes = [ Elf::File::Type::Rel ]
|
63
|
+
@elfdescr = "a relocatable object file"
|
64
|
+
@elftable = ".symtab"
|
65
|
+
else
|
66
|
+
@elftypes = [ Elf::File::Type::Exec, Elf::File::Type::Dyn ]
|
67
|
+
@elfdescr = "an executable or dynamic file"
|
68
|
+
@elftable = ".dynsym"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.analysis(file)
|
73
|
+
Elf::File.open(file) do |elf|
|
74
|
+
unless @elftypes.include? elf.type
|
75
|
+
putnotice "#{file}: not #{@elfdescr}"
|
76
|
+
next
|
77
|
+
end
|
78
|
+
|
79
|
+
if not elf.has_section?(@elftable) or elf[@elftable].class != Elf::SymbolTable
|
80
|
+
putnotice "#{file}: not a dynamically linked file"
|
81
|
+
next
|
82
|
+
end
|
83
|
+
|
84
|
+
if elf.elf_class == Elf::Class::Elf64
|
85
|
+
putnotice "#{file}: testing 64-bit ELF files is meaningless"
|
86
|
+
next
|
87
|
+
end
|
88
|
+
|
89
|
+
use_stat32 = false
|
90
|
+
use_stat64 = false
|
91
|
+
|
92
|
+
elf[@elftable].each do |symbol|
|
93
|
+
next unless symbol.section == Elf::Section::Undef
|
94
|
+
|
95
|
+
use_stat32 ||= (symbol.to_s =~ /^#{SymbolNames}$/)
|
96
|
+
use_stat64 ||= (symbol.to_s =~ /^#{SymbolNames}64$/)
|
97
|
+
|
98
|
+
# avoid running the whole list if we hit both as we cannot hit
|
99
|
+
# _more_
|
100
|
+
break if use_stat32 and use_stat64
|
101
|
+
end
|
102
|
+
|
103
|
+
if use_stat32 and use_stat64
|
104
|
+
@files_mixing << file
|
105
|
+
elsif use_stat32 and not use_stat64
|
106
|
+
@files_nolfs << file
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.results
|
112
|
+
if @files_mixing.size > 0
|
113
|
+
puts "The following files are mixing LFS and non-LFS library calls:"
|
114
|
+
puts " " + @files_mixing.join("\n ")
|
115
|
+
end
|
116
|
+
if @files_nolfs.size > 0
|
117
|
+
puts "The following files are using non-LFS library calls:"
|
118
|
+
puts " " + @files_nolfs.join("\n ")
|
119
|
+
end
|
120
|
+
end
|