summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl/rtl-alloc-check.py
blob: dc59c43c6d5ec964aa861c620657e0ff2793467a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# SPDX-License-Identifier: BSD-2-Clause

#
# Check the allocations for libdl:
#
#  1. Turn on the allocation trace.
#
#  2. Load and unload object files.
#
#  3. Capture the trace output and feed to this tool

# Copyright (c) 2019 Chris Johns <chrisj@rtems.org>.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

from __future__ import print_function

import argparse


class libdl_trace(object):
    def __init__(self, name):
        self.name = name
        self.trace = {'alloc': []}

    def load(self):
        with open(self.name, 'r') as f:
            lc = 0
            for line in f:
                line = line[:-1]
                lc += 1
                if line.startswith('rtl: '):
                    if line.startswith('rtl: alloc: '):
                        self.trace['alloc'] += [(lc, line)]

    def check_allocs(self):
        allocs = {}
        locks = 0
        wr_enable = False
        for lc, line in self.trace['alloc']:
            ls = line.split(' ')
            if len(ls) > 3:
                if ls[2] == 'new:':
                    addr = ls[4].split('=')[1]
                    size = ls[5].split('=')[1]
                    count = 0
                    if addr in allocs:
                        alc, alloced, asize, count = allocs[addr]
                        if alloced:
                            print(
                                '%5d: already alloced: %5d: addr=%-9s size=%-9s count=%d'
                                % (lc, alc, addr, asize, count))
                    allocs[addr] = (lc, True, size, count + 1)
                elif ls[2] == 'del:':
                    addr = ls[4].split('=')[1]
                    if addr != '0':
                        if addr not in allocs:
                            print('%5d: delete never alloced: addr=%s' %
                                  (lc, addr))
                        else:
                            alc, alloced, size, count = allocs[addr]
                            if not alloced:
                                print(
                                    '%5d: delete not alloced: %5d: addr=%-9s size=%-9s count=%d'
                                    % (lc, alc, addr, size, count))
                        allocs[addr] = (lc, False, size, count)
        alloced_remaiing = 0
        addresses = sorted(list(allocs.keys()))
        for addr in addresses:
            lc, alloced, size, count = allocs[addr]
            if alloced:
                print('%5d: never deleted: addr=%-9s size=%-9s count=%d' %
                      (lc, addr, size, count))
                alloced_remaiing += int(size)
        if alloced_remaiing != 0:
            print("Amount alloced: %d" % (alloced_remaiing))


def run(args):
    argsp = argparse.ArgumentParser(prog='rtl-alloc-check',
                                    description='Audit libdl allocations')
    argsp.add_argument('traces', help='libdl trace files', nargs='+')

    opts = argsp.parse_args(args[1:])

    for t in opts.traces:
        trace = libdl_trace(t)
        trace.load()
        trace.check_allocs()


if __name__ == "__main__":
    import sys
    run(sys.argv)