1#!/bin/bash
2
3if [ ! -f "$1" ]
4then
5	cat << EOF
6
7	$(basename $0) <leaksFile> [<options>] [<excludePatterns>]
8
9	<leaksFile>
10
11		A file containing the allocations with stack traces from
12		the guarded heap output.
13
14		To generate such a file run a program with the following
15		environment variables prefixed and pipe the output to a file:
16
17		LD_PRELOAD=libroot_debug.so MALLOC_DEBUG=ges50 program > file
18
19		The number after the "s" is the stack trace depth. Note that
20		there is an implementation defined maximum.
21
22	--no-default-excludes
23
24		Do not exclude known statics and globals. By default a list of
25		excludes is used that removes known allocations that are never
26		freed by the system libraries.
27
28	--no-exclude-empty
29
30		Do not exclude allocations with no stack trace. By default
31		allocations without a stack trace are excluded. This should
32		only happen for very early allocations where the stack trace
33		setting has not yet been applied. The program should not be
34		able to generate such allocations.
35
36	<excludePatterns>
37
38		Exclude allocations that match a regular expression. The
39		expression is matched against the whole text block of the
40		allocation, so can match in the header line as well as any
41		stack trace lines. Note that the whole block is on a single
42		line and newlines have been replaced with the caret (^)
43		character.
44
45		Multiple exclude patterns can be specified as one argument each
46		and they will be ored to form the final expression.
47
48EOF
49
50	exit 1
51fi
52
53
54FILENAME="$1"
55shift
56
57
58DONE_PARSING_OPTIONS=
59NO_DEFAULTS=
60NO_EXCLUDE_EMPTY=
61while [ -z "$DONE_PARSING_OPTIONS" ]
62do
63	case "$1" in
64		--no-default-excludes)
65			NO_DEFAULTS=yes
66			shift
67		;;
68		--no-exclude-empty)
69			NO_EXCLUDE_EMPTY=yes
70			shift
71		;;
72		--*)
73			echo "unrecognized option \"$1\" ignored"
74			shift
75		;;
76		*)
77			DONE_PARSING_OPTIONS=yes
78		;;
79	esac
80done
81
82
83function append_pattern {
84	if [ -z "$EXCLUDE_PATTERN" ]
85	then
86		EXCLUDE_PATTERN="$1"
87	else
88		EXCLUDE_PATTERN="$EXCLUDE_PATTERN|$1"
89	fi
90}
91
92
93EXCLUDE_PATTERN=""
94if [ -z "$NO_DEFAULTS" ]
95then
96	declare -a DEFAULT_EXCLUDE_LIST=( \
97		"<libroot.so> initialize_before " \
98		"<libroot.so> __cxa_atexit " \
99		"<libroot.so> BPrivate::Libroot::LocaleBackend::LoadBackend" \
100		"<libbe.so> initialize_before " \
101		"<libbe.so> initialize_after " \
102		"<libbe.so> _control_input_server_" \
103		"<libbe.so> BApplication::_InitGUIContext" \
104		"<libbe.so> BApplication::_InitAppResources" \
105		"<libbe.so> BResources::LoadResource" \
106		"<libbe.so> BClipboard::_DownloadFromSystem" \
107		"<libbe.so> BToolTipManager::_InitSingleton" \
108		"<libbe.so> BPrivate::WidthBuffer::StringWidth" \
109		"<libtracker.so> _init " \
110		"<libtranslation.so> BTranslatorRoster::Default" \
111		"Translator> " \
112		"<libicu[^.]+.so.[0-9]+> icu(_[0-9]+)?::" \
113	)
114
115	for EXCLUDE in "${DEFAULT_EXCLUDE_LIST[@]}"
116	do
117		append_pattern "$EXCLUDE"
118	done
119fi
120
121
122if [ -z "$NO_EXCLUDE_EMPTY" ]
123then
124	append_pattern "^[^^]*\^$"
125fi
126
127
128while [ $# -gt 0 ]
129do
130	append_pattern "$1"
131	shift
132done
133
134
135ALLOCATIONS=$(cat "$FILENAME" | grep -E "^allocation: |^	" | tr '\n' '^' \
136	| sed 's/\^a/~a/g' | tr '~' '\n' | sed 's/$/^/' | c++filt)
137
138if [ ! -z "$EXCLUDE_PATTERN" ]
139then
140	ALLOCATIONS=$(echo "$ALLOCATIONS" | grep -E -v "$EXCLUDE_PATTERN")
141fi
142
143if [ -z "$ALLOCATIONS" ]
144then
145	COUNT=0
146else
147	COUNT=$(echo "$ALLOCATIONS" | wc -l)
148fi
149
150
151echo "$ALLOCATIONS^total leaks: $COUNT" | tr '^' '\n' | less
152