ruby-elf 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/bin/cowstats CHANGED
@@ -20,245 +20,247 @@
20
20
 
21
21
  require 'elf/tools'
22
22
 
23
- Options = [
24
- # Only show statistics for the various files
25
- ["--statistics", "-s", GetoptLong::NO_ARGUMENT],
26
- # Show the total size of COW pages
27
- ["--total", "-t", GetoptLong::NO_ARGUMENT],
28
- # Ignore C++ "false positives" (vtables and typeinfo)
29
- ["--ignore-cxx", "-x", GetoptLong::NO_ARGUMENT ],
30
- # Ignore Profiling false positives
31
- ["--ignore-profiling", "-p", GetoptLong::NO_ARGUMENT ],
32
- # Ignore .data.rel.ro relocated constants
33
- ["--ignore-data-rel-ro", "-r", GetoptLong::NO_ARGUMENT ],
34
- # Decide sorting column
35
- ["--sort-by", "-S", GetoptLong::REQUIRED_ARGUMENT ]
36
- ]
23
+ module Elf::Tools
24
+ class CoWStats < Elf::Tool
37
25
 
38
- def self.before_options
39
- @statistics = false
40
- @total = false
41
- @ignore_cxx = false
42
- @ignore_profiling = false
43
- @ignore_data_rel_ro = false
26
+ def self.initialize
27
+ super
28
+ @options |= [
29
+ # Only show statistics for the various files
30
+ ["--statistics", "-s", GetoptLong::NO_ARGUMENT],
31
+ # Show the total size of COW pages
32
+ ["--total", "-t", GetoptLong::NO_ARGUMENT],
33
+ # Ignore C++ "false positives" (vtables and typeinfo)
34
+ ["--ignore-cxx", "-x", GetoptLong::NO_ARGUMENT ],
35
+ # Ignore Profiling false positives
36
+ ["--ignore-profiling", "-p", GetoptLong::NO_ARGUMENT ],
37
+ # Ignore .data.rel.ro relocated constants
38
+ ["--ignore-data-rel-ro", "-r", GetoptLong::NO_ARGUMENT ],
39
+ # Decide sorting column
40
+ ["--sort-by", "-S", GetoptLong::REQUIRED_ARGUMENT ]
41
+ ]
44
42
 
45
- @results_sorter = Proc.new do |x, y|
46
- # 0 is the filename
47
- x[0] <=> y[0]
48
- end
49
-
50
- @files_info = {}
51
- end
43
+ @statistics = false
44
+ @total = false
45
+ @ignore_cxx = false
46
+ @ignore_profiling = false
47
+ @ignore_data_rel_ro = false
52
48
 
53
- def self.sort_by_cb(column)
54
- case column
55
- when '.bss'
56
- @results_sorter = Proc.new do |x, y|
57
- x[1][:bss_size] <=> y[1][:bss_size]
58
- end
59
- when '.data'
60
- @results_sorter = Proc.new do |x, y|
61
- x[1][:data_size] <=> y[1][:data_size]
62
- end
63
- when '.data.rel'
64
- @results_sorter = Proc.new do |x, y|
65
- x[1][:rel_size] <=> y[1][:rel_size]
66
- end
67
- when '.data.rel.ro'
68
- @results_sorter = Proc.new do |x, y|
69
- x[1][:relro_size] <=> y[1][:relro_size]
70
- end
71
- else
72
- puterror "invalid sort column: #{column}"
73
- exit -1
74
- end
75
- end
49
+ @results_sorter = Proc.new do |x, y|
50
+ # 0 is the filename
51
+ x[0] <=> y[0]
52
+ end
76
53
 
77
- def self.after_options
78
- if @total
79
- @data_total = 0
80
- @bss_total = 0
81
- @rel_total = 0
82
- @relro_total = 0
83
- end
84
- end
54
+ @files_info = {}
85
55
 
86
- def self.analysis(file)
87
- data_vars = []
88
- data_size = 0
89
- bss_vars = []
90
- bss_size = 0
91
- rel_vars = []
92
- rel_size = 0
93
- relro_vars = []
94
- relro_size = 0
95
-
96
- Elf::File.open(file) do |elf|
97
- if elf.type != Elf::File::Type::Rel
98
- putnotice "#{file}: not an object file"
99
- next
56
+ @data_total = 0
57
+ @bss_total = 0
58
+ @rel_total = 0
59
+ @relro_total = 0
100
60
  end
