1
0
mirror of https://github.com/RPCSX/xed.git synced 2025-04-16 13:39:56 +00:00
Mark Charney ea2ea38f3e elf_sizes: Popen() universal_newlines and exception syntax (linux)
Change-Id: I9bd658ba6c1ec82c28cd062a9118b74d2a9dd66e
(cherry picked from commit e93dabbc58bcb2c4a93c0eac34d6c5cfc9d1195a)
2017-06-12 14:41:25 -04:00

177 lines
4.6 KiB
Python
Executable File

#!/usr/bin/env python
# -*- python -*-
#BEGIN_LEGAL
#
#Copyright (c) 2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#END_LEGAL
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()
# unexpected input happens
try:
x = int(chunks[5],16)
except:
x = 0 # just don't die for now
data[key] = x
return data
def _read64(fn,die_on_errors):
output = _run_readelf_sections(fn,die_on_errors)
if not output:
return None
# in 64b the size is on the next line after the key is located.
key = None
data = {}
for line in output:
line = line.strip()
if key:
chunks = line.split()
# unexpected input happens
try:
x = int(chunks[0],16)
except:
x = 0 # just don't die for now
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: # avoid div/0
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)