xref: /titanic_44/usr/src/cmd/abi/appcert/scripts/abi_index.pl (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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# ident	"%Z%%M%	%I%	%E% SMI"
25*7c478bd9Sstevel@tonic-gate#
26*7c478bd9Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
27*7c478bd9Sstevel@tonic-gate# Use is subject to license terms.
28*7c478bd9Sstevel@tonic-gate#
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate#
31*7c478bd9Sstevel@tonic-gate# This utility program reads the contents file to extract Solaris ELF
32*7c478bd9Sstevel@tonic-gate# libraries, and then runs pvs(1) on them to find the library versioning
33*7c478bd9Sstevel@tonic-gate# information (if any).  This info is printed to stdout in an index file
34*7c478bd9Sstevel@tonic-gate# format.
35*7c478bd9Sstevel@tonic-gate#
36*7c478bd9Sstevel@tonic-gate
37*7c478bd9Sstevel@tonic-gaterequire 5.005;
38*7c478bd9Sstevel@tonic-gateuse strict;
39*7c478bd9Sstevel@tonic-gateuse locale;
40*7c478bd9Sstevel@tonic-gateuse POSIX qw(locale_h);
41*7c478bd9Sstevel@tonic-gateuse Sun::Solaris::Utils qw(textdomain gettext);
42*7c478bd9Sstevel@tonic-gateuse File::Basename;
43*7c478bd9Sstevel@tonic-gate
44*7c478bd9Sstevel@tonic-gateuse vars qw(
45*7c478bd9Sstevel@tonic-gate	@liblist
46*7c478bd9Sstevel@tonic-gate	%symlink
47*7c478bd9Sstevel@tonic-gate	%inode_hash
48*7c478bd9Sstevel@tonic-gate	%fileoutput
49*7c478bd9Sstevel@tonic-gate	%didlib
50*7c478bd9Sstevel@tonic-gate);
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gatesetlocale(LC_ALL, "");
53*7c478bd9Sstevel@tonic-gatetextdomain(TEXT_DOMAIN);
54*7c478bd9Sstevel@tonic-gate
55*7c478bd9Sstevel@tonic-gate# parameters for what types of libraries to list out:
56*7c478bd9Sstevel@tonic-gatemy $must_be_versioned = 0;
57*7c478bd9Sstevel@tonic-gatemy $must_be_public = 0;
58*7c478bd9Sstevel@tonic-gate
59*7c478bd9Sstevel@tonic-gate# paths to skip outright.
60*7c478bd9Sstevel@tonic-gatemy @skip_list = qw(
61*7c478bd9Sstevel@tonic-gate	/etc
62*7c478bd9Sstevel@tonic-gate	/usr/4lib
63*7c478bd9Sstevel@tonic-gate	/usr/perl5
64*7c478bd9Sstevel@tonic-gate);
65*7c478bd9Sstevel@tonic-gatemy $path_skip = join('|', @skip_list);
66*7c478bd9Sstevel@tonic-gate$path_skip = qr/^($path_skip)/;
67*7c478bd9Sstevel@tonic-gate
68*7c478bd9Sstevel@tonic-gate# find library names:
69*7c478bd9Sstevel@tonic-gate#
70*7c478bd9Sstevel@tonic-gate# We have to use pkgchk -l output (even though it is much slower than
71*7c478bd9Sstevel@tonic-gate# parsing /var/sadm/install/contents ourselves) because the contents
72*7c478bd9Sstevel@tonic-gate# file will go away or change incompatibly at some point.
73*7c478bd9Sstevel@tonic-gate#
74*7c478bd9Sstevel@tonic-gatemy $old = $ENV{'LC_ALL'};
75*7c478bd9Sstevel@tonic-gate$ENV{'LC_ALL'} = 'C';
76*7c478bd9Sstevel@tonic-gatemy $contents_fh = do { local *FH; *FH };
77*7c478bd9Sstevel@tonic-gateopen($contents_fh, "/usr/sbin/pkgchk -l|") || die "$!\n";
78*7c478bd9Sstevel@tonic-gateif (defined($old)) {
79*7c478bd9Sstevel@tonic-gate	$ENV{'LC_ALL'} = $old;
80*7c478bd9Sstevel@tonic-gate} else {
81*7c478bd9Sstevel@tonic-gate	delete($ENV{'LC_ALL'});
82*7c478bd9Sstevel@tonic-gate}
83*7c478bd9Sstevel@tonic-gate
84*7c478bd9Sstevel@tonic-gatemy $pathname = '';
85*7c478bd9Sstevel@tonic-gatemy $type = '';
86*7c478bd9Sstevel@tonic-gatemy $link = '';
87*7c478bd9Sstevel@tonic-gatemy $pkgs = '';
88*7c478bd9Sstevel@tonic-gatemy $status = '';
89*7c478bd9Sstevel@tonic-gatemy $inpkgs = 0;
90*7c478bd9Sstevel@tonic-gatewhile (<$contents_fh>) {
91*7c478bd9Sstevel@tonic-gate	next if (/^Ex/);
92*7c478bd9Sstevel@tonic-gate	chomp;
93*7c478bd9Sstevel@tonic-gate	if (/^Pathname:\s*/i) {
94*7c478bd9Sstevel@tonic-gate		$pathname = $';
95*7c478bd9Sstevel@tonic-gate		$type = '';
96*7c478bd9Sstevel@tonic-gate		$link = '';
97*7c478bd9Sstevel@tonic-gate		$status = '';
98*7c478bd9Sstevel@tonic-gate		$pkgs = '';
99*7c478bd9Sstevel@tonic-gate		$inpkgs = 0;
100*7c478bd9Sstevel@tonic-gate		next;
101*7c478bd9Sstevel@tonic-gate	} elsif (/^Type:\s*/i) {
102*7c478bd9Sstevel@tonic-gate		$type = $';
103*7c478bd9Sstevel@tonic-gate		next;
104*7c478bd9Sstevel@tonic-gate	} elsif (/^Source of link:\s*/i) {
105*7c478bd9Sstevel@tonic-gate		$link = $';
106*7c478bd9Sstevel@tonic-gate		next;
107*7c478bd9Sstevel@tonic-gate	} elsif (/^Referenced by/i) {
108*7c478bd9Sstevel@tonic-gate		$inpkgs = 1;
109*7c478bd9Sstevel@tonic-gate	} elsif (/^Current status:\s*/i) {
110*7c478bd9Sstevel@tonic-gate		$status = $';
111*7c478bd9Sstevel@tonic-gate		$inpkgs = 0;
112*7c478bd9Sstevel@tonic-gate		next;
113*7c478bd9Sstevel@tonic-gate	} elsif (/^\s*$/) {
114*7c478bd9Sstevel@tonic-gate		next unless ($pathname =~ m,\.so,);
115*7c478bd9Sstevel@tonic-gate		next unless ($pathname =~ m,/lib,);
116*7c478bd9Sstevel@tonic-gate		next unless ($pathname =~ m,/lib[^/]*\.so\b,);
117*7c478bd9Sstevel@tonic-gate		next unless ($type =~ /regular file|symbolic link/i);
118*7c478bd9Sstevel@tonic-gate		next unless ($status =~ /^\s*installed\s*$/);
119*7c478bd9Sstevel@tonic-gate		$pathname = trim($pathname);
120*7c478bd9Sstevel@tonic-gate		$link = trim($link);
121*7c478bd9Sstevel@tonic-gate		filter($pathname, $link, $pkgs);
122*7c478bd9Sstevel@tonic-gate	}
123*7c478bd9Sstevel@tonic-gate	if ($inpkgs) {
124*7c478bd9Sstevel@tonic-gate		$pkgs .= $_ . ' ';
125*7c478bd9Sstevel@tonic-gate	}
126*7c478bd9Sstevel@tonic-gate}
127*7c478bd9Sstevel@tonic-gateclose($contents_fh);
128*7c478bd9Sstevel@tonic-gate
129*7c478bd9Sstevel@tonic-gate# run pvs(1) on the libraries found:
130*7c478bd9Sstevel@tonic-gatemy $batch = 30;	# batch size to use (running in batches is faster).
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gatemy @list = ();
133*7c478bd9Sstevel@tonic-gatefor (my $i = 1; $i <= scalar(@liblist); $i++) {
134*7c478bd9Sstevel@tonic-gate	push(@list, $liblist[$i-1]);
135*7c478bd9Sstevel@tonic-gate	if ($i % $batch == 0) {
136*7c478bd9Sstevel@tonic-gate		do_pvs(@list) if (@list);
137*7c478bd9Sstevel@tonic-gate		@list = ();
138*7c478bd9Sstevel@tonic-gate	}
139*7c478bd9Sstevel@tonic-gate}
140*7c478bd9Sstevel@tonic-gatedo_pvs(@list) if (@list);	# finish any remainder.
141*7c478bd9Sstevel@tonic-gate
142*7c478bd9Sstevel@tonic-gateexit 0;
143*7c478bd9Sstevel@tonic-gate
144*7c478bd9Sstevel@tonic-gate#
145*7c478bd9Sstevel@tonic-gate# Take a pkgchk -l entry and decide if it corresponds to a Solaris
146*7c478bd9Sstevel@tonic-gate# library. If so, save it in the list @liblist, and record info in
147*7c478bd9Sstevel@tonic-gate# %symlink & %inode_hash associative arrays as appropriate.
148*7c478bd9Sstevel@tonic-gate#
149*7c478bd9Sstevel@tonic-gatesub filter
150*7c478bd9Sstevel@tonic-gate{
151*7c478bd9Sstevel@tonic-gate	my ($path, $link, $pkgs) = @_;
152*7c478bd9Sstevel@tonic-gate
153*7c478bd9Sstevel@tonic-gate
154*7c478bd9Sstevel@tonic-gate	# consider only SUNW packages:
155*7c478bd9Sstevel@tonic-gate	return unless ($pkgs =~ /\bSUNW\S+/);
156*7c478bd9Sstevel@tonic-gate
157*7c478bd9Sstevel@tonic-gate	my $basename;
158*7c478bd9Sstevel@tonic-gate
159*7c478bd9Sstevel@tonic-gate	$basename = basename($path);
160*7c478bd9Sstevel@tonic-gate
161*7c478bd9Sstevel@tonic-gate	if ($link ne '') {
162*7c478bd9Sstevel@tonic-gate		# include developer build-time symlinks:
163*7c478bd9Sstevel@tonic-gate		return unless ($basename =~ /^lib.*\.so[\.\d]*$/);
164*7c478bd9Sstevel@tonic-gate	} else {
165*7c478bd9Sstevel@tonic-gate		return unless ($basename =~ /^lib.*\.so\.[\.\d]+$/);
166*7c478bd9Sstevel@tonic-gate	}
167*7c478bd9Sstevel@tonic-gate	return if ($path =~ /$path_skip/);
168*7c478bd9Sstevel@tonic-gate
169*7c478bd9Sstevel@tonic-gate	return unless (-f $path);
170*7c478bd9Sstevel@tonic-gate
171*7c478bd9Sstevel@tonic-gate	# inode is used to identify what file a symlink point to:
172*7c478bd9Sstevel@tonic-gate	my $inode;
173*7c478bd9Sstevel@tonic-gate	$inode = (stat($path))[1];
174*7c478bd9Sstevel@tonic-gate	return unless (defined($inode));
175*7c478bd9Sstevel@tonic-gate
176*7c478bd9Sstevel@tonic-gate	if ($link ne '') {
177*7c478bd9Sstevel@tonic-gate		# record info about symlinks:
178*7c478bd9Sstevel@tonic-gate		if (exists($symlink{$inode})) {
179*7c478bd9Sstevel@tonic-gate			$symlink{$inode} .= ":" . $path;
180*7c478bd9Sstevel@tonic-gate		} else {
181*7c478bd9Sstevel@tonic-gate			$symlink{$inode} = ":" . $path;
182*7c478bd9Sstevel@tonic-gate		}
183*7c478bd9Sstevel@tonic-gate	} else {
184*7c478bd9Sstevel@tonic-gate		# ordinary file case:
185*7c478bd9Sstevel@tonic-gate		$inode_hash{$path} = $inode;
186*7c478bd9Sstevel@tonic-gate		push(@liblist, $path);
187*7c478bd9Sstevel@tonic-gate	}
188*7c478bd9Sstevel@tonic-gate}
189*7c478bd9Sstevel@tonic-gate
190*7c478bd9Sstevel@tonic-gate#
191*7c478bd9Sstevel@tonic-gate# Run pvs(1) on a list of libraries. More than one is done at a time to
192*7c478bd9Sstevel@tonic-gate# speed things up.
193*7c478bd9Sstevel@tonic-gate#
194*7c478bd9Sstevel@tonic-gate# Extracts the version information and passes it to the output() routine
195*7c478bd9Sstevel@tonic-gate# for final processing.
196*7c478bd9Sstevel@tonic-gate#
197*7c478bd9Sstevel@tonic-gatesub do_pvs
198*7c478bd9Sstevel@tonic-gate{
199*7c478bd9Sstevel@tonic-gate	my (@list) = @_;
200*7c478bd9Sstevel@tonic-gate
201*7c478bd9Sstevel@tonic-gate	my (%list, $paths, $path, $cnt);
202*7c478bd9Sstevel@tonic-gate
203*7c478bd9Sstevel@tonic-gate	#
204*7c478bd9Sstevel@tonic-gate	# record info about the library paths and construct the list of
205*7c478bd9Sstevel@tonic-gate	# files for the pvs command line.
206*7c478bd9Sstevel@tonic-gate	#
207*7c478bd9Sstevel@tonic-gate	$cnt = 0;
208*7c478bd9Sstevel@tonic-gate	$paths = '';
209*7c478bd9Sstevel@tonic-gate	foreach $path (@list) {
210*7c478bd9Sstevel@tonic-gate		$list{$path} = 1;
211*7c478bd9Sstevel@tonic-gate		$paths .= ' ' if ($paths ne '');
212*7c478bd9Sstevel@tonic-gate		#
213*7c478bd9Sstevel@tonic-gate		# $path should never have single quote in it in
214*7c478bd9Sstevel@tonic-gate		# all normal usage. Make sure this is so:
215*7c478bd9Sstevel@tonic-gate		#
216*7c478bd9Sstevel@tonic-gate		next if ($path =~ /'/);
217*7c478bd9Sstevel@tonic-gate		#
218*7c478bd9Sstevel@tonic-gate		# quote the filename in case it has meta-characters
219*7c478bd9Sstevel@tonic-gate		# (which should never happen in all normal usage)
220*7c478bd9Sstevel@tonic-gate		#
221*7c478bd9Sstevel@tonic-gate		$paths .= "'$path'";
222*7c478bd9Sstevel@tonic-gate		$cnt++;
223*7c478bd9Sstevel@tonic-gate	}
224*7c478bd9Sstevel@tonic-gate
225*7c478bd9Sstevel@tonic-gate	return if ($cnt == 0);
226*7c478bd9Sstevel@tonic-gate
227*7c478bd9Sstevel@tonic-gate	# set locale to C for running command, since we interpret the output:
228*7c478bd9Sstevel@tonic-gate	my $old = $ENV{'LC_ALL'};
229*7c478bd9Sstevel@tonic-gate	$ENV{'LC_ALL'} = 'C';
230*7c478bd9Sstevel@tonic-gate
231*7c478bd9Sstevel@tonic-gate	# get the file(1) output for each item:
232*7c478bd9Sstevel@tonic-gate	my $file_fh = do { local *FH; *FH };
233*7c478bd9Sstevel@tonic-gate	open($file_fh, "/usr/bin/file $paths 2>&1 |") || die "$!\n";
234*7c478bd9Sstevel@tonic-gate	my ($file, $out);
235*7c478bd9Sstevel@tonic-gate	while (<$file_fh>) {
236*7c478bd9Sstevel@tonic-gate		($file, $out) = split(/:/, $_, 2);
237*7c478bd9Sstevel@tonic-gate		if ($list{$file} && $out =~ /\bELF\b/) {
238*7c478bd9Sstevel@tonic-gate			$fileoutput{$file} = $out;
239*7c478bd9Sstevel@tonic-gate		}
240*7c478bd9Sstevel@tonic-gate	}
241*7c478bd9Sstevel@tonic-gate	close($file_fh);
242*7c478bd9Sstevel@tonic-gate
243*7c478bd9Sstevel@tonic-gate	#
244*7c478bd9Sstevel@tonic-gate	# in the case of only 1 item, we place it on the command line
245*7c478bd9Sstevel@tonic-gate	# twice to induce pvs(1) to indicate which file it is reporting
246*7c478bd9Sstevel@tonic-gate	# on.
247*7c478bd9Sstevel@tonic-gate	#
248*7c478bd9Sstevel@tonic-gate	if ($cnt == 1) {
249*7c478bd9Sstevel@tonic-gate		$paths .= " $paths";
250*7c478bd9Sstevel@tonic-gate	}
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate	#
253*7c478bd9Sstevel@tonic-gate	# $paths are entries from /var/sadm/install/contents and
254*7c478bd9Sstevel@tonic-gate	# so should not contain spaces or meta characters:
255*7c478bd9Sstevel@tonic-gate	#
256*7c478bd9Sstevel@tonic-gate	my $pvs_fh = do { local *FH; *FH };
257*7c478bd9Sstevel@tonic-gate	open($pvs_fh, "/usr/bin/pvs -dn $paths 2>&1 |") || die "$!\n";
258*7c478bd9Sstevel@tonic-gate
259*7c478bd9Sstevel@tonic-gate	# reset LC_ALL, if there was any:
260*7c478bd9Sstevel@tonic-gate	if (defined($old)) {
261*7c478bd9Sstevel@tonic-gate		$ENV{'LC_ALL'} = $old;
262*7c478bd9Sstevel@tonic-gate	} else {
263*7c478bd9Sstevel@tonic-gate		delete($ENV{'LC_ALL'});
264*7c478bd9Sstevel@tonic-gate	}
265*7c478bd9Sstevel@tonic-gate
266*7c478bd9Sstevel@tonic-gate	my ($pub, $pri, $obs, $evo, $vers, $new_path);
267*7c478bd9Sstevel@tonic-gate
268*7c478bd9Sstevel@tonic-gate	undef($path);
269*7c478bd9Sstevel@tonic-gate
270*7c478bd9Sstevel@tonic-gate	# initialize strings used below for appending info to:
271*7c478bd9Sstevel@tonic-gate	$pub = '';
272*7c478bd9Sstevel@tonic-gate	$pri = '';
273*7c478bd9Sstevel@tonic-gate	$obs = '';
274*7c478bd9Sstevel@tonic-gate	$evo = '';
275*7c478bd9Sstevel@tonic-gate
276*7c478bd9Sstevel@tonic-gate	while (<$pvs_fh>) {
277*7c478bd9Sstevel@tonic-gate		$_ =~ s/\s*$//;
278*7c478bd9Sstevel@tonic-gate		if (m,^([^:]+):$,) {
279*7c478bd9Sstevel@tonic-gate		    # a new pvs file header, e.g. "/usr/lib/libc.so.1:"
280*7c478bd9Sstevel@tonic-gate		    if ($list{$1}) {
281*7c478bd9Sstevel@tonic-gate			$new_path = $1;
282*7c478bd9Sstevel@tonic-gate
283*7c478bd9Sstevel@tonic-gate			# output the previous one and reset accumulators:
284*7c478bd9Sstevel@tonic-gate			if (defined($path)) {
285*7c478bd9Sstevel@tonic-gate				output($path, $pub, $pri, $obs, $evo);
286*7c478bd9Sstevel@tonic-gate
287*7c478bd9Sstevel@tonic-gate				$pub = '';
288*7c478bd9Sstevel@tonic-gate				$pri = '';
289*7c478bd9Sstevel@tonic-gate				$obs = '';
290*7c478bd9Sstevel@tonic-gate				$evo = '';
291*7c478bd9Sstevel@tonic-gate			}
292*7c478bd9Sstevel@tonic-gate			$path = $new_path;
293*7c478bd9Sstevel@tonic-gate			next;	# done with pvs header case
294*7c478bd9Sstevel@tonic-gate		    }
295*7c478bd9Sstevel@tonic-gate		}
296*7c478bd9Sstevel@tonic-gate
297*7c478bd9Sstevel@tonic-gate		# extract SUNW version head end:
298*7c478bd9Sstevel@tonic-gate
299*7c478bd9Sstevel@tonic-gate		$vers = trim($_);
300*7c478bd9Sstevel@tonic-gate		$vers =~ s/;//g;
301*7c478bd9Sstevel@tonic-gate
302*7c478bd9Sstevel@tonic-gate		# handle the various non-standard cases in Solaris libraries:
303*7c478bd9Sstevel@tonic-gate		if ($vers =~ /^(SUNW.*private|SUNW_XIL_GPI)/i) {
304*7c478bd9Sstevel@tonic-gate			$pri .= $vers . ":";
305*7c478bd9Sstevel@tonic-gate		} elsif ($vers =~ /^(SUNW_\d|SYSVABI|SISCD)/) {
306*7c478bd9Sstevel@tonic-gate			$pub .= $vers . ":";
307*7c478bd9Sstevel@tonic-gate		} elsif ($vers =~ /^(SUNW\.\d|SUNW_XIL)/) {
308*7c478bd9Sstevel@tonic-gate			$pub .= $vers . ":";
309*7c478bd9Sstevel@tonic-gate		} elsif ($vers =~ /^SUNWobsolete/) {
310*7c478bd9Sstevel@tonic-gate			$obs .= $vers . ":";
311*7c478bd9Sstevel@tonic-gate		} elsif ($vers =~ /^SUNWevolving/) {
312*7c478bd9Sstevel@tonic-gate			$evo .= $vers . ":";
313*7c478bd9Sstevel@tonic-gate		} else {
314*7c478bd9Sstevel@tonic-gate			next;
315*7c478bd9Sstevel@tonic-gate		}
316*7c478bd9Sstevel@tonic-gate	}
317*7c478bd9Sstevel@tonic-gate	close($pvs_fh);
318*7c478bd9Sstevel@tonic-gate
319*7c478bd9Sstevel@tonic-gate	# output the last one (if any):
320*7c478bd9Sstevel@tonic-gate	if (defined($path)) {
321*7c478bd9Sstevel@tonic-gate		output($path, $pub, $pri, $obs, $evo);
322*7c478bd9Sstevel@tonic-gate	}
323*7c478bd9Sstevel@tonic-gate}
324*7c478bd9Sstevel@tonic-gate
325*7c478bd9Sstevel@tonic-gate#
326*7c478bd9Sstevel@tonic-gate# Take the raw library versioning information and process it into index
327*7c478bd9Sstevel@tonic-gate# file format and then print it out.
328*7c478bd9Sstevel@tonic-gate#
329*7c478bd9Sstevel@tonic-gatesub output
330*7c478bd9Sstevel@tonic-gate{
331*7c478bd9Sstevel@tonic-gate	my ($path, $pub, $pri, $obs, $evo) = @_;
332*7c478bd9Sstevel@tonic-gate
333*7c478bd9Sstevel@tonic-gate	return if ($didlib{$path});	# skip repeating a library
334*7c478bd9Sstevel@tonic-gate
335*7c478bd9Sstevel@tonic-gate	# trim off any trailing separators:
336*7c478bd9Sstevel@tonic-gate	$pub =~ s/:$//;
337*7c478bd9Sstevel@tonic-gate	$pri =~ s/:$//;
338*7c478bd9Sstevel@tonic-gate	$obs =~ s/:$//;
339*7c478bd9Sstevel@tonic-gate	$evo =~ s/:$//;
340*7c478bd9Sstevel@tonic-gate
341*7c478bd9Sstevel@tonic-gate	# work out the type of library:
342*7c478bd9Sstevel@tonic-gate	my $type;
343*7c478bd9Sstevel@tonic-gate	my $defn;
344*7c478bd9Sstevel@tonic-gate	my $n;
345*7c478bd9Sstevel@tonic-gate	if ($pri && ! $pub && ! $obs && ! $evo) {
346*7c478bd9Sstevel@tonic-gate		$type = 'INTERNAL';
347*7c478bd9Sstevel@tonic-gate		$defn = 'NO_PUBLIC_SYMS';
348*7c478bd9Sstevel@tonic-gate	} elsif ($obs) {
349*7c478bd9Sstevel@tonic-gate		$type = 'OBSOLETE';
350*7c478bd9Sstevel@tonic-gate		$defn = $obs;
351*7c478bd9Sstevel@tonic-gate	} elsif ($pub) {
352*7c478bd9Sstevel@tonic-gate		$type = 'PUBLIC';
353*7c478bd9Sstevel@tonic-gate		$defn = $pub;
354*7c478bd9Sstevel@tonic-gate		if ($defn =~ /:/) {
355*7c478bd9Sstevel@tonic-gate			$defn =~ s/:/,/g;
356*7c478bd9Sstevel@tonic-gate			$defn = "PUBLIC=$defn";
357*7c478bd9Sstevel@tonic-gate		}
358*7c478bd9Sstevel@tonic-gate	} elsif ($evo) {
359*7c478bd9Sstevel@tonic-gate		$type = 'EVOLVING';
360*7c478bd9Sstevel@tonic-gate		$defn = $evo;
361*7c478bd9Sstevel@tonic-gate	} elsif (! $pri && ! $pub && ! $obs && ! $evo) {
362*7c478bd9Sstevel@tonic-gate		$type = 'UNVERSIONED';
363*7c478bd9Sstevel@tonic-gate		$defn = '-';
364*7c478bd9Sstevel@tonic-gate	} else {
365*7c478bd9Sstevel@tonic-gate		return;
366*7c478bd9Sstevel@tonic-gate	}
367*7c478bd9Sstevel@tonic-gate
368*7c478bd9Sstevel@tonic-gate	# return if instructed to skip either of these cases:
369*7c478bd9Sstevel@tonic-gate	if ($must_be_versioned && $type eq 'UNVERSIONED') {
370*7c478bd9Sstevel@tonic-gate		return;
371*7c478bd9Sstevel@tonic-gate	}
372*7c478bd9Sstevel@tonic-gate	if ($must_be_public && $type eq 'INTERNAL') {
373*7c478bd9Sstevel@tonic-gate		return;
374*7c478bd9Sstevel@tonic-gate	}
375*7c478bd9Sstevel@tonic-gate
376*7c478bd9Sstevel@tonic-gate
377*7c478bd9Sstevel@tonic-gate	# prepare the output line, including any symlink information:
378*7c478bd9Sstevel@tonic-gate	my $inode = $inode_hash{$path};
379*7c478bd9Sstevel@tonic-gate	my $links;
380*7c478bd9Sstevel@tonic-gate	if ($inode && exists($symlink{$inode})) {
381*7c478bd9Sstevel@tonic-gate		$links = "${path}$symlink{$inode}";
382*7c478bd9Sstevel@tonic-gate	} else {
383*7c478bd9Sstevel@tonic-gate		$links = "$path";
384*7c478bd9Sstevel@tonic-gate	}
385*7c478bd9Sstevel@tonic-gate
386*7c478bd9Sstevel@tonic-gate	# count the total number of references:
387*7c478bd9Sstevel@tonic-gate	my (@n) = split(/:/, $links);
388*7c478bd9Sstevel@tonic-gate	$n = scalar(@n);
389*7c478bd9Sstevel@tonic-gate
390*7c478bd9Sstevel@tonic-gate	# determine the abi to which the library file belongs:
391*7c478bd9Sstevel@tonic-gate	my ($fout, $abi);
392*7c478bd9Sstevel@tonic-gate	$abi = 'unknown';
393*7c478bd9Sstevel@tonic-gate	$fout = $fileoutput{$path};
394*7c478bd9Sstevel@tonic-gate	if ($fout =~ /\bSPARCV9\b/) {
395*7c478bd9Sstevel@tonic-gate		$abi = 'sparcv9';
396*7c478bd9Sstevel@tonic-gate	} elsif ($fout =~ /\bSPARC/) {
397*7c478bd9Sstevel@tonic-gate		$abi = 'sparc';
398*7c478bd9Sstevel@tonic-gate	} elsif ($fout =~ /\bAMD64\b/ || $fout =~ /\bELF\s+64-bit\s+LSB\b/) {
399*7c478bd9Sstevel@tonic-gate		$abi = 'amd64';
400*7c478bd9Sstevel@tonic-gate	} elsif ($fout =~ /\b80386\b/) {
401*7c478bd9Sstevel@tonic-gate		$abi = 'i386';
402*7c478bd9Sstevel@tonic-gate	}
403*7c478bd9Sstevel@tonic-gate	print STDOUT "$abi|$path|$defn|$n|$links\n";
404*7c478bd9Sstevel@tonic-gate
405*7c478bd9Sstevel@tonic-gate	# record that we did this library so we do not process it a second time.
406*7c478bd9Sstevel@tonic-gate	$didlib{$path} = 1;
407*7c478bd9Sstevel@tonic-gate}
408*7c478bd9Sstevel@tonic-gate
409*7c478bd9Sstevel@tonic-gate#
410*7c478bd9Sstevel@tonic-gate# Remove leading and trailing spaces.
411*7c478bd9Sstevel@tonic-gate#
412*7c478bd9Sstevel@tonic-gatesub trim
413*7c478bd9Sstevel@tonic-gate{
414*7c478bd9Sstevel@tonic-gate	my ($x) = @_;
415*7c478bd9Sstevel@tonic-gate	$x =~ s/^\s*//;
416*7c478bd9Sstevel@tonic-gate	$x =~ s/\s*$//;
417*7c478bd9Sstevel@tonic-gate
418*7c478bd9Sstevel@tonic-gate	return $x;
419*7c478bd9Sstevel@tonic-gate}
420