101
- if not elf.has_section?(".symtab")
102
- putnotice "#{file}: no .symtab section found"
103
- next
104
- end
105
-
106
- elf['.symtab'].each do |symbol|
107
- # Ignore undefined, absolute and common symbols.
108
- next unless symbol.section.is_a? Elf::Section
109
- # When the symbol name is empty, it refers to the
110
- # section itself.
111
- next if symbol.name == ""
112
61
 
113
- # Ignore C++ vtables and other symbols when requested
114
- next if @ignore_cxx and symbol.name =~ /^_ZT[VI](N[0-9]+[A-Z_].*)*[0-9]+[A-Z_].*/
115
- # Ignore profiling symbols when requested by user
116
- next if @ignore_profiling and symbol.name =~ /^__gcov_/
117
-
118
- # If the section is NoBits, then it's .bss or equivalent, handle
119
- # and skip right away.
120
- if symbol.section.type == Elf::Section::Type::NoBits
121
- bss_vars << symbol unless @statistics
122
- bss_size += symbol.size
123
- next
124
- end
125
-
126
- # Ignore executable code (.text, .init, .fini)
127
- next if symbol.section.flags.include? Elf::Section::Flags::ExecInstr
128
- # Ignore read-only sections (.rodata)
129
- next unless symbol.section.flags.include? Elf::Section::Flags::Write
130
- # Ignore non-allocated sections (all data sections are allocated)
131
- next unless symbol.section.flags.include? Elf::Section::Flags::Alloc
132
-
133
- # Until I can find a way to distinguish between relocated and
134
- # non-relocated sections, still use the name to choose between
135
- # them. If the name is not in this list, at least warn now
136
- # about it.
137
- #
138
- # The “l” prefix is used by Sun's compiler for x64-specific
139
- # sections that can hold over 2GiB of data. They don't change
140
- # for what we're concerned.
141
- case symbol.section.name
142
- when /^\.l?data\.rel\.ro(\..*)?/
143
- unless @inore_data_rel_ro
144
- relro_vars << symbol unless @statistics
145
- relro_size += symbol.size
62
+ def self.sort_by_cb(column)
63
+ case column
64
+ when '.bss'
65
+ @results_sorter = Proc.new do |x, y|
66
+ x[1][:bss_size] <=> y[1][:bss_size]
67
+ end
68
+ when '.data'
69
+ @results_sorter = Proc.new do |x, y|
70
+ x[1][:data_size] <=> y[1][:data_size]
71
+ end
72
+ when '.data.rel'
73
+ @results_sorter = Proc.new do |x, y|
74
+ x[1][:rel_size] <=> y[1][:rel_size]
75
+ end
76
+ when '.data.rel.ro'
77
+ @results_sorter = Proc.new do |x, y|
78
+ x[1][:relro_size] <=> y[1][:relro_size]
146
79
  end
147
- when /^\.l?data\.rel(\..*)?/, /^\.picdata/
148
- rel_vars << symbol unless @statistics
149
- rel_size += symbol.size
150
- when /^\.l?t?data(\.local)?(\..*)?/
151
- data_vars << symbol unless @statistics
152
- data_size += symbol.size
153
80
  else
154
- puterror "symbol #{symbol.name} in unknown section #{symbol.section.name}"
81
+ puterror "invalid sort column: #{column}"
82
+ exit -1
155
83
  end
156
84
  end
157
-
158
- end
159
85
 
160
- return unless (data_size + bss_size + rel_size + relro_size ) > 0
86
+ def self.analysis(file)
87
+ data_vars = []
88
+ data_size = 0
89
+ bss_vars = []
90
+ bss_size = 0
91
+ rel_vars = []
92
+ rel_size = 0
93
+ relro_vars = []
94
+ relro_size = 0
95
+
96
+ Elf::File.open(file) do |elf|
97
+ if elf.type != Elf::File::Type::Rel
98
+ putnotice "#{file}: not an object file"
99
+ next
100
+ end
101
+ if not elf.has_section?(".symtab")
102
+ putnotice "#{file}: no .symtab section found"
103
+ next
104
+ end
161
105
 
