xref: /optee_os/scripts/mem_usage.py (revision 479c49dd9247118109448e5be0883f08e80c5f46)
1abaf1209SJerome Forissier#!/usr/bin/env python3
2abaf1209SJerome Forissier#
3abaf1209SJerome Forissier# Copyright (c) 2014-2017, Linaro Limited
4abaf1209SJerome Forissier#
5abaf1209SJerome Forissier# SPDX-License-Identifier: BSD-3-Clause
6abaf1209SJerome Forissier
7abaf1209SJerome Forissierimport argparse
8abaf1209SJerome Forissierimport os
9abaf1209SJerome Forissierimport subprocess
10abaf1209SJerome Forissierimport sys
11abaf1209SJerome Forissier
12abaf1209SJerome Forissier
13abaf1209SJerome Forissierdef get_args():
143be7773fSJerome Forissier    parser = argparse.ArgumentParser(description='Shows the memory usage '
153be7773fSJerome Forissier                                     'of an OP-TEE based on ELF sections')
163be7773fSJerome Forissier    parser.add_argument('tee_elf', help='the OP-TEE ELF file (tee.elf)')
173be7773fSJerome Forissier    parser.add_argument('-a', '--all', action='store_true',
183be7773fSJerome Forissier                        help=' same as -i -p -u -U')
193be7773fSJerome Forissier    parser.add_argument('-n', '--no-map', action='store_true',
203be7773fSJerome Forissier                        help=' do not show the detailed section mappings and '
213be7773fSJerome Forissier                        'RAM usage')
223be7773fSJerome Forissier    parser.add_argument('-i', '--init', action='store_true',
233be7773fSJerome Forissier                        help='report the total size of the .*_init sections')
243be7773fSJerome Forissier    parser.add_argument('-p', '--paged', action='store_true',
253be7773fSJerome Forissier                        help='report the total size of the .*_pageable '
263be7773fSJerome Forissier                        'sections')
273be7773fSJerome Forissier    parser.add_argument('-u', '--unpaged', action='store_true',
283be7773fSJerome Forissier                        help='report the total size of the unpaged sections, '
293be7773fSJerome Forissier                        'that is, all sections but the ones in --init or '
303be7773fSJerome Forissier                        '--paged')
313be7773fSJerome Forissier    parser.add_argument('-U', '--unpaged-no-heap', action='store_true',
323be7773fSJerome Forissier                        help='report the size of all unpaged sections '
333be7773fSJerome Forissier                        'excluding heap space. Reflects the size of unpaged '
343be7773fSJerome Forissier                        'code and data (.text, .rodata, .data, .bss, .nozi '
353be7773fSJerome Forissier                        'and possibly unwind tables)')
363be7773fSJerome Forissier    parser.add_argument('-r', '--raw', action='store_true',
373be7773fSJerome Forissier                        help='when processing -i, -p, -u, or -U, show only '
383be7773fSJerome Forissier                        'the size (in decimal) and no other text')
39abaf1209SJerome Forissier    return parser.parse_args()
40abaf1209SJerome Forissier
41abaf1209SJerome Forissier
42abaf1209SJerome Forissierdef printf(format, *args):
43abaf1209SJerome Forissier    sys.stdout.write(format % args)
44abaf1209SJerome Forissier
45abaf1209SJerome Forissier
46abaf1209SJerome Forissierdef print_sect(name, addr, size, round_up=False, print_num_pages=False):
473be7773fSJerome Forissier    if args.no_map:
483be7773fSJerome Forissier        return
49abaf1209SJerome Forissier    if size == 0:
50abaf1209SJerome Forissier        size_kib = 0
51abaf1209SJerome Forissier        num_pages = 0
52abaf1209SJerome Forissier    else:
53abaf1209SJerome Forissier        if round_up:
54abaf1209SJerome Forissier            size_kib = (size - 1) / 1024 + 1
55abaf1209SJerome Forissier        else:
56abaf1209SJerome Forissier            size_kib = size / 1024
57abaf1209SJerome Forissier        num_pages = (size - 1) / 4096 + 1
58abaf1209SJerome Forissier
59abaf1209SJerome Forissier    printf('%-16s %.8X - %.8X size %.8X %3d KiB', name, addr, addr + size,
60abaf1209SJerome Forissier           size, size_kib)
61abaf1209SJerome Forissier    if print_num_pages:
62abaf1209SJerome Forissier        printf(' %d pages', num_pages)
63abaf1209SJerome Forissier    printf('\n')
64abaf1209SJerome Forissier
65abaf1209SJerome Forissier
663be7773fSJerome Forissierdef print_pager_stat(name, size):
673be7773fSJerome Forissier    size_kib = size / 1024
683be7773fSJerome Forissier    if args.raw:
693be7773fSJerome Forissier        printf('%d ', size)
703be7773fSJerome Forissier    else:
713be7773fSJerome Forissier        printf('%-36s size %.8X %3d KiB\n', name, size, size_kib)
723be7773fSJerome Forissier
733be7773fSJerome Forissier
74abaf1209SJerome Forissierdef readelf_cmd():
75abaf1209SJerome Forissier    return os.getenv('CROSS_COMPILE', '') + 'readelf'
76abaf1209SJerome Forissier
77abaf1209SJerome Forissier
78abaf1209SJerome Forissierdef main():
793be7773fSJerome Forissier    global args
803be7773fSJerome Forissier
81abaf1209SJerome Forissier    in_shdr = False
82abaf1209SJerome Forissier    sects = []
833be7773fSJerome Forissier    init_size = 0
843be7773fSJerome Forissier    paged_size = 0
853be7773fSJerome Forissier    unpaged_size = 0
863be7773fSJerome Forissier    unpaged_no_heap_size = 0
87abaf1209SJerome Forissier
88abaf1209SJerome Forissier    args = get_args()
89abaf1209SJerome Forissier    env = os.environ.copy()
90abaf1209SJerome Forissier    env['LC_ALL'] = 'C'
91*479c49ddSJerome Forissier    readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-s',
92*479c49ddSJerome Forissier                                                           args.tee_elf],
93*479c49ddSJerome Forissier                               stdout=subprocess.PIPE, env=env,
94*479c49ddSJerome Forissier                               universal_newlines=True)
95*479c49ddSJerome Forissier    for line in iter(readelf.stdout.readline, ''):
96*479c49ddSJerome Forissier        words = line.split()
97*479c49ddSJerome Forissier        if len(words) == 8 and words[7] == '_end_of_ram':
98*479c49ddSJerome Forissier            end_of_ram = int(words[1], 16)
99*479c49ddSJerome Forissier            break
100*479c49ddSJerome Forissier    readelf.terminate()
101edbeddc1SJerome Forissier    readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-S', '-W',
102edbeddc1SJerome Forissier                                                           args.tee_elf],
103abaf1209SJerome Forissier                               stdout=subprocess.PIPE, env=env,
104abaf1209SJerome Forissier                               universal_newlines=True)
105abaf1209SJerome Forissier    for line in iter(readelf.stdout.readline, ''):
106abaf1209SJerome Forissier        if 'Section Headers:' in line:
107abaf1209SJerome Forissier            in_shdr = True
108abaf1209SJerome Forissier            continue
109abaf1209SJerome Forissier        if 'Key to Flags:' in line:
110abaf1209SJerome Forissier            in_shdr = False
111abaf1209SJerome Forissier            continue
112abaf1209SJerome Forissier        if in_shdr:
113abaf1209SJerome Forissier            words = line.split()
114abaf1209SJerome Forissier            if words[0] == '[':
115abaf1209SJerome Forissier                words.pop(0)
116abaf1209SJerome Forissier            try:
117abaf1209SJerome Forissier                (_, name, _, addr, offs, size, _,
118abaf1209SJerome Forissier                 flags) = words[:8]
119146cbc4fSJerome Forissier            except BaseException:
120abaf1209SJerome Forissier                continue
121abaf1209SJerome Forissier            if (flags == 'AX' or flags == 'WA' or flags == 'A' or
122abaf1209SJerome Forissier                    flags == 'AL'):
123abaf1209SJerome Forissier                sects.append({'name': name, 'addr': addr,
124abaf1209SJerome Forissier                              'offs': offs, 'size': size})
125*479c49ddSJerome Forissier    first_addr = None
126abaf1209SJerome Forissier    for sect in sects:
127abaf1209SJerome Forissier        if sect['addr'] != 0:
128*479c49ddSJerome Forissier            addr = sect['addr']
129*479c49ddSJerome Forissier            if not first_addr:
130*479c49ddSJerome Forissier                first_addr = addr
131*479c49ddSJerome Forissier            if int(addr, 16) >= end_of_ram:
132abaf1209SJerome Forissier                break
133*479c49ddSJerome Forissier            last_addr = addr
134*479c49ddSJerome Forissier            last_size = sect['size']
135abaf1209SJerome Forissier
136abaf1209SJerome Forissier    ram_usage = int(last_addr, 16) + int(last_size, 16) - int(first_addr, 16)
137abaf1209SJerome Forissier    print_sect('RAM Usage', int(first_addr, 16), ram_usage, True, True)
138abaf1209SJerome Forissier
139abaf1209SJerome Forissier    last_addr = 0
140abaf1209SJerome Forissier    last_size = 0
141abaf1209SJerome Forissier    for sect in sects:
142abaf1209SJerome Forissier        name = sect['name']
143abaf1209SJerome Forissier        addr = int(sect['addr'], 16)
144abaf1209SJerome Forissier        size = int(sect['size'], 16)
145abaf1209SJerome Forissier
146*479c49ddSJerome Forissier        if addr >= end_of_ram:
147*479c49ddSJerome Forissier            break
148abaf1209SJerome Forissier        if last_addr != 0 and addr != last_addr + last_size:
149abaf1209SJerome Forissier            print_sect('*hole*', last_addr + last_size,
150abaf1209SJerome Forissier                       addr - (last_addr + last_size))
151abaf1209SJerome Forissier        print_sect(name, addr, size)
1523be7773fSJerome Forissier        if name.endswith('_init'):
1533be7773fSJerome Forissier            init_size += size
1543be7773fSJerome Forissier        elif name.endswith('_pageable'):
1553be7773fSJerome Forissier            paged_size += size
1563be7773fSJerome Forissier        else:
1573be7773fSJerome Forissier            if not name.startswith('.heap'):
1583be7773fSJerome Forissier                unpaged_no_heap_size += size
1593be7773fSJerome Forissier            unpaged_size += size
160abaf1209SJerome Forissier        last_addr = addr
161abaf1209SJerome Forissier        last_size = size
162abaf1209SJerome Forissier
1633be7773fSJerome Forissier    if args.all or args.init:
1643be7773fSJerome Forissier        print_pager_stat('Init sections (.*_init)', init_size)
1653be7773fSJerome Forissier    if args.all or args.paged:
1663be7773fSJerome Forissier        print_pager_stat('Paged sections (.*_pageable)', paged_size)
1673be7773fSJerome Forissier    if args.all or args.unpaged:
1683be7773fSJerome Forissier        print_pager_stat('Unpaged sections ', unpaged_size)
1693be7773fSJerome Forissier    if args.all or args.unpaged_no_heap:
1703be7773fSJerome Forissier        print_pager_stat('Unpaged sections (heap excluded)',
1713be7773fSJerome Forissier                         unpaged_no_heap_size)
1723be7773fSJerome Forissier    if (args.raw and (args.all or args.init or args.paged or
1733be7773fSJerome Forissier                      args.unpaged or args.unpaged_no_heap)):
1743be7773fSJerome Forissier        printf('\n')
1753be7773fSJerome Forissier
176abaf1209SJerome Forissier
177abaf1209SJerome Forissierif __name__ == "__main__":
178abaf1209SJerome Forissier    main()
179