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