162
- if @total
163
- @data_total += data_size
164
- @bss_total += bss_size
165
- @rel_total += rel_size
166
- @relro_total += relro_size
167
- end
168
-
169
- if @statistics
170
- @files_info[file] = {
171
- :data_size => data_size,
172
- :bss_size => bss_size,
173
- :rel_size => rel_size,
174
- :relro_size => relro_size
175
- }
176
- return
177
- end
106
+ elf['.symtab'].each do |symbol|
107
+ # Ignore undefined, absolute and common symbols.
108
+ next unless symbol.section.is_a? Elf::Section
109
+ # When the symbol name is empty, it refers to the
110
+ # section itself.
111
+ next if symbol.name == ""
178
112
 
179
- @output_mutex.synchronize do
180
- puts "Processing file #{file}"
181
-
182
- if bss_vars.length > 0
183
- puts " The following variables aren't initialised (Copy-On-Write):"
184
- bss_vars.each do |sym|
185
- puts " #{sym} (size: #{sym.size})"
186
- end
187
- end
188
-
189
- if data_vars.length > 0
190
- puts " The following variables are writable (Copy-On-Write):"
191
- data_vars.each do |sym|
192
- puts " #{sym} (size: #{sym.size})"
113
+ # Ignore C++ vtables and other symbols when requested
114
+ next if @ignore_cxx and symbol.name =~ /^_ZT[VI](N[0-9]+[A-Z_].*)*[0-9]+[A-Z_].*/
115
+ # Ignore profiling symbols when requested by user
116
+ next if @ignore_profiling and symbol.name =~ /^__gcov_/
117
+
118
+ # If the section is NoBits, then it's .bss or equivalent, handle
119
+ # and skip right away.
120
+ if symbol.section.type == Elf::Section::Type::NoBits
121
+ bss_vars << symbol unless @statistics
122
+ bss_size += symbol.size
123
+ next
124
+ end
125
+
126
+ # Ignore executable code (.text, .init, .fini)
127
+ next if symbol.section.flags.include? Elf::Section::Flags::ExecInstr
128
+ # Ignore read-only sections (.rodata)
129
+ next unless symbol.section.flags.include? Elf::Section::Flags::Write
130
+ # Ignore non-allocated sections (all data sections are allocated)
131
+ next unless symbol.section.flags.include? Elf::Section::Flags::Alloc
132
+
133
+ # Until I can find a way to distinguish between relocated and
134
+ # non-relocated sections, still use the name to choose between
135
+ # them. If the name is not in this list, at least warn now
136
+ # about it.
137
+ #
138
+ # The “l” prefix is used by Sun's compiler for x64-specific
139
+ # sections that can hold over 2GiB of data. They don't change
140
+ # for what we're concerned.
141
+ case symbol.section.name
142
+ when /^\.l?data\.rel\.ro(\..*)?/
143
+ unless @inore_data_rel_ro
144
+ relro_vars << symbol unless @statistics
145
+ relro_size += symbol.size
146
+ end
147
+ when /^\.l?data\.rel(\..*)?/, /^\.picdata/
148
+ rel_vars << symbol unless @statistics
149
+ rel_size += symbol.size
150
+ when /^\.l?t?data(\.local)?(\..*)?/
151
+ data_vars << symbol unless @statistics
152
+ data_size += symbol.size
153
+ else
154
+ puterror "symbol #{symbol.name} in unknown section #{symbol.section.name}"
155
+ end
156
+ end
157
+
193
158
  end
194
- end
195
-
196
- if rel_vars.length > 0
197
- puts " The following variables need runtime relocation (Copy-On-Write):"
198
- rel_vars.each do |sym|
199
- puts " #{sym} (size: #{sym.size})"
159
+
160
+ return unless (data_size + bss_size + rel_size + relro_size ) > 0
161
+
162
+ if @total
163
+ @data_total += data_size
164
+ @bss_total += bss_size
165
+ @rel_total += rel_size
166
+ @relro_total += relro_size
200
167
  end
201
- end
202
-
203
- if relro_vars.length > 0
204
- puts " The following constants need runtime relocation (Prelinkable Copy-On-Write):"
205
- relro_vars.each do |sym|
206
- puts " #{sym} (size: #{sym.size})"
168
+
169
+ if @statistics
170
+ @files_info[file] = {
171
+ :data_size => data_size,
172
+ :bss_size => bss_size,
173
+ :rel_size => rel_size,
174
+ :relro_size => relro_size
175
+ }
176
+ return
207
177
  end
