blob: d9aa2dfafca7ec0d4cb9c1b9856f64badb5a3bf3 [file] [log] [blame]
Jerome Forissierabaf1202017-11-08 13:31:29 +01001#!/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():
Jerome Forissier3be77732017-11-09 15:54:46 +010015 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')
Jerome Forissierabaf1202017-11-08 13:31:29 +010040 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):
Jerome Forissier3be77732017-11-09 15:54:46 +010048 if args.no_map:
49 return
Jerome Forissierabaf1202017-11-08 13:31:29 +010050 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
Jerome Forissier3be77732017-11-09 15:54:46 +010067def 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
Jerome Forissierabaf1202017-11-08 13:31:29 +010075def readelf_cmd():
76 return os.getenv('CROSS_COMPILE', '') + 'readelf'
77
78
79def main():
Jerome Forissier3be77732017-11-09 15:54:46 +010080 global args
81
Jerome Forissierabaf1202017-11-08 13:31:29 +010082 in_shdr = False
83 sects = []
Jerome Forissier3be77732017-11-09 15:54:46 +010084 init_size = 0
85 paged_size = 0
86 unpaged_size = 0
87 unpaged_no_heap_size = 0
Jerome Forissierabaf1202017-11-08 13:31:29 +010088
89 args = get_args()
90 env = os.environ.copy()
91 env['LC_ALL'] = 'C'
Jerome Forissieredbeddc2017-11-21 08:53:54 +010092 readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-S', '-W',
93 args.tee_elf],
Jerome Forissierabaf1202017-11-08 13:31:29 +010094 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)
Jerome Forissier3be77732017-11-09 15:54:46 +0100137 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
Jerome Forissierabaf1202017-11-08 13:31:29 +0100145 last_addr = addr
146 last_size = size
147
Jerome Forissier3be77732017-11-09 15:54:46 +0100148 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
Jerome Forissierabaf1202017-11-08 13:31:29 +0100161
162if __name__ == "__main__":
163 main()