from __future__ import print_function
import os
import sys
import subprocess
import find_dir
try:
import mbuild
except:
sys.path.append(find_dir.find_dir('mbuild'))
import mbuild
def _warn(s):
sys.stderr.write("ERROR:" + s + "\n")
def _die(s):
_warn(s)
sys.exit(1)
def _run_cmd(cmd, die_on_errors=True):
try:
sub = subprocess.Popen(cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True)
lines = sub.stdout.readlines()
sub.wait()
return (sub.returncode, lines)
except OSError as e:
msg = "Execution failed for:" + str( cmd) + ".\nResult is " + str(e)
if die_on_errors:
_die(msg)
else:
return (1,[msg])
def _run_readelf_sections(fn,die_on_errors):
cmd = 'readelf -S ' + fn
(retval, output) = _run_cmd(cmd, die_on_errors)
if retval:
for line in output:
line = line.strip()
_warn(line)
return None
return output
def _find_key(line):
key = None
if line.find('.text') != -1:
key='text'
if line.find('.rodata') != -1:
key='rodata'
if line.find('.data') != -1:
key='data'
if line.find('.bss') != -1:
key='bss'
return key
def _read32(fn,die_on_errors):
output = _run_readelf_sections(fn,die_on_errors)
if not output:
return None
key = None
data = {}
for line in output:
line = line.strip()
key = _find_key(line)
if key:
chunks = line.split()
try:
x = int(chunks[5],16)
except:
x = 0 data[key] = x
return data
def _read64(fn,die_on_errors):
output = _run_readelf_sections(fn,die_on_errors)
if not output:
return None
key = None
data = {}
for line in output:
line = line.strip()
if key:
chunks = line.split()
try:
x = int(chunks[0],16)
except:
x = 0 data[key] = x
key = _find_key(line)
return data
def print_table(data):
python27 = mbuild.check_python_version(2,7)
fmt_str27 = "{0:10s} {1:10,d} Bytes {2:5.2f} MB {3:10.2f}%"
fmt_str = "%10s %10d Bytes %5.2f MB %10.2f%%"
keys = list(data.keys())
keys.sort()
total = 0
for k in keys:
total = total + data[k]
for k in keys:
try: pct = 100.0 * data[k] / total
except:
pct = 0
mb = data[k]/1024.0/1024.0
if python27:
print(fmt_str27.format(k,data[k],mb,pct))
else:
print(fmt_str % (k,data[k],mb,pct))
mb = total/1024.0/1024.0
if python27:
print(fmt_str27.format('total', total, mb, 100))
else:
print(fmt_str % ('total', total, mb, 100))
def _find_mode(fn,die_on_errors):
cmd = 'readelf -h ' + fn
(retval, header) = _run_cmd(cmd, die_on_errors)
mode = 0
if retval == 0:
for line in header:
if 'Class:' in line:
if 'ELF32' in line:
mode=32
break
elif 'ELF64' in line:
mode=64
break
return mode
def work(fn,die_on_errors=True):
mode = _find_mode(fn,die_on_errors)
if mode == 64:
return _read64(fn,die_on_errors)
elif mode == 32:
return _read32(fn,die_on_errors)
return None
if __name__ == '__main__':
if len(sys.argv) != 2:
_die("Need one arg")
fn = sys.argv[1]
d = work(fn)
if d:
print_table(d)