208
- end
209
-
210
- if @total
211
- puts " Total non-initialised variables size: #{bss_size}" unless bss_size == 0
212
- puts " Total writable variables size: #{data_size}" unless data_size == 0
213
- puts " Total variables needing runtime relocation size: #{rel_size}" unless rel_size == 0
214
- unless @ignore_data_rel_ro
215
- puts " Total constants needing runtime relocation size: #{relro_size}" unless relro_size == 0
178
+
179
+ @output_mutex.synchronize do
180
+ puts "Processing file #{file}"
181
+
182
+ if bss_vars.length > 0
183
+ puts " The following variables aren't initialised (Copy-On-Write):"
184
+ bss_vars.each do |sym|
185
+ puts " #{sym} (size: #{sym.size})"
186
+ end
187
+ end
188
+
189
+ if data_vars.length > 0
190
+ puts " The following variables are writable (Copy-On-Write):"
191
+ data_vars.each do |sym|
192
+ puts " #{sym} (size: #{sym.size})"
193
+ end
194
+ end
195
+
196
+ if rel_vars.length > 0
197
+ puts " The following variables need runtime relocation (Copy-On-Write):"
198
+ rel_vars.each do |sym|
199
+ puts " #{sym} (size: #{sym.size})"
200
+ end
201
+ end
202
+
203
+ if relro_vars.length > 0
204
+ puts " The following constants need runtime relocation (Prelinkable Copy-On-Write):"
205
+ relro_vars.each do |sym|
206
+ puts " #{sym} (size: #{sym.size})"
207
+ end
208
+ end
209
+
210
+ if @total
211
+ puts " Total non-initialised variables size: #{bss_size}" unless bss_size == 0
212
+ puts " Total writable variables size: #{data_size}" unless data_size == 0
213
+ puts " Total variables needing runtime relocation size: #{rel_size}" unless rel_size == 0
214
+ unless @ignore_data_rel_ro
215
+ puts " Total constants needing runtime relocation size: #{relro_size}" unless relro_size == 0
216
+ end
217
+ end
216
218
  end
217
219
  end
218
- end
219
- end
220
220
 
221
- def self.results
222
- if @statistics
223
- file_lengths = ["File name".length]
224
- bss_lengths = [".bss size".length]
225
- data_lengths = [".data size".length]
226
- rel_lengths = [".data.rel size".length]
227
- relro_lengths = [".data.rel.ro size".length] unless @no_datalrero
228
- @files_info.each_pair do |file, info|
229
- file_lengths << file.length
230
- bss_lengths << info[:bss_size] .to_s.length
231
- data_lengths << info[:data_size].to_s.length
232
- rel_lengths << info[:rel_size] .to_s.length
233
- relro_lengths<< info[:relro_size] .to_s.length
234
- end
221
+ def self.results
222
+ if @statistics
223
+ file_lengths = ["File name".length]
224
+ bss_lengths = [".bss size".length]
225
+ data_lengths = [".data size".length]
226
+ rel_lengths = [".data.rel size".length]
227
+ relro_lengths = [".data.rel.ro size".length] unless @no_datalrero
228
+ @files_info.each_pair do |file, info|
229
+ file_lengths << file.length
230
+ bss_lengths << info[:bss_size] .to_s.length
231
+ data_lengths << info[:data_size].to_s.length
232
+ rel_lengths << info[:rel_size] .to_s.length
233
+ relro_lengths<< info[:relro_size] .to_s.length
234
+ end
235
235
 
236
- maxlen = file_lengths.max
237
- max_bss_len = bss_lengths .max
238
- max_data_len = data_lengths.max
239
- max_rel_len = rel_lengths .max
240
- max_relro_len= relro_lengths .max
236
+ maxlen = file_lengths.max
237
+ max_bss_len = bss_lengths .max
238
+ max_data_len = data_lengths.max
239
+ max_rel_len = rel_lengths .max
240
+ max_relro_len= relro_lengths .max
241
241
 
