Hmm. Mostly I use "objdump --syms" and chew on the output with a ruby
script.
Here is the script, it's way too specific to our project to be
reusable, and it chews on the output of gcc 2.95 sparc tools.
But you could tweak it (lots)....
Some hints...
We had a particular interest in certain symbols with the name
"dspstd" hence the flocks of extra code in looking at that. Ignore
everything to do with dspstd, just chop it out. (Or use the code for
watching special classes of symbols)
Note the use of gdb (write a command file, run gdb, parse result) to
look inside the executable to find certain compiler computed values.
======================================================================
#!/usr/bin/ruby -w
require 'fileutils'
require 'pp'
if ENV.has_key? "TMPDIR"
TMPDIR = ENV["TMPDIR"]
else
TMPDIR = "/tmp"
end
def print_help_and_exit(plaint="Usage:-")
puts "
#{plaint}
#{File.basename(__FILE__)} [options] ELF_EXECUTABLE+
Computes all static size metrics it can for tha executable.
-? --help This message
"
exit(1)
end
class Hash
def keys_sorted_by_value
keys.sort_by{|k| fetch(k)}
end
def top_keys_by_value(too_small)
keys.find_all{|k| fetch(k) >= too_small}.sort_by{|k| fetch(k)}
end
end
class ResourceUtilization
def initialize( elf, too_small_ram = 512, too_small_rom = 1024,
too_small_dspstd=100)
@elf = elf
@too_small_ram = too_small_ram
@too_small_rom = too_small_rom
@too_small_dspstd = too_small_dspstd
@ram = {}
@rom = {}
@dspstd = {}
end
def elf_size( elf_size = File.read("|sparc-rtems-size [EMAIL PROTECTED]"))
raise "Size output syntax error" unless
elf_size =~ %r{
^ \s+ text \s+ data \s+ bss \s+ dec\s+ hex \s+ filename \n
\s* (\d+) \s+ (\d+) \s+ (\d+) \s+ (\d+) \s+ ([0-9a-fA-F]+) \s .*? [EMAIL
PROTECTED] }x
@text, @data, @bss, dec, hex = $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.hex
raise "Unexpected values dec #{dec} != hex #{hex}" unless
dec == hex
end
def report( io)
io.printf( "
[EMAIL
PROTECTED](%r{#{ENV['HOME']}/|TaitTerm_Base/bld/leon/rom/uninstrumented/},'')}
Text segment: %7.2f Kb
Data segment: %7.2f Kb
BSS segment: %7.2f Kb
Code & Data
Rom Usage : %7.2f Kb
Ram Usage : %7.2f Kb
Total Database partition usage : %7d bytes
Greediest ram symbols >= [EMAIL PROTECTED]
",
@text/1024.0, @data/1024.0, @bss/1024.0,
(@[EMAIL PROTECTED])/1024.0, (@[EMAIL PROTECTED])/1024.0,
@dspstd_total
)
@ram.top_keys_by_value(@too_small_ram).each do |symbol|
size = @ram[symbol]
printf( "%50s\t%7.4f Kb\n", symbol, size / 1024.0)
end
puts "
Greediest rom consuming symbols >= [EMAIL PROTECTED]"
@rom.top_keys_by_value(@too_small_rom).each do |symbol|
size = @rom[symbol]
printf( "%50s\t%7.4f Kb\n", symbol, size / 1024.0)
end
puts "
Greediest Persistent data partition consuming symbols >= [EMAIL PROTECTED]"
@dspstd.top_keys_by_value(@too_small_dspstd).each do |symbol|
size = @dspstd[symbol]
printf( "%50s\t%7d bytes\n",
symbol.sub(%r{LINK_TIME_DESIGNATED_ITEM_dspstd_},''),
size)
end
puts ""
end
NONE = 0
ROM = 1
RAM = 2
SEGMENTS = {
'*ABS*' => NONE,
'*UND*' => NONE,
'.bss' => RAM,
'.data' => ROM | RAM,
'.f_entry' => ROM,
'.fini' => ROM,
'.fixup' => ROM,
'.gcc_except_table' => ROM | RAM,
'.leoncodef' => ROM,
'.rodata' => ROM,
'.rodata1' => ROM,
'.rom_vectors' => ROM,
'.romram' => ROM | RAM,
'.stab' => NONE,
'.stabstr' => NONE,
'.text' => ROM,
'check_fits_rom' => NONE}
SEGMENTS_REGEX = "(#{SEGMENTS.keys.sort.join("|")})".gsub(%r{([.*])},
'\\\\\1')
def elf_syms(elf_io = open( "|sparc-rtems-objdump --syms [EMAIL PROTECTED]"))
elf_io.each do |line|
#12345678 12345678
#000dd7a0 l F .text 0000003c
pscvcp_OutgoingTransferProcessingOutgoingInfoStateAction
if line =~ %r{ ^([0-9a-fA-F]{8}) \s+ (\S+) \s+ (.+?) \s+
(0[0-9a-fA-F]{7}) \s+ (.*) }x
address, lgw, flags, size, symbol = $1.hex, $2, $3, $4.hex, $5
if flags =~ %r{ (?:(F|O|d|df) \s+)? #{SEGMENTS_REGEX}}x
# puts l unless "lgw".index(l)
flag,segment = $1, $2
usage = SEGMENTS[segment]
@ram[symbol] = size if usage&RAM == RAM
@rom[symbol] = size if usage&ROM == ROM
if symbol =~ %r{ LINK_TIME_DESIGNATED_([A-Z]+)_dspstd_(.*) }ix
type, sub_symbol = $1, $2
# p
[type,sub_symbol,size,segment,sprintf("%x",address),address]
# @dspstd_ram += size
# @dspstd_rom += size
if type == 'ITEM'
# @dspstd_rom += size
@dspstd[symbol] = nil
elsif type == 'HANDLE'
elsif type == 'SERVICE'
elsif type == 'MAXIMUM'
else
raise "Unexpected type '#{type}', expected one of [ITEM,HANDLE]"
end
end
else
puts "WEIRD! #{line}"
end
end
end
ensure
elf_io.close
end
def dspstd_size
command_file = "#{TMPDIR}/gdb_command.#{Process.pid}"
syms = @dspstd.keys.sort
open( command_file, 'w') do |cmdf|
syms.each do |sym|
cmdf.puts "p ((dspstd_itemConfiguration_t *)#{sym})->sizeBytes"
end
cmdf.puts "quit"
end
gdb = "sparc-rtems-gdb --quiet --nx --batch --command=#{command_file} [EMAIL
PROTECTED]"
result = `#{gdb}`
i = 1
@dspstd_total = 0
result.scan(%r{\$ (\d+) \s+=\s+ (\d+)\n}x) do |match|
j = $1.to_i
sizeBytes = $2.to_i
raise "gdb output syntax error expected '#{i} = sizeBytes, got $0" unless
i == j
@dspstd[syms[i-1]] = sizeBytes
@dspstd_total += sizeBytes
i += 1
end
end
end
print_help_and_exit( "Insufficient arguments") if ARGV.length <= 0
arg = ARGV.shift
print_help_and_exit if arg =~ %r{ ^--?(\?|h(e(lp?)?)?) $ }x
ARGV.unshift arg
ARGV.each do |arg|
ru = ResourceUtilization.new(arg)
ru.elf_size
ru.elf_syms
ru.dspstd_size
ru.report(STDOUT)
end
On Mon, 21 May 2007, Chris Bayley wrote:
Hi team, I am looking for a utility that will give me a really powerful
look into the memory usage of my elf binaries
What I want to do is something like this:
first extract all the symbols and size information using nm -S,
then graph the information with an expression in section terms ie
(.text|.rodata) vs. an expression in symbol terms ie. symbols starting
('rtos_[.+]|gui_[.+])
thus the above example would show me the combined ROM useage of all
the sybols being with 'rtos_' or 'gui_'.
even cooler would be then to present the information in a pie chart
fromat like 'filelight' or konqueror's 'radial view' does with the
ability to drill down and look in more detail at a given area.
If you are a programmer and can identify the need I refer to above what
are the tools you are already using to glen this kind of analysis of
memory usage in your programs ??
What I am aiming at here is a powerful tool which will help show me
where to take a scalpel to a slightly overweight binary constructed from
1000 objects.
Regards,
Chris
John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : [EMAIL PROTECTED]
New Zealand