Add pager options to mem_usage.py
Adds options to report the size of the init, paged and unpaged areas
in pager builds (CFG_WITH_PAGER=y). This is helpful to monitor the
evolution of the code size, and identify issues such as when useless
functions get pulled into the unpaged area by mistake.
For instance, here is what we can get with 'mem_usage.py -nUr' and a
few lines of script (shows changes in the size of unpaged code and
data for a non-debug qemu_virt build since 2.5.0):
2.5.0 67600
2.5.0-2-g0b8e6e78 67632 +32 core: abort: fix get_fault_type()
2.5.0-11-g87d96185 67728 +96 core: pager: avoid page faults with pager lock held
2.5.0-37-g0073c9a8 67792 +64 core: pager: optimize tee_pager_handle_fault()
2.5.0-40-g935ac3ec 67888 +96 core: arm32: handle aborts in system mode
2.5.0-53-g2e4e94bf 67920 +32 core: default enable program flow prediction on ARMv7 cores
2.5.0-57-ge84e1fec 67704 -216 core: clean and unwind arm32_aeabi_[l]divmod_a32.S
2.5.0-63-g23346f16 67736 +32 Add support for several user TA stores
2.5.0-76-gb2087a20 67608 -128 core: pager: deal with large CFG_TEE_RAM_VA_SIZE
2.5.0-77-g00aa47a4 67688 +80 core: plat-vexpress: increase CFG_TEE_RAM_VA_SIZE
2.5.0-112-g86e50a60 67696 +8 core: arm: psci: add suspend resume common functions
2.5.0-120-g13b3ee90 67768 +72 core: print rwx flags for each MMU region when a user TA aborts
2.5.0-122-ge61644fb 83408 +15640 core: make reset_secondary() unpaged
2.5.0-123-g1506eb6f 83424 +16 core: plat-vexpress: init gic on secondary cores
2.5.0-124-ge2b68c87 91368 +7944 core: plat-vextpress-qemu_virt: update num cores
2.5.0-126-g5402a9fe 92808 +1440 qemu_virt: enable smp boot
2.5.0-132-gda51216b 92840 +32 dts: pass PA of reserved region
2.5.0-173-gb4121bfb 92848 +8 pl011: prevent putc() and flush() function from blocking indefinitely
2.5.0-176-g55d6853c 92912 +64 core: add registered shared memory support
2.5.0-182-g93d3c451 163936 +71024 core: pager: ltc: prng: add entropy to the AE key for paged TAs
2.5.0-202-ga71af55e 163984 +48 core: mobj: add mobj_get_phys_offs()
2.5.0-203-g5c7a19bb 163968 -16 core: mobj: remove double physical offset
2.5.0-205-g430dcbd8 163944 -24 core: reimplement mobj_mapped_shm_alloc()
2.5.0-208-gbbed97b6 163976 +32 core:mmu: fix userland va2pa conversion
2.5.0-209-g42d91b4b 164040 +64 core:mmu: fix userland pa2va conversion
2.6.0-rc1-1-gb6449075 164136 +96 thread.c: free rpc arg mobj during cache disabling
2.6.0-7-g8473540d 77144 -86992 Keep assembly functions in separate sections
2.6.0-8-g64113fca 77112 -32 core: arm32: replace _start with reset() function
2.6.0-9-g486754e8 77176 +64 core: arm32: reset_secondary() set reset vector
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Volodymyr Babchuk <vlad.babchuk@gmail.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Acked-by Etienne Carriere <etienne.carriere@linaro.org>
diff --git a/scripts/mem_usage.py b/scripts/mem_usage.py
index 4309314..8b7faf0 100755
--- a/scripts/mem_usage.py
+++ b/scripts/mem_usage.py
@@ -12,10 +12,31 @@
def get_args():
- parser = argparse.ArgumentParser(
- description='Shows the memory layout of the TEE ELF file. '
- 'Size is provided for each section.')
- parser.add_argument('tee_elf', help='The OP-TEE ELF file (tee.elf)')
+ parser = argparse.ArgumentParser(description='Shows the memory usage '
+ 'of an OP-TEE based on ELF sections')
+ parser.add_argument('tee_elf', help='the OP-TEE ELF file (tee.elf)')
+ parser.add_argument('-a', '--all', action='store_true',
+ help=' same as -i -p -u -U')
+ parser.add_argument('-n', '--no-map', action='store_true',
+ help=' do not show the detailed section mappings and '
+ 'RAM usage')
+ parser.add_argument('-i', '--init', action='store_true',
+ help='report the total size of the .*_init sections')
+ parser.add_argument('-p', '--paged', action='store_true',
+ help='report the total size of the .*_pageable '
+ 'sections')
+ parser.add_argument('-u', '--unpaged', action='store_true',
+ help='report the total size of the unpaged sections, '
+ 'that is, all sections but the ones in --init or '
+ '--paged')
+ parser.add_argument('-U', '--unpaged-no-heap', action='store_true',
+ help='report the size of all unpaged sections '
+ 'excluding heap space. Reflects the size of unpaged '
+ 'code and data (.text, .rodata, .data, .bss, .nozi '
+ 'and possibly unwind tables)')
+ parser.add_argument('-r', '--raw', action='store_true',
+ help='when processing -i, -p, -u, or -U, show only '
+ 'the size (in decimal) and no other text')
return parser.parse_args()
@@ -24,6 +45,8 @@
def print_sect(name, addr, size, round_up=False, print_num_pages=False):
+ if args.no_map:
+ return
if size == 0:
size_kib = 0
num_pages = 0
@@ -41,13 +64,27 @@
printf('\n')
+def print_pager_stat(name, size):
+ size_kib = size / 1024
+ if args.raw:
+ printf('%d ', size)
+ else:
+ printf('%-36s size %.8X %3d KiB\n', name, size, size_kib)
+
+
def readelf_cmd():
return os.getenv('CROSS_COMPILE', '') + 'readelf'
def main():
+ global args
+
in_shdr = False
sects = []
+ init_size = 0
+ paged_size = 0
+ unpaged_size = 0
+ unpaged_no_heap_size = 0
args = get_args()
env = os.environ.copy()
@@ -96,9 +133,30 @@
print_sect('*hole*', last_addr + last_size,
addr - (last_addr + last_size))
print_sect(name, addr, size)
+ if name.endswith('_init'):
+ init_size += size
+ elif name.endswith('_pageable'):
+ paged_size += size
+ else:
+ if not name.startswith('.heap'):
+ unpaged_no_heap_size += size
+ unpaged_size += size
last_addr = addr
last_size = size
+ if args.all or args.init:
+ print_pager_stat('Init sections (.*_init)', init_size)
+ if args.all or args.paged:
+ print_pager_stat('Paged sections (.*_pageable)', paged_size)
+ if args.all or args.unpaged:
+ print_pager_stat('Unpaged sections ', unpaged_size)
+ if args.all or args.unpaged_no_heap:
+ print_pager_stat('Unpaged sections (heap excluded)',
+ unpaged_no_heap_size)
+ if (args.raw and (args.all or args.init or args.paged or
+ args.unpaged or args.unpaged_no_heap)):
+ printf('\n')
+
if __name__ == "__main__":
main()