242
- datarelro_header = @ignore_data_rel_ro ? "" : " | #{'.data.rel.ro size'.ljust max_relro_len}"
243
- puts "#{'File name'.ljust maxlen} | #{'.bss size'.ljust max_data_len} | #{'.data size'.ljust max_data_len} | #{'.data.rel size'.ljust max_rel_len}#{datarelro_header}"
242
+ datarelro_header = @ignore_data_rel_ro ? "" : " | #{'.data.rel.ro size'.ljust max_relro_len}"
243
+ puts "#{'File name'.ljust maxlen} | #{'.bss size'.ljust max_data_len} | #{'.data size'.ljust max_data_len} | #{'.data.rel size'.ljust max_rel_len}#{datarelro_header}"
244
244
 
245
- (@files_info.sort &@results_sorter).each do |file, info|
246
- datarelro_line = @ignore_data_rel_ro ? "" : " #{info[:relro_size].to_s.rjust max_relro_len}"
247
- puts "#{file.ljust maxlen} #{info[:bss_size].to_s.rjust max_bss_len} #{info[:data_size].to_s.rjust max_data_len} #{info[:rel_size].to_s.rjust max_rel_len}#{datarelro_line}"
248
- end
249
- end
245
+ (@files_info.sort &@results_sorter).each do |file, info|
246
+ datarelro_line = @ignore_data_rel_ro ? "" : " #{info[:relro_size].to_s.rjust max_relro_len}"
247
+ puts "#{file.ljust maxlen} #{info[:bss_size].to_s.rjust max_bss_len} #{info[:data_size].to_s.rjust max_data_len} #{info[:rel_size].to_s.rjust max_rel_len}#{datarelro_line}"
248
+ end
249
+ end
250
250
 
251
- if @total
252
- data_total_real = @data_total > 0 ? ((@data_total/4096) + (@data_total % 4096 ? 1 : 0)) * 4096 : 0
253
- bss_total_real = @bss_total > 0 ? ((@bss_total/4096) + (@bss_total % 4096 ? 1 : 0)) * 4096 : 0
254
- rel_total_real = @rel_total > 0 ? ((@rel_total/4096) + (@rel_total % 4096 ? 1 : 0)) * 4096 : 0
255
- relro_total_real = @relro_total > 0 ? ((@relro_total/4096) + (@relro_total % 4096 ? 1 : 0)) * 4096 : 0
251
+ if @total
252
+ data_total_real = @data_total > 0 ? ((@data_total/4096) + (@data_total % 4096 ? 1 : 0)) * 4096 : 0
253
+ bss_total_real = @bss_total > 0 ? ((@bss_total/4096) + (@bss_total % 4096 ? 1 : 0)) * 4096 : 0
254
+ rel_total_real = @rel_total > 0 ? ((@rel_total/4096) + (@rel_total % 4096 ? 1 : 0)) * 4096 : 0
255
+ relro_total_real = @relro_total > 0 ? ((@relro_total/4096) + (@relro_total % 4096 ? 1 : 0)) * 4096 : 0
256
256
 
257
- puts "Totals:"
258
- puts " #{@bss_total} (#{bss_total_real} \"real\") bytes of non-initialised variables."
259
- puts " #{@data_total} (#{data_total_real} \"real\") bytes of writable variables."
260
- puts " #{@rel_total} (#{rel_total_real} \"real\") bytes of variables needing runtime relocation."
261
- puts " #{@relro_total} (#{relro_total_real} \"real\") bytes of constants needing runtime relocation." unless @no_datalrero
262
- puts " Total #{@data_total+@bss_total+@rel_total+@relro_total} (#{data_total_real+bss_total_real+rel_total_real+relro_total_real} \"real\") bytes of variables in copy-on-write sections"
257
+ puts "Totals:"
258
+ puts " #{@bss_total} (#{bss_total_real} \"real\") bytes of non-initialised variables."
259
+ puts " #{@data_total} (#{data_total_real} \"real\") bytes of writable variables."
260
+ puts " #{@rel_total} (#{rel_total_real} \"real\") bytes of variables needing runtime relocation."
261
+ puts " #{@relro_total} (#{relro_total_real} \"real\") bytes of constants needing runtime relocation." unless @no_datalrero
262
+ puts " Total #{@data_total+@bss_total+@rel_total+@relro_total} (#{data_total_real+bss_total_real+rel_total_real+relro_total_real} \"real\") bytes of variables in copy-on-write sections"
263
+ end
264
+ end
263
265
  end
264
266
  end