1abaf1209SJerome Forissier#!/usr/bin/env python3 2abaf1209SJerome Forissier# 3abaf1209SJerome Forissier# Copyright (c) 2014-2017, Linaro Limited 4abaf1209SJerome Forissier# 5abaf1209SJerome Forissier# SPDX-License-Identifier: BSD-3-Clause 6abaf1209SJerome Forissier 7abaf1209SJerome Forissierimport argparse 8abaf1209SJerome Forissierimport os 9abaf1209SJerome Forissierimport subprocess 10abaf1209SJerome Forissierimport sys 11abaf1209SJerome Forissier 12abaf1209SJerome Forissier 13abaf1209SJerome Forissierdef get_args(): 143be7773fSJerome Forissier parser = argparse.ArgumentParser(description='Shows the memory usage ' 153be7773fSJerome Forissier 'of an OP-TEE based on ELF sections') 163be7773fSJerome Forissier parser.add_argument('tee_elf', help='the OP-TEE ELF file (tee.elf)') 173be7773fSJerome Forissier parser.add_argument('-a', '--all', action='store_true', 183be7773fSJerome Forissier help=' same as -i -p -u -U') 193be7773fSJerome Forissier parser.add_argument('-n', '--no-map', action='store_true', 203be7773fSJerome Forissier help=' do not show the detailed section mappings and ' 213be7773fSJerome Forissier 'RAM usage') 223be7773fSJerome Forissier parser.add_argument('-i', '--init', action='store_true', 233be7773fSJerome Forissier help='report the total size of the .*_init sections') 243be7773fSJerome Forissier parser.add_argument('-p', '--paged', action='store_true', 253be7773fSJerome Forissier help='report the total size of the .*_pageable ' 263be7773fSJerome Forissier 'sections') 273be7773fSJerome Forissier parser.add_argument('-u', '--unpaged', action='store_true', 283be7773fSJerome Forissier help='report the total size of the unpaged sections, ' 293be7773fSJerome Forissier 'that is, all sections but the ones in --init or ' 303be7773fSJerome Forissier '--paged') 313be7773fSJerome Forissier parser.add_argument('-U', '--unpaged-no-heap', action='store_true', 323be7773fSJerome Forissier help='report the size of all unpaged sections ' 333be7773fSJerome Forissier 'excluding heap space. Reflects the size of unpaged ' 343be7773fSJerome Forissier 'code and data (.text, .rodata, .data, .bss, .nozi ' 353be7773fSJerome Forissier 'and possibly unwind tables)') 363be7773fSJerome Forissier parser.add_argument('-r', '--raw', action='store_true', 373be7773fSJerome Forissier help='when processing -i, -p, -u, or -U, show only ' 383be7773fSJerome Forissier 'the size (in decimal) and no other text') 39abaf1209SJerome Forissier return parser.parse_args() 40abaf1209SJerome Forissier 41abaf1209SJerome Forissier 42abaf1209SJerome Forissierdef printf(format, *args): 43abaf1209SJerome Forissier sys.stdout.write(format % args) 44abaf1209SJerome Forissier 45abaf1209SJerome Forissier 46abaf1209SJerome Forissierdef print_sect(name, addr, size, round_up=False, print_num_pages=False): 473be7773fSJerome Forissier if args.no_map: 483be7773fSJerome Forissier return 49abaf1209SJerome Forissier if size == 0: 50abaf1209SJerome Forissier size_kib = 0 51abaf1209SJerome Forissier num_pages = 0 52abaf1209SJerome Forissier else: 53abaf1209SJerome Forissier if round_up: 54abaf1209SJerome Forissier size_kib = (size - 1) / 1024 + 1 55abaf1209SJerome Forissier else: 56abaf1209SJerome Forissier size_kib = size / 1024 57abaf1209SJerome Forissier num_pages = (size - 1) / 4096 + 1 58abaf1209SJerome Forissier 59abaf1209SJerome Forissier printf('%-16s %.8X - %.8X size %.8X %3d KiB', name, addr, addr + size, 60abaf1209SJerome Forissier size, size_kib) 61abaf1209SJerome Forissier if print_num_pages: 62abaf1209SJerome Forissier printf(' %d pages', num_pages) 63abaf1209SJerome Forissier printf('\n') 64abaf1209SJerome Forissier 65abaf1209SJerome Forissier 663be7773fSJerome Forissierdef print_pager_stat(name, size): 673be7773fSJerome Forissier size_kib = size / 1024 683be7773fSJerome Forissier if args.raw: 693be7773fSJerome Forissier printf('%d ', size) 703be7773fSJerome Forissier else: 713be7773fSJerome Forissier printf('%-36s size %.8X %3d KiB\n', name, size, size_kib) 723be7773fSJerome Forissier 733be7773fSJerome Forissier 74abaf1209SJerome Forissierdef readelf_cmd(): 75abaf1209SJerome Forissier return os.getenv('CROSS_COMPILE', '') + 'readelf' 76abaf1209SJerome Forissier 77abaf1209SJerome Forissier 78abaf1209SJerome Forissierdef main(): 793be7773fSJerome Forissier global args 803be7773fSJerome Forissier 81abaf1209SJerome Forissier in_shdr = False 82abaf1209SJerome Forissier sects = [] 833be7773fSJerome Forissier init_size = 0 843be7773fSJerome Forissier paged_size = 0 853be7773fSJerome Forissier unpaged_size = 0 863be7773fSJerome Forissier unpaged_no_heap_size = 0 87abaf1209SJerome Forissier 88abaf1209SJerome Forissier args = get_args() 89abaf1209SJerome Forissier env = os.environ.copy() 90abaf1209SJerome Forissier env['LC_ALL'] = 'C' 91*479c49ddSJerome Forissier readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-s', 92*479c49ddSJerome Forissier args.tee_elf], 93*479c49ddSJerome Forissier stdout=subprocess.PIPE, env=env, 94*479c49ddSJerome Forissier universal_newlines=True) 95*479c49ddSJerome Forissier for line in iter(readelf.stdout.readline, ''): 96*479c49ddSJerome Forissier words = line.split() 97*479c49ddSJerome Forissier if len(words) == 8 and words[7] == '_end_of_ram': 98*479c49ddSJerome Forissier end_of_ram = int(words[1], 16) 99*479c49ddSJerome Forissier break 100*479c49ddSJerome Forissier readelf.terminate() 101edbeddc1SJerome Forissier readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-S', '-W', 102edbeddc1SJerome Forissier args.tee_elf], 103abaf1209SJerome Forissier stdout=subprocess.PIPE, env=env, 104abaf1209SJerome Forissier universal_newlines=True) 105abaf1209SJerome Forissier for line in iter(readelf.stdout.readline, ''): 106abaf1209SJerome Forissier if 'Section Headers:' in line: 107abaf1209SJerome Forissier in_shdr = True 108abaf1209SJerome Forissier continue 109abaf1209SJerome Forissier if 'Key to Flags:' in line: 110abaf1209SJerome Forissier in_shdr = False 111abaf1209SJerome Forissier continue 112abaf1209SJerome Forissier if in_shdr: 113abaf1209SJerome Forissier words = line.split() 114abaf1209SJerome Forissier if words[0] == '[': 115abaf1209SJerome Forissier words.pop(0) 116abaf1209SJerome Forissier try: 117abaf1209SJerome Forissier (_, name, _, addr, offs, size, _, 118abaf1209SJerome Forissier flags) = words[:8] 119146cbc4fSJerome Forissier except BaseException: 120abaf1209SJerome Forissier continue 121abaf1209SJerome Forissier if (flags == 'AX' or flags == 'WA' or flags == 'A' or 122abaf1209SJerome Forissier flags == 'AL'): 123abaf1209SJerome Forissier sects.append({'name': name, 'addr': addr, 124abaf1209SJerome Forissier 'offs': offs, 'size': size}) 125*479c49ddSJerome Forissier first_addr = None 126abaf1209SJerome Forissier for sect in sects: 127abaf1209SJerome Forissier if sect['addr'] != 0: 128*479c49ddSJerome Forissier addr = sect['addr'] 129*479c49ddSJerome Forissier if not first_addr: 130*479c49ddSJerome Forissier first_addr = addr 131*479c49ddSJerome Forissier if int(addr, 16) >= end_of_ram: 132abaf1209SJerome Forissier break 133*479c49ddSJerome Forissier last_addr = addr 134*479c49ddSJerome Forissier last_size = sect['size'] 135abaf1209SJerome Forissier 136abaf1209SJerome Forissier ram_usage = int(last_addr, 16) + int(last_size, 16) - int(first_addr, 16) 137abaf1209SJerome Forissier print_sect('RAM Usage', int(first_addr, 16), ram_usage, True, True) 138abaf1209SJerome Forissier 139abaf1209SJerome Forissier last_addr = 0 140abaf1209SJerome Forissier last_size = 0 141abaf1209SJerome Forissier for sect in sects: 142abaf1209SJerome Forissier name = sect['name'] 143abaf1209SJerome Forissier addr = int(sect['addr'], 16) 144abaf1209SJerome Forissier size = int(sect['size'], 16) 145abaf1209SJerome Forissier 146*479c49ddSJerome Forissier if addr >= end_of_ram: 147*479c49ddSJerome Forissier break 148abaf1209SJerome Forissier if last_addr != 0 and addr != last_addr + last_size: 149abaf1209SJerome Forissier print_sect('*hole*', last_addr + last_size, 150abaf1209SJerome Forissier addr - (last_addr + last_size)) 151abaf1209SJerome Forissier print_sect(name, addr, size) 1523be7773fSJerome Forissier if name.endswith('_init'): 1533be7773fSJerome Forissier init_size += size 1543be7773fSJerome Forissier elif name.endswith('_pageable'): 1553be7773fSJerome Forissier paged_size += size 1563be7773fSJerome Forissier else: 1573be7773fSJerome Forissier if not name.startswith('.heap'): 1583be7773fSJerome Forissier unpaged_no_heap_size += size 1593be7773fSJerome Forissier unpaged_size += size 160abaf1209SJerome Forissier last_addr = addr 161abaf1209SJerome Forissier last_size = size 162abaf1209SJerome Forissier 1633be7773fSJerome Forissier if args.all or args.init: 1643be7773fSJerome Forissier print_pager_stat('Init sections (.*_init)', init_size) 1653be7773fSJerome Forissier if args.all or args.paged: 1663be7773fSJerome Forissier print_pager_stat('Paged sections (.*_pageable)', paged_size) 1673be7773fSJerome Forissier if args.all or args.unpaged: 1683be7773fSJerome Forissier print_pager_stat('Unpaged sections ', unpaged_size) 1693be7773fSJerome Forissier if args.all or args.unpaged_no_heap: 1703be7773fSJerome Forissier print_pager_stat('Unpaged sections (heap excluded)', 1713be7773fSJerome Forissier unpaged_no_heap_size) 1723be7773fSJerome Forissier if (args.raw and (args.all or args.init or args.paged or 1733be7773fSJerome Forissier args.unpaged or args.unpaged_no_heap)): 1743be7773fSJerome Forissier printf('\n') 1753be7773fSJerome Forissier 176abaf1209SJerome Forissier 177abaf1209SJerome Forissierif __name__ == "__main__": 178abaf1209SJerome Forissier main() 179