1#!/usr/bin/env python3 2# 3# Copyright (c) 2014-2017, Linaro Limited 4# All rights reserved. 5# 6# SPDX-License-Identifier: BSD-3-Clause 7 8import argparse 9import os 10import subprocess 11import sys 12 13 14def get_args(): 15 parser = argparse.ArgumentParser(description='Shows the memory usage ' 16 'of an OP-TEE based on ELF sections') 17 parser.add_argument('tee_elf', help='the OP-TEE ELF file (tee.elf)') 18 parser.add_argument('-a', '--all', action='store_true', 19 help=' same as -i -p -u -U') 20 parser.add_argument('-n', '--no-map', action='store_true', 21 help=' do not show the detailed section mappings and ' 22 'RAM usage') 23 parser.add_argument('-i', '--init', action='store_true', 24 help='report the total size of the .*_init sections') 25 parser.add_argument('-p', '--paged', action='store_true', 26 help='report the total size of the .*_pageable ' 27 'sections') 28 parser.add_argument('-u', '--unpaged', action='store_true', 29 help='report the total size of the unpaged sections, ' 30 'that is, all sections but the ones in --init or ' 31 '--paged') 32 parser.add_argument('-U', '--unpaged-no-heap', action='store_true', 33 help='report the size of all unpaged sections ' 34 'excluding heap space. Reflects the size of unpaged ' 35 'code and data (.text, .rodata, .data, .bss, .nozi ' 36 'and possibly unwind tables)') 37 parser.add_argument('-r', '--raw', action='store_true', 38 help='when processing -i, -p, -u, or -U, show only ' 39 'the size (in decimal) and no other text') 40 return parser.parse_args() 41 42 43def printf(format, *args): 44 sys.stdout.write(format % args) 45 46 47def print_sect(name, addr, size, round_up=False, print_num_pages=False): 48 if args.no_map: 49 return 50 if size == 0: 51 size_kib = 0 52 num_pages = 0 53 else: 54 if round_up: 55 size_kib = (size - 1) / 1024 + 1 56 else: 57 size_kib = size / 1024 58 num_pages = (size - 1) / 4096 + 1 59 60 printf('%-16s %.8X - %.8X size %.8X %3d KiB', name, addr, addr + size, 61 size, size_kib) 62 if print_num_pages: 63 printf(' %d pages', num_pages) 64 printf('\n') 65 66 67def print_pager_stat(name, size): 68 size_kib = size / 1024 69 if args.raw: 70 printf('%d ', size) 71 else: 72 printf('%-36s size %.8X %3d KiB\n', name, size, size_kib) 73 74 75def readelf_cmd(): 76 return os.getenv('CROSS_COMPILE', '') + 'readelf' 77 78 79def main(): 80 global args 81 82 in_shdr = False 83 sects = [] 84 init_size = 0 85 paged_size = 0 86 unpaged_size = 0 87 unpaged_no_heap_size = 0 88 89 args = get_args() 90 env = os.environ.copy() 91 env['LC_ALL'] = 'C' 92 readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-S', '-W', 93 args.tee_elf], 94 stdout=subprocess.PIPE, env=env, 95 universal_newlines=True) 96 for line in iter(readelf.stdout.readline, ''): 97 if 'Section Headers:' in line: 98 in_shdr = True 99 continue 100 if 'Key to Flags:' in line: 101 in_shdr = False 102 continue 103 if in_shdr: 104 words = line.split() 105 if words[0] == '[': 106 words.pop(0) 107 try: 108 (_, name, _, addr, offs, size, _, 109 flags) = words[:8] 110 except: 111 continue 112 if (flags == 'AX' or flags == 'WA' or flags == 'A' or 113 flags == 'AL'): 114 sects.append({'name': name, 'addr': addr, 115 'offs': offs, 'size': size}) 116 for sect in sects: 117 if sect['addr'] != 0: 118 first_addr = sect['addr'] 119 break 120 last_addr = sects[-1]['addr'] 121 last_size = sects[-1]['size'] 122 123 ram_usage = int(last_addr, 16) + int(last_size, 16) - int(first_addr, 16) 124 print_sect('RAM Usage', int(first_addr, 16), ram_usage, True, True) 125 126 last_addr = 0 127 last_size = 0 128 for sect in sects: 129 name = sect['name'] 130 addr = int(sect['addr'], 16) 131 size = int(sect['size'], 16) 132 133 if last_addr != 0 and addr != last_addr + last_size: 134 print_sect('*hole*', last_addr + last_size, 135 addr - (last_addr + last_size)) 136 print_sect(name, addr, size) 137 if name.endswith('_init'): 138 init_size += size 139 elif name.endswith('_pageable'): 140 paged_size += size 141 else: 142 if not name.startswith('.heap'): 143 unpaged_no_heap_size += size 144 unpaged_size += size 145 last_addr = addr 146 last_size = size 147 148 if args.all or args.init: 149 print_pager_stat('Init sections (.*_init)', init_size) 150 if args.all or args.paged: 151 print_pager_stat('Paged sections (.*_pageable)', paged_size) 152 if args.all or args.unpaged: 153 print_pager_stat('Unpaged sections ', unpaged_size) 154 if args.all or args.unpaged_no_heap: 155 print_pager_stat('Unpaged sections (heap excluded)', 156 unpaged_no_heap_size) 157 if (args.raw and (args.all or args.init or args.paged or 158 args.unpaged or args.unpaged_no_heap)): 159 printf('\n') 160 161 162if __name__ == "__main__": 163 main() 164