1*7c478bd9Sstevel@tonic-gate#!/usr/perl5/bin/perl -w
2*7c478bd9Sstevel@tonic-gate#
3*7c478bd9Sstevel@tonic-gate# CDDL HEADER START
4*7c478bd9Sstevel@tonic-gate#
5*7c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the
6*7c478bd9Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only
7*7c478bd9Sstevel@tonic-gate# (the "License").  You may not use this file except in compliance
8*7c478bd9Sstevel@tonic-gate# with the License.
9*7c478bd9Sstevel@tonic-gate#
10*7c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11*7c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
12*7c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
13*7c478bd9Sstevel@tonic-gate# and limitations under the License.
14*7c478bd9Sstevel@tonic-gate#
15*7c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
16*7c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17*7c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
18*7c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
19*7c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
20*7c478bd9Sstevel@tonic-gate#
21*7c478bd9Sstevel@tonic-gate# CDDL HEADER END
22*7c478bd9Sstevel@tonic-gate#
23*7c478bd9Sstevel@tonic-gate#
24*7c478bd9Sstevel@tonic-gate# Copyright (c) 1996-2000 by Sun Microsystems, Inc.
25*7c478bd9Sstevel@tonic-gate# All rights reserved.
26*7c478bd9Sstevel@tonic-gate#
27*7c478bd9Sstevel@tonic-gate#ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate#
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate#
31*7c478bd9Sstevel@tonic-gate# This utility program reads the symcheck output of each binary and
32*7c478bd9Sstevel@tonic-gate# creates additional output for then and an overall report.
33*7c478bd9Sstevel@tonic-gate#
34*7c478bd9Sstevel@tonic-gate
35*7c478bd9Sstevel@tonic-gaterequire 5.005;
36*7c478bd9Sstevel@tonic-gateuse strict;
37*7c478bd9Sstevel@tonic-gateuse locale;
38*7c478bd9Sstevel@tonic-gateuse POSIX qw(locale_h);
39*7c478bd9Sstevel@tonic-gateuse Sun::Solaris::Utils qw(textdomain gettext);
40*7c478bd9Sstevel@tonic-gateuse File::Basename;
41*7c478bd9Sstevel@tonic-gateuse File::Path;
42*7c478bd9Sstevel@tonic-gate
43*7c478bd9Sstevel@tonic-gateuse lib qw(/usr/lib/abi/appcert);
44*7c478bd9Sstevel@tonic-gateuse AppcertUtil;
45*7c478bd9Sstevel@tonic-gate
46*7c478bd9Sstevel@tonic-gatesetlocale(LC_ALL, "");
47*7c478bd9Sstevel@tonic-gatetextdomain(TEXT_DOMAIN);
48*7c478bd9Sstevel@tonic-gate
49*7c478bd9Sstevel@tonic-gateuse vars qw(
50*7c478bd9Sstevel@tonic-gate	$tmp_report_dir
51*7c478bd9Sstevel@tonic-gate	$misc_check_databases_loaded_ok
52*7c478bd9Sstevel@tonic-gate	%result_list_hash
53*7c478bd9Sstevel@tonic-gate	%result_msg
54*7c478bd9Sstevel@tonic-gate	%warnings_found
55*7c478bd9Sstevel@tonic-gate);
56*7c478bd9Sstevel@tonic-gate
57*7c478bd9Sstevel@tonic-gateset_clean_up_exit_routine(\&clean_up_exit);
58*7c478bd9Sstevel@tonic-gate
59*7c478bd9Sstevel@tonic-gateimport_vars_from_environment();
60*7c478bd9Sstevel@tonic-gate
61*7c478bd9Sstevel@tonic-gatesignals('on', \&interrupted);
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gateset_working_dir();
64*7c478bd9Sstevel@tonic-gate
65*7c478bd9Sstevel@tonic-gategenerate_reports();
66*7c478bd9Sstevel@tonic-gate
67*7c478bd9Sstevel@tonic-gateclean_up();
68*7c478bd9Sstevel@tonic-gate
69*7c478bd9Sstevel@tonic-gateexit 0;
70*7c478bd9Sstevel@tonic-gate
71*7c478bd9Sstevel@tonic-gate#
72*7c478bd9Sstevel@tonic-gate# working_dir has been imported by import_vars_from_environment()
73*7c478bd9Sstevel@tonic-gate# A sanity check is performed here to make sure it exists.
74*7c478bd9Sstevel@tonic-gate#
75*7c478bd9Sstevel@tonic-gatesub set_working_dir
76*7c478bd9Sstevel@tonic-gate{
77*7c478bd9Sstevel@tonic-gate	if (! defined($working_dir) || ! -d $working_dir) {
78*7c478bd9Sstevel@tonic-gate		exiter("$command_name: " . sprintf(gettext(
79*7c478bd9Sstevel@tonic-gate		    "cannot locate working directory: %s\n"), $working_dir));
80*7c478bd9Sstevel@tonic-gate	}
81*7c478bd9Sstevel@tonic-gate}
82*7c478bd9Sstevel@tonic-gate
83*7c478bd9Sstevel@tonic-gate#
84*7c478bd9Sstevel@tonic-gate# Called when interrupted by user.
85*7c478bd9Sstevel@tonic-gate#
86*7c478bd9Sstevel@tonic-gatesub interrupted
87*7c478bd9Sstevel@tonic-gate{
88*7c478bd9Sstevel@tonic-gate	$SIG{$_[0]} = 'DEFAULT';
89*7c478bd9Sstevel@tonic-gate	signals('off');
90*7c478bd9Sstevel@tonic-gate	clean_up_exit(1);
91*7c478bd9Sstevel@tonic-gate}
92*7c478bd9Sstevel@tonic-gate
93*7c478bd9Sstevel@tonic-gate#
94*7c478bd9Sstevel@tonic-gate# Does the cleanup and then exit with return code $rc.  Note: The
95*7c478bd9Sstevel@tonic-gate# utility routine exiter() will call this routine.
96*7c478bd9Sstevel@tonic-gate#
97*7c478bd9Sstevel@tonic-gatesub clean_up_exit
98*7c478bd9Sstevel@tonic-gate{
99*7c478bd9Sstevel@tonic-gate	my ($rc) = @_;
100*7c478bd9Sstevel@tonic-gate	$rc = 0 unless ($rc);
101*7c478bd9Sstevel@tonic-gate
102*7c478bd9Sstevel@tonic-gate	clean_up();
103*7c478bd9Sstevel@tonic-gate	exit $rc;
104*7c478bd9Sstevel@tonic-gate}
105*7c478bd9Sstevel@tonic-gate
106*7c478bd9Sstevel@tonic-gate#
107*7c478bd9Sstevel@tonic-gate# General cleanup activities are placed here. There may not be an
108*7c478bd9Sstevel@tonic-gate# immediate exit after this cleanup.
109*7c478bd9Sstevel@tonic-gate#
110*7c478bd9Sstevel@tonic-gatesub clean_up
111*7c478bd9Sstevel@tonic-gate{
112*7c478bd9Sstevel@tonic-gate	if (defined($tmp_report_dir) && -d $tmp_report_dir) {
113*7c478bd9Sstevel@tonic-gate		rmtree($tmp_report_dir);
114*7c478bd9Sstevel@tonic-gate	}
115*7c478bd9Sstevel@tonic-gate}
116*7c478bd9Sstevel@tonic-gate
117*7c478bd9Sstevel@tonic-gate#
118*7c478bd9Sstevel@tonic-gate# Top level routine for generating the additional reports.
119*7c478bd9Sstevel@tonic-gate#
120*7c478bd9Sstevel@tonic-gatesub generate_reports
121*7c478bd9Sstevel@tonic-gate{
122*7c478bd9Sstevel@tonic-gate	# Make a tmp dir for the reporting work.
123*7c478bd9Sstevel@tonic-gate	$tmp_report_dir = create_tmp_dir($tmp_dir);
124*7c478bd9Sstevel@tonic-gate
125*7c478bd9Sstevel@tonic-gate	if (! -d $tmp_report_dir) {
126*7c478bd9Sstevel@tonic-gate		exiter(nocreatedir($tmp_report_dir, $!));
127*7c478bd9Sstevel@tonic-gate	}
128*7c478bd9Sstevel@tonic-gate
129*7c478bd9Sstevel@tonic-gate	pmsg("\n");
130*7c478bd9Sstevel@tonic-gate	print_line();
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gate	my ($dir, $path_to_object);
133*7c478bd9Sstevel@tonic-gate
134*7c478bd9Sstevel@tonic-gate	#
135*7c478bd9Sstevel@tonic-gate	# Loop over each object item in the working_dir.
136*7c478bd9Sstevel@tonic-gate	#  - $dir will be each one of these object directories.
137*7c478bd9Sstevel@tonic-gate	#  - $path_to_object will be the corresponding actual path
138*7c478bd9Sstevel@tonic-gate	#    to the the binary to be profiled.
139*7c478bd9Sstevel@tonic-gate	# Output will be placed down in $dir, e.g. "$dir/report"
140*7c478bd9Sstevel@tonic-gate	#
141*7c478bd9Sstevel@tonic-gate
142*7c478bd9Sstevel@tonic-gate	while (defined($dir = next_dir_name())) {
143*7c478bd9Sstevel@tonic-gate
144*7c478bd9Sstevel@tonic-gate		# Map object output dir to actual path of the object:
145*7c478bd9Sstevel@tonic-gate		$path_to_object = dir_name_to_path($dir);
146*7c478bd9Sstevel@tonic-gate
147*7c478bd9Sstevel@tonic-gate		# Make a report for it:
148*7c478bd9Sstevel@tonic-gate		report_object($path_to_object, $dir);
149*7c478bd9Sstevel@tonic-gate	}
150*7c478bd9Sstevel@tonic-gate
151*7c478bd9Sstevel@tonic-gate	my $type;
152*7c478bd9Sstevel@tonic-gate	foreach $type (keys(%result_list_hash)) {
153*7c478bd9Sstevel@tonic-gate		$result_list_hash{$type} =~ s/\|+$//;
154*7c478bd9Sstevel@tonic-gate	}
155*7c478bd9Sstevel@tonic-gate
156*7c478bd9Sstevel@tonic-gate	print_report();
157*7c478bd9Sstevel@tonic-gate	my $tout;
158*7c478bd9Sstevel@tonic-gate	$tout = gettext(
159*7c478bd9Sstevel@tonic-gate	    "Additional output regarding private symbols usage and other\n" .
160*7c478bd9Sstevel@tonic-gate	    "data is in the directory:\n");
161*7c478bd9Sstevel@tonic-gate
162*7c478bd9Sstevel@tonic-gate	$tout .= "\n   $working_dir\n\n";
163*7c478bd9Sstevel@tonic-gate
164*7c478bd9Sstevel@tonic-gate	$tout .= gettext(
165*7c478bd9Sstevel@tonic-gate	    "see the appcert documentation for more information.\n");
166*7c478bd9Sstevel@tonic-gate
167*7c478bd9Sstevel@tonic-gate	pmsg("%s", $tout);
168*7c478bd9Sstevel@tonic-gate
169*7c478bd9Sstevel@tonic-gate	clean_up();	# Remove any tmp directories and files.
170*7c478bd9Sstevel@tonic-gate}
171*7c478bd9Sstevel@tonic-gate
172*7c478bd9Sstevel@tonic-gate#
173*7c478bd9Sstevel@tonic-gate# Examines the symcheck output for a given binary object recording and
174*7c478bd9Sstevel@tonic-gate# reporting and problems found.  Generates additional reports and
175*7c478bd9Sstevel@tonic-gate# summaries.
176*7c478bd9Sstevel@tonic-gate#
177*7c478bd9Sstevel@tonic-gatesub report_object
178*7c478bd9Sstevel@tonic-gate{
179*7c478bd9Sstevel@tonic-gate	my ($object, $dir) = @_;
180*7c478bd9Sstevel@tonic-gate
181*7c478bd9Sstevel@tonic-gate	my (%problems);
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate	my $problems_file = "$dir/check.problems";
184*7c478bd9Sstevel@tonic-gate
185*7c478bd9Sstevel@tonic-gate	my $problems_fh = do { local *FH; *FH };
186*7c478bd9Sstevel@tonic-gate	open($problems_fh, "<$problems_file") ||
187*7c478bd9Sstevel@tonic-gate	    exiter(nofile($problems_file, $!));
188*7c478bd9Sstevel@tonic-gate
189*7c478bd9Sstevel@tonic-gate	# We need the "warning" msgs and text from the Misc Checks loaded:
190*7c478bd9Sstevel@tonic-gate	if (! defined($misc_check_databases_loaded_ok)) {
191*7c478bd9Sstevel@tonic-gate		$misc_check_databases_loaded_ok = load_misc_check_databases();
192*7c478bd9Sstevel@tonic-gate	}
193*7c478bd9Sstevel@tonic-gate
194*7c478bd9Sstevel@tonic-gate	my ($prob, $incomp, $c, $w);
195*7c478bd9Sstevel@tonic-gate	my $problem_count = 0;
196*7c478bd9Sstevel@tonic-gate	my $incomplete_count = 0;
197*7c478bd9Sstevel@tonic-gate	my $line_count = 0;
198*7c478bd9Sstevel@tonic-gate
199*7c478bd9Sstevel@tonic-gate	while (<$problems_fh>) {
200*7c478bd9Sstevel@tonic-gate		chomp;
201*7c478bd9Sstevel@tonic-gate		$prob = 1;
202*7c478bd9Sstevel@tonic-gate		$incomp = 0;
203*7c478bd9Sstevel@tonic-gate		$line_count++;
204*7c478bd9Sstevel@tonic-gate
205*7c478bd9Sstevel@tonic-gate		if (/^DYNAMIC: PRIVATE_SYMBOL_USE\s+(\d*)/) {
206*7c478bd9Sstevel@tonic-gate			$problems{'private_syms'} += $1;
207*7c478bd9Sstevel@tonic-gate		} elsif (/^DYNAMIC: UNBOUND_SYMBOL_USE\s+(\d*)/) {
208*7c478bd9Sstevel@tonic-gate			$problems{'unbound_syms'} += $1;
209*7c478bd9Sstevel@tonic-gate			$incomp = 1;
210*7c478bd9Sstevel@tonic-gate		} elsif (/^DYNAMIC: UNRECOGNIZED_SYMBOL_USE\s+(\d*)/) {
211*7c478bd9Sstevel@tonic-gate			$problems{'unrecognized_syms'} += $1;
212*7c478bd9Sstevel@tonic-gate			$incomp = 1;
213*7c478bd9Sstevel@tonic-gate		} elsif (/^DYNAMIC: NO_DYNAMIC_BINDINGS_FOUND\s*(.*)$/) {
214*7c478bd9Sstevel@tonic-gate			$problems{'no_dynamic_bindings'} .= "$1, ";
215*7c478bd9Sstevel@tonic-gate			$incomp = 1;
216*7c478bd9Sstevel@tonic-gate		} elsif (/^STATIC: LINKED_ARCHIVE\s+(.*)$/) {
217*7c478bd9Sstevel@tonic-gate			$problems{'static_linking'} .= "$1, ";
218*7c478bd9Sstevel@tonic-gate		} elsif (/^STATIC: COMPLETELY_STATIC/) {
219*7c478bd9Sstevel@tonic-gate			$problems{'completely_static'}++;
220*7c478bd9Sstevel@tonic-gate		} elsif (/^MISC: REMOVED_SCOPED_SYMBOLS:\s+(.*)$/) {
221*7c478bd9Sstevel@tonic-gate			$problems{'scoped_symbols'} .= "$1, ";
222*7c478bd9Sstevel@tonic-gate		} elsif (/^MISC: WARNING:\s+(INCOMPLETE\S+)/) {
223*7c478bd9Sstevel@tonic-gate			$problems{'warnings'} .= "$1|";
224*7c478bd9Sstevel@tonic-gate			$incomp = 1;
225*7c478bd9Sstevel@tonic-gate		} elsif (/^MISC: WARNING:\s+(.*)$/) {
226*7c478bd9Sstevel@tonic-gate			$problems{'warnings'} .= "$1|";
227*7c478bd9Sstevel@tonic-gate		} else {
228*7c478bd9Sstevel@tonic-gate			$prob = 0;
229*7c478bd9Sstevel@tonic-gate		}
230*7c478bd9Sstevel@tonic-gate		$problem_count += $prob;
231*7c478bd9Sstevel@tonic-gate		$incomplete_count += $incomp;
232*7c478bd9Sstevel@tonic-gate	}
233*7c478bd9Sstevel@tonic-gate	close($problems_fh);
234*7c478bd9Sstevel@tonic-gate
235*7c478bd9Sstevel@tonic-gate	if ($line_count == 0) {
236*7c478bd9Sstevel@tonic-gate		# No problems at all, leave a comment message:
237*7c478bd9Sstevel@tonic-gate		open($problems_fh, ">$problems_file") ||
238*7c478bd9Sstevel@tonic-gate		    exiter(nofile($problems_file, $!));
239*7c478bd9Sstevel@tonic-gate		print $problems_fh "# NO_PROBLEMS_DETECTED\n";
240*7c478bd9Sstevel@tonic-gate		close($problems_fh);
241*7c478bd9Sstevel@tonic-gate	}
242*7c478bd9Sstevel@tonic-gate
243*7c478bd9Sstevel@tonic-gate	if ($problem_count == 0) {
244*7c478bd9Sstevel@tonic-gate		$result_list_hash{'passed'} .= "$object|";
245*7c478bd9Sstevel@tonic-gate		return;
246*7c478bd9Sstevel@tonic-gate	}
247*7c478bd9Sstevel@tonic-gate
248*7c478bd9Sstevel@tonic-gate	if ($incomplete_count == $problem_count) {
249*7c478bd9Sstevel@tonic-gate		$result_list_hash{'incomplete'} .= "$object|";
250*7c478bd9Sstevel@tonic-gate	} else {
251*7c478bd9Sstevel@tonic-gate		$result_list_hash{'failed'} .= "$object|";
252*7c478bd9Sstevel@tonic-gate	}
253*7c478bd9Sstevel@tonic-gate
254*7c478bd9Sstevel@tonic-gate	my $m;
255*7c478bd9Sstevel@tonic-gate
256*7c478bd9Sstevel@tonic-gate	if ($m = $problems{'private_syms'}) {
257*7c478bd9Sstevel@tonic-gate		$result_list_hash{'private_syms'} .= "$object|";
258*7c478bd9Sstevel@tonic-gate		$result_msg{$object} .= "$m " .
259*7c478bd9Sstevel@tonic-gate		    gettext("private symbols") . "; ";
260*7c478bd9Sstevel@tonic-gate	}
261*7c478bd9Sstevel@tonic-gate
262*7c478bd9Sstevel@tonic-gate	if ($m = $problems{'unbound_syms'}) {
263*7c478bd9Sstevel@tonic-gate		$result_list_hash{'unbound_syms'} .= "$object|";
264*7c478bd9Sstevel@tonic-gate		$result_msg{$object} .= "$m " .
265*7c478bd9Sstevel@tonic-gate		    gettext("unbound symbols") . "; ";
266*7c478bd9Sstevel@tonic-gate
267*7c478bd9Sstevel@tonic-gate		# add this case to the warnings output at end of report.
268*7c478bd9Sstevel@tonic-gate		my $tag  = 'unbound symbols';
269*7c478bd9Sstevel@tonic-gate		$warnings_found{$tag} .= "$object|";
270*7c478bd9Sstevel@tonic-gate
271*7c478bd9Sstevel@tonic-gate		if (! exists($warnings_desc{$tag})) {
272*7c478bd9Sstevel@tonic-gate			my $desc = gettext("unbound symbols");
273*7c478bd9Sstevel@tonic-gate			$warnings_desc{$tag} = $desc;
274*7c478bd9Sstevel@tonic-gate		}
275*7c478bd9Sstevel@tonic-gate	}
276*7c478bd9Sstevel@tonic-gate
277*7c478bd9Sstevel@tonic-gate	if ($m = $problems{'unrecognized_syms'}) {
278*7c478bd9Sstevel@tonic-gate		$result_list_hash{'unrecognized_syms'} .= "$object|";
279*7c478bd9Sstevel@tonic-gate		$result_msg{$object} .= "$m " .
280*7c478bd9Sstevel@tonic-gate		    gettext("unrecognized symbols") . "; ";
281*7c478bd9Sstevel@tonic-gate
282*7c478bd9Sstevel@tonic-gate		# Add this case to the warnings output at end of report.
283*7c478bd9Sstevel@tonic-gate		my $tag  = 'unrecognized symbols';
284*7c478bd9Sstevel@tonic-gate		$warnings_found{$tag} .= "$object|";
285*7c478bd9Sstevel@tonic-gate
286*7c478bd9Sstevel@tonic-gate		if (! exists($warnings_desc{$tag})) {
287*7c478bd9Sstevel@tonic-gate			my $desc = gettext("unrecognized symbols");
288*7c478bd9Sstevel@tonic-gate			$warnings_desc{$tag} = $desc;
289*7c478bd9Sstevel@tonic-gate		}
290*7c478bd9Sstevel@tonic-gate	}
291*7c478bd9Sstevel@tonic-gate
292*7c478bd9Sstevel@tonic-gate	if ($m = $problems{'static_linking'}) {
293*7c478bd9Sstevel@tonic-gate		$result_list_hash{'static_linking'} .= "$object|";
294*7c478bd9Sstevel@tonic-gate		$m =~ s/,\s*$//;
295*7c478bd9Sstevel@tonic-gate		$result_msg{$object} .= sprintf(gettext(
296*7c478bd9Sstevel@tonic-gate		    "statically linked with %s"), $m) . "; ";
297*7c478bd9Sstevel@tonic-gate
298*7c478bd9Sstevel@tonic-gate		# Add this case to the warnings output at end of report.
299*7c478bd9Sstevel@tonic-gate		my $tag  = 'statically linked';
300*7c478bd9Sstevel@tonic-gate		$warnings_found{$tag} .= "$object|";
301*7c478bd9Sstevel@tonic-gate
302*7c478bd9Sstevel@tonic-gate		if (! exists($warnings_desc{$tag})) {
303*7c478bd9Sstevel@tonic-gate			my $desc =
304*7c478bd9Sstevel@tonic-gate			    gettext("static linking of Solaris libraries");
305*7c478bd9Sstevel@tonic-gate			$warnings_desc{$tag} = $desc;
306*7c478bd9Sstevel@tonic-gate		}
307*7c478bd9Sstevel@tonic-gate	}
308*7c478bd9Sstevel@tonic-gate
309*7c478bd9Sstevel@tonic-gate	if ($problems{'completely_static'}) {
310*7c478bd9Sstevel@tonic-gate		$result_list_hash{'completely_static'} .= "$object|";
311*7c478bd9Sstevel@tonic-gate		$result_msg{$object} .=
312*7c478bd9Sstevel@tonic-gate		    gettext("completely statically linked") . "; ";
313*7c478bd9Sstevel@tonic-gate
314*7c478bd9Sstevel@tonic-gate		# Add this case to the warnings output.
315*7c478bd9Sstevel@tonic-gate		my $tag  = gettext("completely statically linked");
316*7c478bd9Sstevel@tonic-gate		$warnings_found{$tag} .= "$object|";
317*7c478bd9Sstevel@tonic-gate
318*7c478bd9Sstevel@tonic-gate		my $desc =
319*7c478bd9Sstevel@tonic-gate		    gettext("complete static linking of Solaris libraries");
320*7c478bd9Sstevel@tonic-gate		if (! exists($warnings_desc{$tag})) {
321*7c478bd9Sstevel@tonic-gate			$warnings_desc{$tag} = $desc;
322*7c478bd9Sstevel@tonic-gate		}
323*7c478bd9Sstevel@tonic-gate
324*7c478bd9Sstevel@tonic-gate	} elsif ($m = $problems{'no_dynamic_bindings'}) {
325*7c478bd9Sstevel@tonic-gate		#
326*7c478bd9Sstevel@tonic-gate		# Note we skip this error if it is completely static.
327*7c478bd9Sstevel@tonic-gate		# The app could technically be SUID as well.
328*7c478bd9Sstevel@tonic-gate		#
329*7c478bd9Sstevel@tonic-gate
330*7c478bd9Sstevel@tonic-gate		$result_list_hash{'no_dynamic_bindings'} .= "$object|";
331*7c478bd9Sstevel@tonic-gate		$m =~ s/,\s*$//;
332*7c478bd9Sstevel@tonic-gate		$m = " : $m";
333*7c478bd9Sstevel@tonic-gate		$m =~ s/ : NO_SYMBOL_BINDINGS_FOUND//;
334*7c478bd9Sstevel@tonic-gate		$m =~ s/^ :/:/;
335*7c478bd9Sstevel@tonic-gate		$result_msg{$object} .=
336*7c478bd9Sstevel@tonic-gate		    gettext("no bindings found") . "$m; ";
337*7c478bd9Sstevel@tonic-gate	}
338*7c478bd9Sstevel@tonic-gate
339*7c478bd9Sstevel@tonic-gate	if ($m = $problems{'scoped_symbols'}) {
340*7c478bd9Sstevel@tonic-gate		$m =~ s/[,\s]*$//;
341*7c478bd9Sstevel@tonic-gate		$result_list_hash{'scoped_symbols'} .= "$object|";
342*7c478bd9Sstevel@tonic-gate		$c = scalar(my @a = split(' ', $m));
343*7c478bd9Sstevel@tonic-gate
344*7c478bd9Sstevel@tonic-gate		$result_msg{$object} .= "$c " .
345*7c478bd9Sstevel@tonic-gate		    gettext("demoted (removed) private symbols") . ": $m; ";
346*7c478bd9Sstevel@tonic-gate
347*7c478bd9Sstevel@tonic-gate		# Add this case to the warnings output.
348*7c478bd9Sstevel@tonic-gate		my $tag  = 'scoped symbols';
349*7c478bd9Sstevel@tonic-gate		$warnings_found{$tag} .= "$object|";
350*7c478bd9Sstevel@tonic-gate
351*7c478bd9Sstevel@tonic-gate		my $desc = gettext(
352*7c478bd9Sstevel@tonic-gate		    "dependency on demoted (removed) private Solaris symbols");
353*7c478bd9Sstevel@tonic-gate		if (! exists($warnings_desc{$tag})) {
354*7c478bd9Sstevel@tonic-gate			$warnings_desc{$tag} = $desc;
355*7c478bd9Sstevel@tonic-gate		}
356*7c478bd9Sstevel@tonic-gate	}
357*7c478bd9Sstevel@tonic-gate
358*7c478bd9Sstevel@tonic-gate	if ($m = $problems{'warnings'}) {
359*7c478bd9Sstevel@tonic-gate		foreach $w (split(/\|/, $m)) {
360*7c478bd9Sstevel@tonic-gate			next if ($w =~ /^\s*$/);
361*7c478bd9Sstevel@tonic-gate
362*7c478bd9Sstevel@tonic-gate			$c = $w;
363*7c478bd9Sstevel@tonic-gate			if (defined($warnings_desc{$c})) {
364*7c478bd9Sstevel@tonic-gate				$c = $warnings_desc{$c};
365*7c478bd9Sstevel@tonic-gate				$c = gettext($c);
366*7c478bd9Sstevel@tonic-gate			}
367*7c478bd9Sstevel@tonic-gate			$c =~ s/;//g;
368*7c478bd9Sstevel@tonic-gate			$result_msg{$object} .= "$c; ";
369*7c478bd9Sstevel@tonic-gate			$warnings_found{$w} .= "$object|";
370*7c478bd9Sstevel@tonic-gate		}
371*7c478bd9Sstevel@tonic-gate	}
372*7c478bd9Sstevel@tonic-gate
373*7c478bd9Sstevel@tonic-gate	$result_msg{$object} =~ s/;\s+$//;
374*7c478bd9Sstevel@tonic-gate}
375*7c478bd9Sstevel@tonic-gate
376*7c478bd9Sstevel@tonic-gate#
377*7c478bd9Sstevel@tonic-gate# Create the top level roll-up report.
378*7c478bd9Sstevel@tonic-gate#
379*7c478bd9Sstevel@tonic-gatesub print_report
380*7c478bd9Sstevel@tonic-gate{
381*7c478bd9Sstevel@tonic-gate	# Count the number of passed, failed and total binary objects:
382*7c478bd9Sstevel@tonic-gate	my(@a);
383*7c478bd9Sstevel@tonic-gate	my($r_passed, $r_incomp, $r_failed);
384*7c478bd9Sstevel@tonic-gate	if (exists($result_list_hash{'passed'})) {
385*7c478bd9Sstevel@tonic-gate		$r_passed = $result_list_hash{'passed'};
386*7c478bd9Sstevel@tonic-gate	} else {
387*7c478bd9Sstevel@tonic-gate		$r_passed = '';
388*7c478bd9Sstevel@tonic-gate	}
389*7c478bd9Sstevel@tonic-gate	if (exists($result_list_hash{'incomplete'})) {
390*7c478bd9Sstevel@tonic-gate		$r_incomp = $result_list_hash{'incomplete'};
391*7c478bd9Sstevel@tonic-gate	} else {
392*7c478bd9Sstevel@tonic-gate		$r_incomp = '';
393*7c478bd9Sstevel@tonic-gate	}
394*7c478bd9Sstevel@tonic-gate	if (exists($result_list_hash{'failed'})) {
395*7c478bd9Sstevel@tonic-gate		$r_failed = $result_list_hash{'failed'};
396*7c478bd9Sstevel@tonic-gate	} else {
397*7c478bd9Sstevel@tonic-gate		$r_failed = '';
398*7c478bd9Sstevel@tonic-gate	}
399*7c478bd9Sstevel@tonic-gate	my $n_passed = scalar(@a = split(/\|/, $r_passed));
400*7c478bd9Sstevel@tonic-gate	my $n_incomp = scalar(@a = split(/\|/, $r_incomp));
401*7c478bd9Sstevel@tonic-gate	my $n_failed = scalar(@a = split(/\|/, $r_failed));
402*7c478bd9Sstevel@tonic-gate	my $n_checked = $n_passed + $n_incomp + $n_failed;
403*7c478bd9Sstevel@tonic-gate
404*7c478bd9Sstevel@tonic-gate	my ($summary_result, $msg, $output, $object);
405*7c478bd9Sstevel@tonic-gate
406*7c478bd9Sstevel@tonic-gate
407*7c478bd9Sstevel@tonic-gate	if ($n_checked == 0) {
408*7c478bd9Sstevel@tonic-gate		$summary_result = $text{'Summary_Result_None_Checked'};
409*7c478bd9Sstevel@tonic-gate	} elsif ($n_failed > 0) {
410*7c478bd9Sstevel@tonic-gate		$summary_result = $text{'Summary_Result_Some_Failed'};
411*7c478bd9Sstevel@tonic-gate	} elsif ($n_incomp > 0) {
412*7c478bd9Sstevel@tonic-gate		$summary_result = $text{'Summary_Result_Some_Incomplete'};
413*7c478bd9Sstevel@tonic-gate	} else {
414*7c478bd9Sstevel@tonic-gate		$summary_result = $text{'Summary_Result_All_Passed'};
415*7c478bd9Sstevel@tonic-gate	}
416*7c478bd9Sstevel@tonic-gate
417*7c478bd9Sstevel@tonic-gate	# place the info in problem count file:
418*7c478bd9Sstevel@tonic-gate	my $cnt_file = "$working_dir/ProblemCount";
419*7c478bd9Sstevel@tonic-gate	my $pcount_fh = do { local *FH; *FH };
420*7c478bd9Sstevel@tonic-gate	if (! open($pcount_fh, ">$cnt_file")) {
421*7c478bd9Sstevel@tonic-gate		exiter(nofile($cnt_file, $!));
422*7c478bd9Sstevel@tonic-gate	}
423*7c478bd9Sstevel@tonic-gate
424*7c478bd9Sstevel@tonic-gate	print $pcount_fh "$n_failed / $n_checked binary_objects_had_problems\n";
425*7c478bd9Sstevel@tonic-gate	print $pcount_fh
426*7c478bd9Sstevel@tonic-gate	    "$n_incomp / $n_checked could_not_be_completely_checked\n";
427*7c478bd9Sstevel@tonic-gate
428*7c478bd9Sstevel@tonic-gate	print $pcount_fh "NO_PROBLEMS_LIST: $r_passed\n";
429*7c478bd9Sstevel@tonic-gate	print $pcount_fh "INCOMPLETE_LIST: $r_incomp\n";
430*7c478bd9Sstevel@tonic-gate	print $pcount_fh "PROBLEMS_LIST: $r_failed\n";
431*7c478bd9Sstevel@tonic-gate	close($pcount_fh);
432*7c478bd9Sstevel@tonic-gate
433*7c478bd9Sstevel@tonic-gate	#
434*7c478bd9Sstevel@tonic-gate	# Set the overall result code.
435*7c478bd9Sstevel@tonic-gate	# This is used to communicate back to the appcert script to
436*7c478bd9Sstevel@tonic-gate	# indicate how it should exit(). The string must start with the
437*7c478bd9Sstevel@tonic-gate	# exit number, after which a message may follow.
438*7c478bd9Sstevel@tonic-gate	#
439*7c478bd9Sstevel@tonic-gate
440*7c478bd9Sstevel@tonic-gate	if ($n_checked == 0) {
441*7c478bd9Sstevel@tonic-gate		overall_result_code("3 => nothing_checked");
442*7c478bd9Sstevel@tonic-gate	} elsif ($n_failed > 0) {
443*7c478bd9Sstevel@tonic-gate		overall_result_code("2 => some_problems_detected($n_failed)");
444*7c478bd9Sstevel@tonic-gate	} elsif ($n_incomp > 0) {
445*7c478bd9Sstevel@tonic-gate		overall_result_code("1 => " .
446*7c478bd9Sstevel@tonic-gate		    "some_binaries_incompletely_checked($n_incomp)");
447*7c478bd9Sstevel@tonic-gate	} else {
448*7c478bd9Sstevel@tonic-gate		overall_result_code("0 => no_problems_detected");
449*7c478bd9Sstevel@tonic-gate	}
450*7c478bd9Sstevel@tonic-gate
451*7c478bd9Sstevel@tonic-gate	my ($sp0, $sp, $sf, $si);	# PASS & FAIL spacing tags.
452*7c478bd9Sstevel@tonic-gate	$sp0 = '   ';
453*7c478bd9Sstevel@tonic-gate	if ($batch_report) {
454*7c478bd9Sstevel@tonic-gate		$sp = 'PASS ';
455*7c478bd9Sstevel@tonic-gate		$sf = 'FAIL ';
456*7c478bd9Sstevel@tonic-gate		$si = 'INC  ';
457*7c478bd9Sstevel@tonic-gate	} else {
458*7c478bd9Sstevel@tonic-gate		$sp = $sp0;
459*7c478bd9Sstevel@tonic-gate		$sf = $sp0;
460*7c478bd9Sstevel@tonic-gate		$si = $sp0;
461*7c478bd9Sstevel@tonic-gate	}
462*7c478bd9Sstevel@tonic-gate
463*7c478bd9Sstevel@tonic-gate
464*7c478bd9Sstevel@tonic-gate	$msg = sprintf(gettext("Summary: %s"), $summary_result) . "\n\n";
465*7c478bd9Sstevel@tonic-gate	my $format = gettext("A total of %d binary objects were examined.");
466*7c478bd9Sstevel@tonic-gate	$msg .= sprintf($format, $n_checked) . "\n\n\n";
467*7c478bd9Sstevel@tonic-gate	$output .= $msg;
468*7c478bd9Sstevel@tonic-gate
469*7c478bd9Sstevel@tonic-gate	my $fmt1 = gettext(
470*7c478bd9Sstevel@tonic-gate	    "The following (%d of %d) components had no problems detected:");
471*7c478bd9Sstevel@tonic-gate
472*7c478bd9Sstevel@tonic-gate	if ($n_passed > 0) {
473*7c478bd9Sstevel@tonic-gate		$output .= sprintf($fmt1, $n_passed, $n_checked);
474*7c478bd9Sstevel@tonic-gate		$output .= "\n\n";
475*7c478bd9Sstevel@tonic-gate
476*7c478bd9Sstevel@tonic-gate		foreach $object (split(/\|/, $r_passed)) {
477*7c478bd9Sstevel@tonic-gate			$output .= "${sp}$object\n";
478*7c478bd9Sstevel@tonic-gate		}
479*7c478bd9Sstevel@tonic-gate		$output .= "\n";
480*7c478bd9Sstevel@tonic-gate	}
481*7c478bd9Sstevel@tonic-gate
482*7c478bd9Sstevel@tonic-gate	my $fmt2 = gettext(
483*7c478bd9Sstevel@tonic-gate	    "The following (%d of %d) components had no problems detected,\n" .
484*7c478bd9Sstevel@tonic-gate	    "   but could not be completely checked:");
485*7c478bd9Sstevel@tonic-gate
486*7c478bd9Sstevel@tonic-gate	if ($n_incomp > 0) {
487*7c478bd9Sstevel@tonic-gate		$output .= sprintf($fmt2, $n_incomp, $n_checked);
488*7c478bd9Sstevel@tonic-gate		$output .= "\n\n";
489*7c478bd9Sstevel@tonic-gate
490*7c478bd9Sstevel@tonic-gate		foreach $object (split(/\|/, $r_incomp)) {
491*7c478bd9Sstevel@tonic-gate			$msg = $result_msg{$object};
492*7c478bd9Sstevel@tonic-gate			$output .= "${si}$object\t($msg)\n";
493*7c478bd9Sstevel@tonic-gate		}
494*7c478bd9Sstevel@tonic-gate		$output .= "\n";
495*7c478bd9Sstevel@tonic-gate	}
496*7c478bd9Sstevel@tonic-gate
497*7c478bd9Sstevel@tonic-gate	my $fmt3 = gettext(
498*7c478bd9Sstevel@tonic-gate	    "The following (%d of %d) components have potential " .
499*7c478bd9Sstevel@tonic-gate	    "stability problems:");
500*7c478bd9Sstevel@tonic-gate	if ($n_failed > 0) {
501*7c478bd9Sstevel@tonic-gate		$output .= sprintf($fmt3, $n_failed, $n_checked);
502*7c478bd9Sstevel@tonic-gate		$output .= "\n\n";
503*7c478bd9Sstevel@tonic-gate
504*7c478bd9Sstevel@tonic-gate		foreach $object (split(/\|/, $r_failed)) {
505*7c478bd9Sstevel@tonic-gate			$msg = $result_msg{$object};
506*7c478bd9Sstevel@tonic-gate			$output .= "${sf}$object\t($msg)\n";
507*7c478bd9Sstevel@tonic-gate		}
508*7c478bd9Sstevel@tonic-gate		$output .= "\n";
509*7c478bd9Sstevel@tonic-gate	}
510*7c478bd9Sstevel@tonic-gate
511*7c478bd9Sstevel@tonic-gate	$output .= "\n" . get_summary();
512*7c478bd9Sstevel@tonic-gate
513*7c478bd9Sstevel@tonic-gate	$output .= "\n" . get_warnings();
514*7c478bd9Sstevel@tonic-gate
515*7c478bd9Sstevel@tonic-gate	my $report_file = "$working_dir/Report";
516*7c478bd9Sstevel@tonic-gate	my $report_fh = do { local *FH; *FH };
517*7c478bd9Sstevel@tonic-gate	open($report_fh, ">$report_file") ||
518*7c478bd9Sstevel@tonic-gate	    exiter(nofile($report_file, $!));
519*7c478bd9Sstevel@tonic-gate
520*7c478bd9Sstevel@tonic-gate	print $report_fh $output;
521*7c478bd9Sstevel@tonic-gate	close($report_fh);
522*7c478bd9Sstevel@tonic-gate	system($cmd_more, $report_file);
523*7c478bd9Sstevel@tonic-gate}
524*7c478bd9Sstevel@tonic-gate
525*7c478bd9Sstevel@tonic-gate#
526*7c478bd9Sstevel@tonic-gate# Collects all of the warnings issued for the binaries that were
527*7c478bd9Sstevel@tonic-gate# checked.  Returns the warning text that will go into the roll-up
528*7c478bd9Sstevel@tonic-gate# report.
529*7c478bd9Sstevel@tonic-gate#
530*7c478bd9Sstevel@tonic-gatesub get_warnings
531*7c478bd9Sstevel@tonic-gate{
532*7c478bd9Sstevel@tonic-gate	my ($w, $c, $output, $count);
533*7c478bd9Sstevel@tonic-gate
534*7c478bd9Sstevel@tonic-gate	if (! %warnings_found) {
535*7c478bd9Sstevel@tonic-gate		return '';	# appends null string to output text
536*7c478bd9Sstevel@tonic-gate	}
537*7c478bd9Sstevel@tonic-gate
538*7c478bd9Sstevel@tonic-gate	$output = gettext("Summary of various warnings:") . "\n\n";
539*7c478bd9Sstevel@tonic-gate	my(@a);
540*7c478bd9Sstevel@tonic-gate	foreach $w (keys(%warnings_found)) {
541*7c478bd9Sstevel@tonic-gate		$warnings_found{$w} =~ s/\|+$//;
542*7c478bd9Sstevel@tonic-gate		$count = scalar(@a = split(/\|/, $warnings_found{$w}));
543*7c478bd9Sstevel@tonic-gate		$c = $w;
544*7c478bd9Sstevel@tonic-gate		if (defined($warnings_desc{$c})) {
545*7c478bd9Sstevel@tonic-gate			$c = $warnings_desc{$c};
546*7c478bd9Sstevel@tonic-gate		}
547*7c478bd9Sstevel@tonic-gate		$c = gettext($c);
548*7c478bd9Sstevel@tonic-gate		$output .= " - $c  " . sprintf(gettext(
549*7c478bd9Sstevel@tonic-gate		    "(%d binaries)\n"), $count);
550*7c478bd9Sstevel@tonic-gate		$output .= "\n";
551*7c478bd9Sstevel@tonic-gate
552*7c478bd9Sstevel@tonic-gate	}
553*7c478bd9Sstevel@tonic-gate	$output .= "\n";
554*7c478bd9Sstevel@tonic-gate
555*7c478bd9Sstevel@tonic-gate	return $output;
556*7c478bd9Sstevel@tonic-gate}
557*7c478bd9Sstevel@tonic-gate
558*7c478bd9Sstevel@tonic-gate#
559*7c478bd9Sstevel@tonic-gate# Computes the summary information for each binary object that was
560*7c478bd9Sstevel@tonic-gate# checked.  Returns the text that will go into the roll-up report.
561*7c478bd9Sstevel@tonic-gate#
562*7c478bd9Sstevel@tonic-gatesub get_summary
563*7c478bd9Sstevel@tonic-gate{
564*7c478bd9Sstevel@tonic-gate	my ($dir, $file);
565*7c478bd9Sstevel@tonic-gate	my (%lib_private, %libsym_private);
566*7c478bd9Sstevel@tonic-gate	my (%libapp, %libapp_private);
567*7c478bd9Sstevel@tonic-gate
568*7c478bd9Sstevel@tonic-gate	my ($bin, $arch, $direct, $lib, $class, $sym);
569*7c478bd9Sstevel@tonic-gate
570*7c478bd9Sstevel@tonic-gate	while (defined($dir = next_dir_name())) {
571*7c478bd9Sstevel@tonic-gate
572*7c478bd9Sstevel@tonic-gate		# This is where the public symbol list is:
573*7c478bd9Sstevel@tonic-gate		$file = "$dir/check.dynamic.public";
574*7c478bd9Sstevel@tonic-gate
575*7c478bd9Sstevel@tonic-gate		my %app_public;
576*7c478bd9Sstevel@tonic-gate		my %app_sym_public;
577*7c478bd9Sstevel@tonic-gate		my %app_private;
578*7c478bd9Sstevel@tonic-gate		my %app_sym_private;
579*7c478bd9Sstevel@tonic-gate
580*7c478bd9Sstevel@tonic-gate		if (-s $file) {
581*7c478bd9Sstevel@tonic-gate			my $publics_fh = do { local *FH; *FH };
582*7c478bd9Sstevel@tonic-gate			open($publics_fh, "<$file") ||
583*7c478bd9Sstevel@tonic-gate			    exiter(nofile($file, $!));
584*7c478bd9Sstevel@tonic-gate
585*7c478bd9Sstevel@tonic-gate			while (<$publics_fh>) {
586*7c478bd9Sstevel@tonic-gate				next if (/^\s*#/);
587*7c478bd9Sstevel@tonic-gate				chomp;
588*7c478bd9Sstevel@tonic-gate				($bin, $arch, $direct, $lib, $class, $sym) =
589*7c478bd9Sstevel@tonic-gate				    split(/\|/, $_);
590*7c478bd9Sstevel@tonic-gate
591*7c478bd9Sstevel@tonic-gate				$libapp{"$lib|$bin"}++;
592*7c478bd9Sstevel@tonic-gate
593*7c478bd9Sstevel@tonic-gate				$app_public{$lib}++;
594*7c478bd9Sstevel@tonic-gate				$app_sym_public{"$lib|$sym"}++;
595*7c478bd9Sstevel@tonic-gate			}
596*7c478bd9Sstevel@tonic-gate			close($publics_fh);
597*7c478bd9Sstevel@tonic-gate		}
598*7c478bd9Sstevel@tonic-gate
599*7c478bd9Sstevel@tonic-gate		# This is where the private symbol list is:
600*7c478bd9Sstevel@tonic-gate		$file = "$dir/check.dynamic.private";
601*7c478bd9Sstevel@tonic-gate
602*7c478bd9Sstevel@tonic-gate		if (-s $file) {
603*7c478bd9Sstevel@tonic-gate			my $privates_fh = do { local *FH; *FH };
604*7c478bd9Sstevel@tonic-gate			open($privates_fh, "<$file") ||
605*7c478bd9Sstevel@tonic-gate			    exiter(nofile($file, $!));
606*7c478bd9Sstevel@tonic-gate
607*7c478bd9Sstevel@tonic-gate			while (<$privates_fh>) {
608*7c478bd9Sstevel@tonic-gate				next if (/^\s*#/);
609*7c478bd9Sstevel@tonic-gate				chomp;
610*7c478bd9Sstevel@tonic-gate				($bin, $arch, $direct, $lib, $class, $sym) =
611*7c478bd9Sstevel@tonic-gate				    split(/\|/, $_);
612*7c478bd9Sstevel@tonic-gate
613*7c478bd9Sstevel@tonic-gate				$lib_private{$lib}++;
614*7c478bd9Sstevel@tonic-gate				$libsym_private{"$lib|$sym"}++;
615*7c478bd9Sstevel@tonic-gate				$libapp_private{"$lib|$bin"}++;
616*7c478bd9Sstevel@tonic-gate				$libapp{"$lib|$bin"}++;
617*7c478bd9Sstevel@tonic-gate
618*7c478bd9Sstevel@tonic-gate				$app_private{$lib}++;
619*7c478bd9Sstevel@tonic-gate				$app_sym_private{"$lib|$sym"}++;
620*7c478bd9Sstevel@tonic-gate			}
621*7c478bd9Sstevel@tonic-gate			close($privates_fh);
622*7c478bd9Sstevel@tonic-gate		}
623*7c478bd9Sstevel@tonic-gate
624*7c478bd9Sstevel@tonic-gate		write_app_summary($dir, \%app_public, \%app_sym_public,
625*7c478bd9Sstevel@tonic-gate		    \%app_private, \%app_sym_private);
626*7c478bd9Sstevel@tonic-gate	}
627*7c478bd9Sstevel@tonic-gate
628*7c478bd9Sstevel@tonic-gate	my ($app_total, $app_private_total);
629*7c478bd9Sstevel@tonic-gate	my ($key, $lib2, $app2, $sym2);
630*7c478bd9Sstevel@tonic-gate	my $val;
631*7c478bd9Sstevel@tonic-gate	my $text;
632*7c478bd9Sstevel@tonic-gate
633*7c478bd9Sstevel@tonic-gate	foreach $lib (sort(keys(%lib_private))) {
634*7c478bd9Sstevel@tonic-gate
635*7c478bd9Sstevel@tonic-gate		$app_total = 0;
636*7c478bd9Sstevel@tonic-gate		foreach $key (keys(%libapp)) {
637*7c478bd9Sstevel@tonic-gate			($lib2, $app2) = split(/\|/, $key);
638*7c478bd9Sstevel@tonic-gate			$app_total++ if ($lib eq $lib2);
639*7c478bd9Sstevel@tonic-gate		}
640*7c478bd9Sstevel@tonic-gate
641*7c478bd9Sstevel@tonic-gate		$app_private_total = 0;
642*7c478bd9Sstevel@tonic-gate		foreach $key (keys(%libapp_private)) {
643*7c478bd9Sstevel@tonic-gate			($lib2, $app2) = split(/\|/, $key);
644*7c478bd9Sstevel@tonic-gate			$app_private_total++ if ($lib eq $lib2);
645*7c478bd9Sstevel@tonic-gate		}
646*7c478bd9Sstevel@tonic-gate
647*7c478bd9Sstevel@tonic-gate		my @list;
648*7c478bd9Sstevel@tonic-gate		while (($key, $val) =  each(%libsym_private)) {
649*7c478bd9Sstevel@tonic-gate			($lib2, $sym2) = split(/\|/, $key);
650*7c478bd9Sstevel@tonic-gate			next unless ($lib eq $lib2);
651*7c478bd9Sstevel@tonic-gate			push(@list, "$sym2 $val");
652*7c478bd9Sstevel@tonic-gate
653*7c478bd9Sstevel@tonic-gate		}
654*7c478bd9Sstevel@tonic-gate
655*7c478bd9Sstevel@tonic-gate		$text .= private_format($lib, $app_total,
656*7c478bd9Sstevel@tonic-gate		    $app_private_total, @list);
657*7c478bd9Sstevel@tonic-gate	}
658*7c478bd9Sstevel@tonic-gate
659*7c478bd9Sstevel@tonic-gate	if (! defined($text)) {
660*7c478bd9Sstevel@tonic-gate		return '';	# appends null string to output report.
661*7c478bd9Sstevel@tonic-gate	}
662*7c478bd9Sstevel@tonic-gate	return $text;
663*7c478bd9Sstevel@tonic-gate}
664*7c478bd9Sstevel@tonic-gate
665*7c478bd9Sstevel@tonic-gate#
666*7c478bd9Sstevel@tonic-gate# Given the symbols and counts of private symbols used by all binaries
667*7c478bd9Sstevel@tonic-gate# that were checked, returns a pretty-printed format table of the
668*7c478bd9Sstevel@tonic-gate# symbols. This text goes into the roll-up report and the summary.dynamic
669*7c478bd9Sstevel@tonic-gate# file.
670*7c478bd9Sstevel@tonic-gate#
671*7c478bd9Sstevel@tonic-gatesub private_format
672*7c478bd9Sstevel@tonic-gate{
673*7c478bd9Sstevel@tonic-gate	my ($lib, $tot, $priv, @list) = @_;
674*7c478bd9Sstevel@tonic-gate
675*7c478bd9Sstevel@tonic-gate	my (@sorted) = sort_on_count(@list);
676*7c478bd9Sstevel@tonic-gate	my $formatted = list_format('  ', @sorted);
677*7c478bd9Sstevel@tonic-gate
678*7c478bd9Sstevel@tonic-gate	my $text;
679*7c478bd9Sstevel@tonic-gate	my $libbase = basename($lib);
680*7c478bd9Sstevel@tonic-gate
681*7c478bd9Sstevel@tonic-gate	$text = sprintf(gettext(
682*7c478bd9Sstevel@tonic-gate	    "Summary of Private symbol use in %s\n"), $lib);
683*7c478bd9Sstevel@tonic-gate	my $fmt =
684*7c478bd9Sstevel@tonic-gate	    gettext("%d binaries used %s, %d of these used private symbols");
685*7c478bd9Sstevel@tonic-gate	$text .= sprintf($fmt, $tot, $libbase, $priv);
686*7c478bd9Sstevel@tonic-gate	$text .= "\n\n$formatted\n";
687*7c478bd9Sstevel@tonic-gate
688*7c478bd9Sstevel@tonic-gate	return $text;
689*7c478bd9Sstevel@tonic-gate}
690*7c478bd9Sstevel@tonic-gate
691*7c478bd9Sstevel@tonic-gate#
692*7c478bd9Sstevel@tonic-gate# Given the public/private symbol and library usage information for a
693*7c478bd9Sstevel@tonic-gate# binary object, creates an output file with this information formatted
694*7c478bd9Sstevel@tonic-gate# in tables.
695*7c478bd9Sstevel@tonic-gate#
696*7c478bd9Sstevel@tonic-gatesub write_app_summary
697*7c478bd9Sstevel@tonic-gate{
698*7c478bd9Sstevel@tonic-gate	my ($dir, $public, $sym_public, $private, $sym_private) = @_;
699*7c478bd9Sstevel@tonic-gate
700*7c478bd9Sstevel@tonic-gate	my $outfile = "$dir/summary.dynamic";
701*7c478bd9Sstevel@tonic-gate
702*7c478bd9Sstevel@tonic-gate	my $summary_fh = do { local *FH; *FH };
703*7c478bd9Sstevel@tonic-gate	open($summary_fh, ">$outfile") ||
704*7c478bd9Sstevel@tonic-gate	    exiter(nofile($outfile, $!));
705*7c478bd9Sstevel@tonic-gate
706*7c478bd9Sstevel@tonic-gate	my $path_to_object = dir_name_to_path($dir);
707*7c478bd9Sstevel@tonic-gate
708*7c478bd9Sstevel@tonic-gate
709*7c478bd9Sstevel@tonic-gate	my ($tmp1, $tmp2, $tmp3);
710*7c478bd9Sstevel@tonic-gate
711*7c478bd9Sstevel@tonic-gate	$tmp1 = gettext("ABI SYMBOL USAGE SUMMARY REPORT");
712*7c478bd9Sstevel@tonic-gate	$tmp2 = '*' x length($tmp1);
713*7c478bd9Sstevel@tonic-gate
714*7c478bd9Sstevel@tonic-gate	print $summary_fh "$tmp2\n$tmp1\n$tmp2\n\n";
715*7c478bd9Sstevel@tonic-gate
716*7c478bd9Sstevel@tonic-gate	print $summary_fh "  ", sprintf(gettext(
717*7c478bd9Sstevel@tonic-gate	    "Binary Object: %s\n"), $path_to_object);
718*7c478bd9Sstevel@tonic-gate
719*7c478bd9Sstevel@tonic-gate	my $uname_a = `$cmd_uname -a`;
720*7c478bd9Sstevel@tonic-gate	print $summary_fh "  ", sprintf(gettext("System: %s\n"), $uname_a);
721*7c478bd9Sstevel@tonic-gate
722*7c478bd9Sstevel@tonic-gate	$tmp1 = gettext("References to shared objects in the Solaris ABI");
723*7c478bd9Sstevel@tonic-gate	$tmp2 = '*' x length($tmp1);
724*7c478bd9Sstevel@tonic-gate
725*7c478bd9Sstevel@tonic-gate	print $summary_fh "$tmp2\n$tmp1\n$tmp2\n\n";
726*7c478bd9Sstevel@tonic-gate
727*7c478bd9Sstevel@tonic-gate
728*7c478bd9Sstevel@tonic-gate	my (%libs, $lib, $maxlen, $len);
729*7c478bd9Sstevel@tonic-gate	$maxlen = 0;
730*7c478bd9Sstevel@tonic-gate
731*7c478bd9Sstevel@tonic-gate	foreach $lib (keys(%$public), keys(%$private)) {
732*7c478bd9Sstevel@tonic-gate		$len = length($lib);
733*7c478bd9Sstevel@tonic-gate		$maxlen = $len if ($len > $maxlen);
734*7c478bd9Sstevel@tonic-gate		$libs{$lib} = 1;
735*7c478bd9Sstevel@tonic-gate	}
736*7c478bd9Sstevel@tonic-gate
737*7c478bd9Sstevel@tonic-gate	if (! %libs) {
738*7c478bd9Sstevel@tonic-gate		my $str = gettext(
739*7c478bd9Sstevel@tonic-gate		"  NONE FOUND. Possible explanations:\n" .
740*7c478bd9Sstevel@tonic-gate		"    - the dynamic profiling failed, see ldd(1), ld.so.1(1)\n" .
741*7c478bd9Sstevel@tonic-gate		"    - the object is SUID or SGID\n" .
742*7c478bd9Sstevel@tonic-gate		"    - the object is completely statically linked.\n"
743*7c478bd9Sstevel@tonic-gate		);
744*7c478bd9Sstevel@tonic-gate		print $summary_fh $str, "\n";
745*7c478bd9Sstevel@tonic-gate		close($summary_fh);
746*7c478bd9Sstevel@tonic-gate		return;
747*7c478bd9Sstevel@tonic-gate	}
748*7c478bd9Sstevel@tonic-gate
749*7c478bd9Sstevel@tonic-gate	foreach $lib (sort(keys(%libs))) {
750*7c478bd9Sstevel@tonic-gate		print $summary_fh "  $lib\n";
751*7c478bd9Sstevel@tonic-gate	}
752*7c478bd9Sstevel@tonic-gate	print $summary_fh "\n";
753*7c478bd9Sstevel@tonic-gate
754*7c478bd9Sstevel@tonic-gate	my ($len1, $len2, $len3);
755*7c478bd9Sstevel@tonic-gate	my $heading = '  ' . gettext("Library");
756*7c478bd9Sstevel@tonic-gate	$heading .= ' ' x ($maxlen + 6 - length($heading));
757*7c478bd9Sstevel@tonic-gate	$len1 = length($heading) - 2;
758*7c478bd9Sstevel@tonic-gate	my $public_str = gettext("Public");
759*7c478bd9Sstevel@tonic-gate	$len2 = length($public_str);
760*7c478bd9Sstevel@tonic-gate	my $private_str = gettext("Private");
761*7c478bd9Sstevel@tonic-gate	$len3 = length("  $private_str");
762*7c478bd9Sstevel@tonic-gate	$heading .= "$public_str  $private_str";
763*7c478bd9Sstevel@tonic-gate	$tmp3 = $heading;
764*7c478bd9Sstevel@tonic-gate	$tmp3 =~ s/\S/-/g;
765*7c478bd9Sstevel@tonic-gate
766*7c478bd9Sstevel@tonic-gate	$tmp1 = gettext("Symbol usage statistics (summary by shared object)");
767*7c478bd9Sstevel@tonic-gate	$tmp2 = '*' x length($tmp1);
768*7c478bd9Sstevel@tonic-gate
769*7c478bd9Sstevel@tonic-gate	print $summary_fh "$tmp2\n$tmp1\n$tmp2\n\n";
770*7c478bd9Sstevel@tonic-gate	print $summary_fh "$heading\n";
771*7c478bd9Sstevel@tonic-gate	print $summary_fh "$tmp3\n";
772*7c478bd9Sstevel@tonic-gate
773*7c478bd9Sstevel@tonic-gate	my ($pub, $priv, $str);
774*7c478bd9Sstevel@tonic-gate	foreach $lib (sort(keys(%libs))) {
775*7c478bd9Sstevel@tonic-gate		$pub  = $public->{$lib};
776*7c478bd9Sstevel@tonic-gate		$priv = $private->{$lib};
777*7c478bd9Sstevel@tonic-gate
778*7c478bd9Sstevel@tonic-gate		$pub = 0 if (! defined($pub));
779*7c478bd9Sstevel@tonic-gate		$priv = 0 if (! defined($priv));
780*7c478bd9Sstevel@tonic-gate
781*7c478bd9Sstevel@tonic-gate		$str = '  ';
782*7c478bd9Sstevel@tonic-gate		$str .= sprintf("%-${len1}s", $lib);
783*7c478bd9Sstevel@tonic-gate		$str .= sprintf("%${len2}s", $pub);
784*7c478bd9Sstevel@tonic-gate		$str .= sprintf("%${len3}s", $priv);
785*7c478bd9Sstevel@tonic-gate		print $summary_fh $str, "\n";
786*7c478bd9Sstevel@tonic-gate	}
787*7c478bd9Sstevel@tonic-gate	print $summary_fh "\n";
788*7c478bd9Sstevel@tonic-gate
789*7c478bd9Sstevel@tonic-gate	$tmp1 = gettext("Symbol usage (detailed inventory by shared object)");
790*7c478bd9Sstevel@tonic-gate	$tmp2 = '*' x length($tmp1);
791*7c478bd9Sstevel@tonic-gate
792*7c478bd9Sstevel@tonic-gate	print $summary_fh "$tmp2\n$tmp1\n$tmp2\n\n";
793*7c478bd9Sstevel@tonic-gate
794*7c478bd9Sstevel@tonic-gate	my (@pub, @priv, $lib2, $sym2, $text, $key);
795*7c478bd9Sstevel@tonic-gate	foreach $lib (sort(keys(%libs))) {
796*7c478bd9Sstevel@tonic-gate		@pub  = ();
797*7c478bd9Sstevel@tonic-gate		@priv = ();
798*7c478bd9Sstevel@tonic-gate
799*7c478bd9Sstevel@tonic-gate		foreach $key (keys(%$sym_public)) {
800*7c478bd9Sstevel@tonic-gate			next unless (index($key, $lib) == 0);
801*7c478bd9Sstevel@tonic-gate			($lib2, $sym2) = split(/\|/, $key, 2);
802*7c478bd9Sstevel@tonic-gate			next unless ($lib2 eq $lib);
803*7c478bd9Sstevel@tonic-gate			push(@pub, $sym2);
804*7c478bd9Sstevel@tonic-gate		}
805*7c478bd9Sstevel@tonic-gate		foreach $key (keys(%$sym_private)) {
806*7c478bd9Sstevel@tonic-gate			next unless (index($key, $lib) == 0);
807*7c478bd9Sstevel@tonic-gate			($lib2, $sym2) = split(/\|/, $key, 2);
808*7c478bd9Sstevel@tonic-gate			next unless ($lib2 eq $lib);
809*7c478bd9Sstevel@tonic-gate			push(@priv, $sym2);
810*7c478bd9Sstevel@tonic-gate		}
811*7c478bd9Sstevel@tonic-gate
812*7c478bd9Sstevel@tonic-gate		next if (! @pub && ! @priv);
813*7c478bd9Sstevel@tonic-gate
814*7c478bd9Sstevel@tonic-gate		my $fmt = gettext("Symbols in %s Directly Referenced");
815*7c478bd9Sstevel@tonic-gate		$text = sprintf($fmt, $lib);
816*7c478bd9Sstevel@tonic-gate
817*7c478bd9Sstevel@tonic-gate		if (@pub) {
818*7c478bd9Sstevel@tonic-gate			$lib2 = scalar(@pub);
819*7c478bd9Sstevel@tonic-gate			$text .= sprintf(gettext(
820*7c478bd9Sstevel@tonic-gate			    "  %d public symbols are used:\n"), $lib2);
821*7c478bd9Sstevel@tonic-gate			$text .= list_format('    ', sort(@pub));
822*7c478bd9Sstevel@tonic-gate			$text .= "\n";
823*7c478bd9Sstevel@tonic-gate		}
824*7c478bd9Sstevel@tonic-gate		if (@priv) {
825*7c478bd9Sstevel@tonic-gate			$lib2 = scalar(@priv);
826*7c478bd9Sstevel@tonic-gate			$text .= sprintf(gettext(
827*7c478bd9Sstevel@tonic-gate			    "  %d private symbols are used:\n"), $lib2);
828*7c478bd9Sstevel@tonic-gate			$text .= list_format('    ', sort(@priv));
829*7c478bd9Sstevel@tonic-gate			$text .= "\n";
830*7c478bd9Sstevel@tonic-gate		}
831*7c478bd9Sstevel@tonic-gate
832*7c478bd9Sstevel@tonic-gate		print $summary_fh $text;
833*7c478bd9Sstevel@tonic-gate	}
834*7c478bd9Sstevel@tonic-gate	close($summary_fh);
835*7c478bd9Sstevel@tonic-gate}
836