175 lines
5.6 KiB
Python
Executable File
175 lines
5.6 KiB
Python
Executable File
#! /usr/bin/env python
|
|
|
|
#
|
|
# Copyright (c) 2015 Wind River Systems, Inc.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
#
|
|
# 1) Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions and the following disclaimer.
|
|
#
|
|
# 2) Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions and the following disclaimer in the documentation
|
|
# and/or other materials provided with the distribution.
|
|
#
|
|
# 3) Neither the name of Wind River Systems nor the names of its contributors
|
|
# may be used to endorse or promote products derived from this software without
|
|
# specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
|
|
# Arguments:
|
|
# - name of ELF image
|
|
|
|
# Output:
|
|
# - sends section and RAM/ROM usage to standard output
|
|
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
|
|
xip_rom_size = 0 # XIP ROM usage in bytes
|
|
xip_ram_size = 0 # XIP RAM usage in bytes
|
|
ram_size = 0 # non-XIP RAM usage in bytes
|
|
|
|
objdump_list = [] # data gleaned from "objdump -h"
|
|
|
|
|
|
def is_xip(filename):
|
|
""" Determine if image is configured for XIP """
|
|
|
|
# Search for CONFIG_XIP in the ELF's list of symbols using NM and AWK.
|
|
# GREP can not be used as it returns an error if the symbol is not found.
|
|
is_xip_command = "nm " + filename + " | awk '/CONFIG_XIP/ { print $3 }'"
|
|
|
|
is_xip_output = subprocess.check_output(is_xip_command, shell=True)
|
|
|
|
return (len(is_xip_output) != 0)
|
|
|
|
|
|
def calculate_sizes(filename):
|
|
""" Calculate RAM and ROM usage by section """
|
|
|
|
global ram_size
|
|
global xip_rom_size
|
|
global xip_ram_size
|
|
|
|
objdump_command = "objdump -h " + filename
|
|
objdump_output = subprocess.check_output(objdump_command,
|
|
shell=True).splitlines()
|
|
|
|
for line in objdump_output:
|
|
words = line.split()
|
|
|
|
if (len(words) == 0): # Skip lines that are too short
|
|
continue
|
|
|
|
index = words[0]
|
|
if (not index[0].isdigit()): # Skip lines that do not start
|
|
continue # with a digit
|
|
|
|
name = words[1] # Skip lines with section names
|
|
if (name[0] == '.'): # starting with '.'
|
|
continue
|
|
|
|
size = int(words[2], 16)
|
|
phys_addr = int(words[4], 16)
|
|
|
|
# Add section to memory use totals (for both non-XIP and XIP scenarios)
|
|
#
|
|
# In an XIP image, the following sections are placed into ROM:
|
|
# text, ctors, rodata and datas
|
|
# In an XIP image, the following sections are placed into RAM:
|
|
# datas, bss and noinit
|
|
# In a non-XIP image, the following sections are placed into RAM
|
|
# text, ctors, rodata, datas, bss and noinit
|
|
#
|
|
# Unrecognized section names are tagged with the '*' character
|
|
# and are not included in the calculations.
|
|
|
|
ram_size += size
|
|
|
|
if ((name == "text") or (name == "ctors") or (name == "rodata")):
|
|
xip_rom_size += size
|
|
elif (name == "datas"):
|
|
xip_rom_size += size
|
|
xip_ram_size += size
|
|
elif ((name == "bss") or (name == "noinit")):
|
|
xip_ram_size += size
|
|
else:
|
|
name += "*" # Unrecognized section
|
|
ram_size -= size # Undo the calculation
|
|
|
|
objdump_list.append("%-17s 0x%08x %8d %5x" %
|
|
(name, phys_addr, size, size))
|
|
|
|
|
|
def display_sizes(filename):
|
|
""" Display the section and memory usage """
|
|
|
|
print("SECTION NAME ADDRESS SIZE HEX")
|
|
|
|
for line in objdump_list:
|
|
print(line)
|
|
print
|
|
|
|
if (is_xip(filename)):
|
|
print("Total: %d bytes (ROM) + %d bytes (RAM)" %
|
|
(xip_rom_size, xip_ram_size))
|
|
else:
|
|
print("Total: %d bytes (RAM)" % ram_size)
|
|
|
|
|
|
def is_elf(filename):
|
|
""" Determine if 'filename' is an ELF image file """
|
|
|
|
magic = 0
|
|
|
|
with open(filename, "rb") as f:
|
|
magic = f.read(4)
|
|
|
|
return (magic == "\x7fELF")
|
|
|
|
|
|
def display_help():
|
|
""" Display tool help information """
|
|
|
|
print("Usage: truesize <elf_file>")
|
|
print("Display section information and calculated memory usage.")
|
|
print("Unrecognized sections are tagged with '*' and are not included")
|
|
print("in the calculations.")
|
|
|
|
|
|
def sanitize_arguments():
|
|
""" Perform sanity checks on the command line arguments """
|
|
|
|
# Ensures that the correct number of arguments is supplied to the tool and
|
|
# that the specified file is an ELF image.
|
|
|
|
if ((len(sys.argv) != 2) or (not is_elf(sys.argv[1]))):
|
|
display_help()
|
|
sys.exit(1)
|
|
|
|
|
|
###############################################################################
|
|
#
|
|
# TRUESIZE MAINLINE
|
|
#
|
|
|
|
|
|
sanitize_arguments()
|
|
calculate_sizes(sys.argv[1])
|
|
display_sizes(sys.argv[1])
|