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', 92 args.tee_elf], 93 stdout=subprocess.PIPE, env=env, 94 universal_newlines=True) 95 for line in iter(readelf.stdout.readline, ''): 96 words = line.split() 97 if len(words) == 8 and words[7] == '_end_of_ram': 98 end_of_ram = int(words[1], 16) 99 break 100 readelf.terminate() 101 readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-S', '-W', 102 args.tee_elf], 103 stdout=subprocess.PIPE, env=env, 104 universal_newlines=True) 105 for line in iter(readelf.stdout.readline, ''): 106 if 'Section Headers:' in line: 107 in_shdr = True 108 continue 109 if 'Key to Flags:' in line: 110 in_shdr = False 111 continue 112 if in_shdr: 113 words = line.split() 114 if words[0] == '[': 115 words.pop(0) 116 try: 117 (_, name, _, addr, offs, size, _, 118 flags) = words[:8] 119 except BaseException: 120 continue 121 if ('A' in flags): 122 sects.append({'name': name, 'addr': addr, 123 'offs': offs, 'size': size}) 124 first_addr = None 125 for sect in sects: 126 if sect['addr'] != 0: 127 addr = sect['addr'] 128 if not first_addr: 129 first_addr = addr 130 if int(addr, 16) >= end_of_ram: 131 break 132 last_addr = addr 133 last_size = sect['size'] 134 135 ram_usage = int(last_addr, 16) + int(last_size, 16) - int(first_addr, 16) 136 print_sect('RAM Usage', int(first_addr, 16), ram_usage, True, True) 137 138 last_addr = 0 139 last_size = 0 140 for sect in sects: 141 name = sect['name'] 142 addr = int(sect['addr'], 16) 143 size = int(sect['size'], 16) 144 145 if addr >= end_of_ram: 146 break 147 if last_addr != 0 and addr != last_addr + last_size: 148 print_sect('*hole*', last_addr + last_size, 149 addr - (last_addr + last_size)) 150 print_sect(name, addr, size) 151 if name.endswith('_init'): 152 init_size += size 153 elif name.endswith('_pageable'): 154 paged_size += size 155 else: 156 if not name.startswith('.heap'): 157 unpaged_no_heap_size += size 158 unpaged_size += size 159 last_addr = addr 160 last_size = size 161 162 if args.all or args.init: 163 print_pager_stat('Init sections (.*_init)', init_size) 164 if args.all or args.paged: 165 print_pager_stat('Paged sections (.*_pageable)', paged_size) 166 if args.all or args.unpaged: 167 print_pager_stat('Unpaged sections ', unpaged_size) 168 if args.all or args.unpaged_no_heap: 169 print_pager_stat('Unpaged sections (heap excluded)', 170 unpaged_no_heap_size) 171 if (args.raw and (args.all or args.init or args.paged or 172 args.unpaged or args.unpaged_no_heap)): 173 printf('\n') 174 175 176if __name__ == "__main__": 177 main() 178