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