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