175ce41a5SAli Bahrami#!/usr/bin/perl -w 275ce41a5SAli Bahrami# 375ce41a5SAli Bahrami# CDDL HEADER START 475ce41a5SAli Bahrami# 575ce41a5SAli Bahrami# The contents of this file are subject to the terms of the 675ce41a5SAli Bahrami# Common Development and Distribution License (the "License"). 775ce41a5SAli Bahrami# You may not use this file except in compliance with the License. 875ce41a5SAli Bahrami# 975ce41a5SAli Bahrami# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1075ce41a5SAli Bahrami# or http://www.opensolaris.org/os/licensing. 1175ce41a5SAli Bahrami# See the License for the specific language governing permissions 1275ce41a5SAli Bahrami# and limitations under the License. 1375ce41a5SAli Bahrami# 1475ce41a5SAli Bahrami# When distributing Covered Code, include this CDDL HEADER in each 1575ce41a5SAli Bahrami# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1675ce41a5SAli Bahrami# If applicable, add the following below this CDDL HEADER, with the 1775ce41a5SAli Bahrami# fields enclosed by brackets "[]" replaced with your own identifying 1875ce41a5SAli Bahrami# information: Portions Copyright [yyyy] [name of copyright owner] 1975ce41a5SAli Bahrami# 2075ce41a5SAli Bahrami# CDDL HEADER END 2175ce41a5SAli Bahrami# 2275ce41a5SAli Bahrami 2375ce41a5SAli Bahrami# 24*5253169eSAli Bahrami# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 2575ce41a5SAli Bahrami# 2675ce41a5SAli Bahrami 2775ce41a5SAli Bahrami# 2875ce41a5SAli Bahrami# Check versioning information. 2975ce41a5SAli Bahrami# 3075ce41a5SAli Bahrami# This script descends a directory hierarchy inspecting ELF shared objects for 3175ce41a5SAli Bahrami# version definitions. The general theme is to verify that common versioning 3275ce41a5SAli Bahrami# rules have been used to build these objects. 3375ce41a5SAli Bahrami# 3475ce41a5SAli Bahrami# As always, a number of components don't follow the rules, or require 3575ce41a5SAli Bahrami# special handling. An exceptions file is used to specify these cases. 3675ce41a5SAli Bahrami# 3775ce41a5SAli Bahrami# By default any file that has conditions that should be reported is first 3875ce41a5SAli Bahrami# listed and then each condition follows. The -o (one-line) option produces a 3975ce41a5SAli Bahrami# more terse output which is better for sorting/diffing with "nightly". 4075ce41a5SAli Bahrami# 4175ce41a5SAli Bahrami# Besides the default operation of checking the files within a directory 4275ce41a5SAli Bahrami# hierarchy, a detailed analysis of each files versions can be created with the 4375ce41a5SAli Bahrami# -d option. The database created is useful for auditing the difference between 4475ce41a5SAli Bahrami# different builds, and for thus monitoring that versioning changes are made in 4575ce41a5SAli Bahrami# a compatible manner. 4675ce41a5SAli Bahrami 4775ce41a5SAli Bahrami 4875ce41a5SAli Bahrami# Define all global variables (required for strict) 4975ce41a5SAli Bahramiuse vars qw($Prog $Intfdir); 5075ce41a5SAli Bahramiuse vars qw(%opt @SaveArgv $ErrFH $ObjCnt); 5175ce41a5SAli Bahrami 5275ce41a5SAli Bahrami 5375ce41a5SAli Bahrami# An exception file is used to specify regular expressions to match 5475ce41a5SAli Bahrami# objects. These directives specify special attributes of the object. 5575ce41a5SAli Bahrami# The regular expressions are read from the file and compiled into the 5675ce41a5SAli Bahrami# regular expression variables. 5775ce41a5SAli Bahrami# 5875ce41a5SAli Bahrami# The name of each regular expression variable is of the form 5975ce41a5SAli Bahrami# 6075ce41a5SAli Bahrami# $EXRE_xxx 6175ce41a5SAli Bahrami# 6275ce41a5SAli Bahrami# where xxx is the name of the exception in lower case. For example, 6375ce41a5SAli Bahrami# the regular expression variable for PLUGINS is $EXRE_plugins. 6475ce41a5SAli Bahrami# 6575ce41a5SAli Bahrami# onbld_elfmod::LoadExceptionsToEXRE() depends on this naming convention 6675ce41a5SAli Bahrami# to initialize the regular expression variables, and to detect invalid 6775ce41a5SAli Bahrami# exception names. 6875ce41a5SAli Bahrami# 6975ce41a5SAli Bahrami# If a given exception is not used in the exception file, its regular 7075ce41a5SAli Bahrami# expression variable will be undefined. Users of these variables must 7175ce41a5SAli Bahrami# test the variable with defined() prior to use: 7275ce41a5SAli Bahrami# 7375ce41a5SAli Bahrami# defined($EXRE_plugins) && ($foo =~ $EXRE_plugins) 7475ce41a5SAli Bahrami# 7575ce41a5SAli Bahrami# ---- 7675ce41a5SAli Bahrami# 7775ce41a5SAli Bahrami# The exceptions are: 7875ce41a5SAli Bahrami# 7975ce41a5SAli Bahrami# NONSTD_VERNAME 8075ce41a5SAli Bahrami# Objects are expected to use standard names for versions. 8175ce41a5SAli Bahrami# This directive is used to relax that requirement. 8275ce41a5SAli Bahrami# 8375ce41a5SAli Bahrami# NOVERDEF 8475ce41a5SAli Bahrami# Objects that are not required to have a versioned name. Note that 8575ce41a5SAli Bahrami# PLUGINS objects are implicitly NOVERDEF, so this directive is 8675ce41a5SAli Bahrami# for use with non-plugin objects. 8775ce41a5SAli Bahrami# 8875ce41a5SAli Bahrami# PLUGINS 8975ce41a5SAli Bahrami# Plugin objects are not required to have a versioned name, and are 9075ce41a5SAli Bahrami# not required to be internally versioned. 9175ce41a5SAli Bahrami# 9275ce41a5SAli Bahramiuse vars qw($EXRE_nonstd_vername $EXRE_noverdef $EXRE_plugin); 9375ce41a5SAli Bahrami 9475ce41a5SAli Bahramiuse strict; 9575ce41a5SAli Bahrami 9675ce41a5SAli Bahramiuse POSIX qw(getenv); 9775ce41a5SAli Bahramiuse Getopt::Std; 9875ce41a5SAli Bahramiuse File::Basename; 9975ce41a5SAli Bahrami 10075ce41a5SAli Bahrami 10175ce41a5SAli Bahrami 10275ce41a5SAli Bahrami 10375ce41a5SAli Bahrami## ProcFile(BasePath, RelPath, Class, Type, Verdef, Alias) 10475ce41a5SAli Bahrami# 10575ce41a5SAli Bahrami# Investigate runtime attributes of a sharable object 10675ce41a5SAli Bahrami# 10775ce41a5SAli Bahrami# entry: 10875ce41a5SAli Bahrami# BasePath - Base path from which relative paths are taken 10975ce41a5SAli Bahrami# RelPath - Path of object taken relative to BasePath 11075ce41a5SAli Bahrami# Class - ELFCLASS of object 11175ce41a5SAli Bahrami# Type - ELF type of object 11275ce41a5SAli Bahrami# Verdef - VERDEF if object defines versions, NOVERDEF otherwise 11375ce41a5SAli Bahrami# Alias - Alias lines corresponding to the object, or an empty ('') 11475ce41a5SAli Bahrami# string if there are no aliases. 11575ce41a5SAli Bahrami# 11675ce41a5SAli Bahramisub ProcFile { 11775ce41a5SAli Bahrami my($BasePath, $RelPath, $Class, $Type, $Verdef, $Alias) = @_; 11875ce41a5SAli Bahrami 11975ce41a5SAli Bahrami my($File, $FullPath, %Vers, $VersCnt, %TopVer); 12075ce41a5SAli Bahrami my($Val, $Ttl, $NotPlugin); 12175ce41a5SAli Bahrami 12275ce41a5SAli Bahrami $FullPath = "$BasePath/$RelPath"; 12375ce41a5SAli Bahrami @_ = split /\//, $RelPath; 12475ce41a5SAli Bahrami $File = $_[$#_]; 12575ce41a5SAli Bahrami 12675ce41a5SAli Bahrami $Ttl = 0; 12775ce41a5SAli Bahrami 128*5253169eSAli Bahrami # If this object is not a symlink, does not follow the runtime 129*5253169eSAli Bahrami # versioned name convention, and it does not reside underneath 130*5253169eSAli Bahrami # a directory identified as containing plugin objects intended 131*5253169eSAli Bahrami # for use with dlopen() only, issue a warning. 132*5253169eSAli Bahrami # 133*5253169eSAli Bahrami # Note that it can only be a symlink if the user specified 134*5253169eSAli Bahrami # a single file on the command line, because the use of 135*5253169eSAli Bahrami # 'find_elf -a' is required for a symlink to be seen. 13675ce41a5SAli Bahrami $NotPlugin = !defined($EXRE_plugin) || ($RelPath !~ $EXRE_plugin); 137*5253169eSAli Bahrami if (($File !~ /\.so\./) && $NotPlugin && (! -l $FullPath)) { 13875ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 13975ce41a5SAli Bahrami "does not have a versioned name"); 14075ce41a5SAli Bahrami } 14175ce41a5SAli Bahrami 14275ce41a5SAli Bahrami # If there are no versions in the file we're done. 14375ce41a5SAli Bahrami if ($Verdef eq 'NOVERDEF') { 14475ce41a5SAli Bahrami # Report the lack of versioning, unless the object is 14575ce41a5SAli Bahrami # a known plugin, or is explicitly exempt. 14675ce41a5SAli Bahrami if ($NotPlugin && 14775ce41a5SAli Bahrami (!defined($EXRE_noverdef) || ($RelPath !~ $EXRE_noverdef))) { 14875ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 14975ce41a5SAli Bahrami "no versions found"); 15075ce41a5SAli Bahrami } 15175ce41a5SAli Bahrami return; 15275ce41a5SAli Bahrami } 15375ce41a5SAli Bahrami 15475ce41a5SAli Bahrami # Get a hash of the top versions in the inheritance chains. 15575ce41a5SAli Bahrami %TopVer = (); 15675ce41a5SAli Bahrami foreach my $Line (split(/\n/, `pvs -don $FullPath 2>&1`)) { 15775ce41a5SAli Bahrami $Line =~ s/^.*-\s*(.*);/$1/; 15875ce41a5SAli Bahrami $TopVer{$Line} = 1; 15975ce41a5SAli Bahrami } 16075ce41a5SAli Bahrami 161*5253169eSAli Bahrami # Determine the name used for the base version. It should match the 162*5253169eSAli Bahrami # soname if the object has one, and the object basename otherwise. 163*5253169eSAli Bahrami # 164*5253169eSAli Bahrami # Note that elfedit writes an error to stderr if the object lacks an 165*5253169eSAli Bahrami # soname, so we direct stderr to /dev/null. 166*5253169eSAli Bahrami my $soname = 167*5253169eSAli Bahrami `elfedit -r -osimple -e 'dyn:value dt_soname' $FullPath 2>/dev/null`; 168*5253169eSAli Bahrami if ($soname eq '') { 169*5253169eSAli Bahrami $soname = $File; 170*5253169eSAli Bahrami } else { 171*5253169eSAli Bahrami chomp $soname; 172*5253169eSAli Bahrami } 173*5253169eSAli Bahrami 17475ce41a5SAli Bahrami # First determine what versions exist that offer interfaces. pvs -dos 17575ce41a5SAli Bahrami # will list these. Note that other versions may exist, ones that 17675ce41a5SAli Bahrami # don't offer interfaces ... we'll get to those next. 17775ce41a5SAli Bahrami %Vers = (); 17875ce41a5SAli Bahrami $VersCnt = 0; 179*5253169eSAli Bahrami my %TopNumberedVers = (); 18075ce41a5SAli Bahrami foreach my $Line (split(/\n/, `pvs -dos $FullPath 2>&1`)) { 18175ce41a5SAli Bahrami my($Ver) = $Line; 18275ce41a5SAli Bahrami 18375ce41a5SAli Bahrami $Ver =~ s/^.*-\t(.*): .*/$1/; # isolate version 18475ce41a5SAli Bahrami 18575ce41a5SAli Bahrami # See if we've already caught this version name. We only look 18675ce41a5SAli Bahrami # at each version once. 18775ce41a5SAli Bahrami next if ($Vers{$Ver}) ; 18875ce41a5SAli Bahrami 18975ce41a5SAli Bahrami # Note that the non-empty version has been seen 19075ce41a5SAli Bahrami $Vers{$Ver} = 1; 19175ce41a5SAli Bahrami $VersCnt++; 19275ce41a5SAli Bahrami 193*5253169eSAli Bahrami # Identify the version type 194*5253169eSAli Bahrami my @Cat = onbld_elfmod_vertype::Category($Ver, $soname); 195*5253169eSAli Bahrami 196*5253169eSAli Bahrami 197*5253169eSAli Bahrami # Numbered public versions have the form 19875ce41a5SAli Bahrami # 199*5253169eSAli Bahrami # <prefix>major.minor[.micro] 200*5253169eSAli Bahrami # 201*5253169eSAli Bahrami # with 2 or three numeric values. We expect these versions to 202*5253169eSAli Bahrami # use inheritance, so there should only be one top version for 203*5253169eSAli Bahrami # each major number. It is possible, though rare, to have more 204*5253169eSAli Bahrami # than one top version if the major numbers differ. 205*5253169eSAli Bahrami # 206*5253169eSAli Bahrami # %TopNumberedVers uses the prefix and major number as the 207*5253169eSAli Bahrami # key. Each key holds a reference to an array which contains 208*5253169eSAli Bahrami # the top versions with the same prefix and major number. 209*5253169eSAli Bahrami if ($Cat[0] eq 'NUMBERED') { 210*5253169eSAli Bahrami push @{$TopNumberedVers{"$Cat[2]$Cat[3]"}}, $Ver 211*5253169eSAli Bahrami if $TopVer{$Ver}; 21275ce41a5SAli Bahrami next; 21375ce41a5SAli Bahrami } 21475ce41a5SAli Bahrami 215*5253169eSAli Bahrami # If it is a non-standard version, and there's not an 216*5253169eSAli Bahrami # exception in place for it, report an error. 217*5253169eSAli Bahrami if ($Cat[0] eq 'UNKNOWN') { 21875ce41a5SAli Bahrami if (!defined($EXRE_nonstd_vername) || 21975ce41a5SAli Bahrami ($RelPath !~ $EXRE_nonstd_vername)) { 22075ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 22175ce41a5SAli Bahrami "non-standard version name: $Ver"); 22275ce41a5SAli Bahrami } 22375ce41a5SAli Bahrami next; 22475ce41a5SAli Bahrami } 22575ce41a5SAli Bahrami 226*5253169eSAli Bahrami # If we are here, it is one of PLAIN, PRIVATE, or SONAME, 227*5253169eSAli Bahrami # all of which we quietly accept. 228*5253169eSAli Bahrami next; 229*5253169eSAli Bahrami } 230*5253169eSAli Bahrami 23175ce41a5SAli Bahrami # If this file has been scoped, but not versioned (i.e., a mapfile was 23275ce41a5SAli Bahrami # used to demote symbols but no version name was applied to the 23375ce41a5SAli Bahrami # global interfaces) then it's another non-standard case. 23475ce41a5SAli Bahrami if ($VersCnt eq 0) { 23575ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 23675ce41a5SAli Bahrami "scoped object contains no versions"); 23775ce41a5SAli Bahrami return; 23875ce41a5SAli Bahrami } 23975ce41a5SAli Bahrami 240*5253169eSAli Bahrami # If this file has multiple inheritance chains starting with the 241*5253169eSAli Bahrami # same prefix and major number, that's wrong. 242*5253169eSAli Bahrami foreach my $Ver (sort keys %TopNumberedVers) { 243*5253169eSAli Bahrami if (scalar(@{$TopNumberedVers{$Ver}}) > 1) { 24475ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 24575ce41a5SAli Bahrami "multiple $Ver inheritance chains (missing " . 24675ce41a5SAli Bahrami "inheritance?): " . 247*5253169eSAli Bahrami join(', ', @{$TopNumberedVers{$Ver}})); 24875ce41a5SAli Bahrami } 24975ce41a5SAli Bahrami } 25075ce41a5SAli Bahrami 25175ce41a5SAli Bahrami 25275ce41a5SAli Bahrami # Produce an interface description for the object. 25375ce41a5SAli Bahrami # For each version, generate a VERSION declaration of the form: 25475ce41a5SAli Bahrami # 25575ce41a5SAli Bahrami # [TOP_]VERSION version direct-count total-count 25675ce41a5SAli Bahrami # symname1 25775ce41a5SAli Bahrami # symname2 25875ce41a5SAli Bahrami # ... 25975ce41a5SAli Bahrami # 260*5253169eSAli Bahrami # We suppress base and private versions from this output. 261*5253169eSAli Bahrami # Everything else goes in, whether it's a version we recognize 262*5253169eSAli Bahrami # or not. If an object only has base or private versions, we do 263*5253169eSAli Bahrami # not produce an interface description for that object. 26475ce41a5SAli Bahrami # 26575ce41a5SAli Bahrami if ($opt{i}) { 26675ce41a5SAli Bahrami my $header_done = 0; 26775ce41a5SAli Bahrami 26875ce41a5SAli Bahrami # The use of 'pvs -v' is to identify the BASE version 26975ce41a5SAli Bahrami foreach my $Line (split(/\n/, `pvs -dv $FullPath 2>&1`)) { 27075ce41a5SAli Bahrami # Skip base version 27175ce41a5SAli Bahrami next if ($Line =~ /\[BASE\]/); 27275ce41a5SAli Bahrami 27375ce41a5SAli Bahrami # Directly inherited versions follow the version name 27475ce41a5SAli Bahrami # in a comma separated list within {} brackets. Capture 27575ce41a5SAli Bahrami # that information, for use with our VERSION line. 27675ce41a5SAli Bahrami my $InheritVers = ($Line =~ /(\{.*\});$/) ? "\t$1" : ''; 27775ce41a5SAli Bahrami 278*5253169eSAli Bahrami # Extract the version name 27975ce41a5SAli Bahrami $Line =~ s/^\s*([^;: ]*).*/$1/; 28075ce41a5SAli Bahrami 281*5253169eSAli Bahrami # Skip version if it is in the SONAME or PRIVATE 282*5253169eSAli Bahrami # categories. 283*5253169eSAli Bahrami # 284*5253169eSAli Bahrami # The above test for BASE should have caught the 285*5253169eSAli Bahrami # SONAME already, but older versions of pvs have a 286*5253169eSAli Bahrami # bug that prevents them from printing [BASE] on 287*5253169eSAli Bahrami # the base version. In order to solidify things even 288*5253169eSAli Bahrami # more, we also exclude versions that end with 289*5253169eSAli Bahrami # a '.so.*' suffix. 290*5253169eSAli Bahrami my @Cat = onbld_elfmod_vertype::Category($Line, $soname); 291*5253169eSAli Bahrami if (($Cat[0] eq 'SONAME') || 292*5253169eSAli Bahrami ($Cat[0] eq 'PRIVATE') || 293*5253169eSAli Bahrami ($Line =~ /\.so\.\d+$/)) { 294*5253169eSAli Bahrami next; 295*5253169eSAli Bahrami } 29675ce41a5SAli Bahrami 29775ce41a5SAli Bahrami # We want to output the symbols in sorted order, so 29875ce41a5SAli Bahrami # we gather them first, and then sort the results. 29975ce41a5SAli Bahrami # An array would suffice, but we have observed objects 30075ce41a5SAli Bahrami # with odd inheritance chains in which the same 30175ce41a5SAli Bahrami # sub-version gets inherited more than once, leading 30275ce41a5SAli Bahrami # to the same symbol showing up more than once. Using 30375ce41a5SAli Bahrami # a hash instead of an array thins out the duplicates. 30475ce41a5SAli Bahrami my %Syms = (); 30575ce41a5SAli Bahrami my $symitem = $opt{I} ? 'NEW' : 'SYMBOL'; 30675ce41a5SAli Bahrami my $version_cnt = 0; 30775ce41a5SAli Bahrami foreach my $Sym 30875ce41a5SAli Bahrami (split(/\n/, `pvs -ds -N $Line $FullPath 2>&1`)) { 30975ce41a5SAli Bahrami if ($Sym =~ /:$/) { 31075ce41a5SAli Bahrami $version_cnt++; 31175ce41a5SAli Bahrami # If this is an inherited sub-version, 31275ce41a5SAli Bahrami # we don't need to continue unless 31375ce41a5SAli Bahrami # generating output in -I mode. 31475ce41a5SAli Bahrami if ($version_cnt >= 2) { 31575ce41a5SAli Bahrami last if !$opt{I}; 31675ce41a5SAli Bahrami $symitem = 'INHERIT'; 31775ce41a5SAli Bahrami } 31875ce41a5SAli Bahrami next; 31975ce41a5SAli Bahrami } 32075ce41a5SAli Bahrami $Sym =~ s/[ \t]*(.*);$/$1/; 32175ce41a5SAli Bahrami $Sym =~ s/ .*$//; # remove any data size 32275ce41a5SAli Bahrami $Syms{$Sym} = $symitem; 32375ce41a5SAli Bahrami } 32475ce41a5SAli Bahrami 32575ce41a5SAli Bahrami if (!$header_done) { 32675ce41a5SAli Bahrami print INTFILE "\n" if !$opt{h} && ($ObjCnt != 0); 32775ce41a5SAli Bahrami $ObjCnt++; 32875ce41a5SAli Bahrami print INTFILE "OBJECT\t$RelPath\n"; 32975ce41a5SAli Bahrami print INTFILE "CLASS\tELFCLASS$Class\n"; 33075ce41a5SAli Bahrami print INTFILE "TYPE\tET_$Type\n"; 33175ce41a5SAli Bahrami print INTFILE $Alias if ($Alias ne ''); 33275ce41a5SAli Bahrami $header_done = 1; 33375ce41a5SAli Bahrami } 33475ce41a5SAli Bahrami 33575ce41a5SAli Bahrami my $item = $TopVer{$Line} ? 'TOP_VERSION' : 'VERSION'; 33675ce41a5SAli Bahrami print INTFILE "$item\t$Line$InheritVers\n"; 33775ce41a5SAli Bahrami 33875ce41a5SAli Bahrami # Output symbols in sorted order 33975ce41a5SAli Bahrami foreach my $Sym (sort keys %Syms) { 34075ce41a5SAli Bahrami print INTFILE "\t$Syms{$Sym}\t$Sym\n"; 34175ce41a5SAli Bahrami } 34275ce41a5SAli Bahrami } 34375ce41a5SAli Bahrami } 34475ce41a5SAli Bahrami} 34575ce41a5SAli Bahrami 34675ce41a5SAli Bahrami## ProcFindElf(file) 34775ce41a5SAli Bahrami# 34875ce41a5SAli Bahrami# Open the specified file, which must be produced by "find_elf -r", 34975ce41a5SAli Bahrami# and process the files it describes. 35075ce41a5SAli Bahramisub ProcFindElf { 35175ce41a5SAli Bahrami my $file = $_[0]; 35275ce41a5SAli Bahrami my $line; 35375ce41a5SAli Bahrami my $LineNum = 0; 35475ce41a5SAli Bahrami my $prefix; 35575ce41a5SAli Bahrami my @ObjList = (); 35675ce41a5SAli Bahrami my %ObjToAlias = (); 35775ce41a5SAli Bahrami 35875ce41a5SAli Bahrami open(FIND_ELF, $file) || die "$Prog: Unable to open $file"; 35975ce41a5SAli Bahrami 36075ce41a5SAli Bahrami # This script requires relative paths, created by the 'find_elf -r' 36175ce41a5SAli Bahrami # option. When this is done, the first non-comment line will always 36275ce41a5SAli Bahrami # be PREFIX. Obtain that line, or issue a fatal error. 36375ce41a5SAli Bahrami while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) { 36475ce41a5SAli Bahrami if ($line =~ /^PREFIX\s+(.*)$/) { 36575ce41a5SAli Bahrami $prefix = $1; 36675ce41a5SAli Bahrami last; 36775ce41a5SAli Bahrami } 36875ce41a5SAli Bahrami 36975ce41a5SAli Bahrami die "$file: PREFIX expected on line $LineNum\n"; 37075ce41a5SAli Bahrami } 37175ce41a5SAli Bahrami 37275ce41a5SAli Bahrami 37375ce41a5SAli Bahrami # Process the remainder of the file. 37475ce41a5SAli Bahrami while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) { 37575ce41a5SAli Bahrami if ($line =~ /^OBJECT\s/i) { 37675ce41a5SAli Bahrami push @ObjList, $line; 37775ce41a5SAli Bahrami next; 37875ce41a5SAli Bahrami } 37975ce41a5SAli Bahrami 38075ce41a5SAli Bahrami if ($line =~ /^ALIAS\s/i) { 38175ce41a5SAli Bahrami my ($item, $obj, $alias) = split(/\s+/, $line, 3); 38275ce41a5SAli Bahrami my $str = "ALIAS\t$alias\n"; 38375ce41a5SAli Bahrami 38475ce41a5SAli Bahrami if (defined($ObjToAlias{$obj})) { 38575ce41a5SAli Bahrami $ObjToAlias{$obj} .= $str; 38675ce41a5SAli Bahrami } else { 38775ce41a5SAli Bahrami $ObjToAlias{$obj} = $str; 38875ce41a5SAli Bahrami } 38975ce41a5SAli Bahrami } 39075ce41a5SAli Bahrami } 39175ce41a5SAli Bahrami 39275ce41a5SAli Bahrami foreach $line (@ObjList) { 39375ce41a5SAli Bahrami my ($item, $class, $type, $verdef, $obj) = 39475ce41a5SAli Bahrami split(/\s+/, $line, 5); 39575ce41a5SAli Bahrami 39675ce41a5SAli Bahrami my $alias = defined($ObjToAlias{$obj}) ? $ObjToAlias{$obj} : ''; 39775ce41a5SAli Bahrami 39875ce41a5SAli Bahrami # We are only interested in sharable objects. We may see 39975ce41a5SAli Bahrami # other file types if processing a list of objects 40075ce41a5SAli Bahrami # supplied via the -f option. 40175ce41a5SAli Bahrami next if ($type ne 'DYN'); 40275ce41a5SAli Bahrami 40375ce41a5SAli Bahrami ProcFile($prefix, $obj, $class, $type, $verdef, $alias); 40475ce41a5SAli Bahrami } 40575ce41a5SAli Bahrami 40675ce41a5SAli Bahrami close FIND_ELF; 40775ce41a5SAli Bahrami} 40875ce41a5SAli Bahrami 40975ce41a5SAli Bahrami 41075ce41a5SAli Bahrami# ----------------------------------------------------------------------------- 41175ce41a5SAli Bahrami 41275ce41a5SAli Bahrami# Establish a program name for any error diagnostics. 41375ce41a5SAli Bahramichomp($Prog = `basename $0`); 41475ce41a5SAli Bahrami 41575ce41a5SAli Bahrami# Check that we have arguments. 41675ce41a5SAli Bahrami@SaveArgv = @ARGV; 417*5253169eSAli Bahramiif ((getopts('c:E:e:f:hIi:ow:', \%opt) == 0) || (!$opt{f} && ($#ARGV == -1))) { 418*5253169eSAli Bahrami print "usage: $Prog [-hIo] [-c vtype_mod] [-E errfile] [-e exfile]\n"; 419*5253169eSAli Bahrami print "\t\t[-f listfile] [-i intffile] [-w outdir] file | dir, ...\n"; 42075ce41a5SAli Bahrami print "\n"; 421*5253169eSAli Bahrami print "\t[-c vtype_mod]\tsupply alternative version category module\n"; 42275ce41a5SAli Bahrami print "\t[-E errfile]\tdirect error output to file\n"; 42375ce41a5SAli Bahrami print "\t[-e exfile]\texceptions file\n"; 42475ce41a5SAli Bahrami print "\t[-f listfile]\tuse file list produced by find_elf -r\n"; 425*5253169eSAli Bahrami print "\t[-h]\t\tdo not produce a CDDL/Copyright header comment\n"; 426*5253169eSAli Bahrami print "\t[-I]\t\tExpand inheritance in -i output (debugging)\n"; 42775ce41a5SAli Bahrami print "\t[-i intffile]\tcreate interface description output file\n"; 42875ce41a5SAli Bahrami print "\t[-o]\t\tproduce one-liner output (prefixed with pathname)\n"; 42975ce41a5SAli Bahrami print "\t[-w outdir]\tinterpret all files relative to given directory\n"; 43075ce41a5SAli Bahrami exit 1; 43175ce41a5SAli Bahrami} 43275ce41a5SAli Bahrami 433*5253169eSAli Bahrami# We depend on the onbld_elfmod and onbld_elfmod_vertype perl modules. 434*5253169eSAli Bahrami# Both modules are maintained in the same directory as this script, 435*5253169eSAli Bahrami# and are installed in ../lib/perl. Use the local one if present, 436*5253169eSAli Bahrami# and the installed one otherwise. 437*5253169eSAli Bahrami# 438*5253169eSAli Bahrami# The caller is allowed to supply an alternative implementation for 439*5253169eSAli Bahrami# onbld_elfmod_vertype via the -c option. In this case, the alternative 440*5253169eSAli Bahrami# implementation is expected to provide the same interface as the standard 441*5253169eSAli Bahrami# copy, and is loaded instead. 442*5253169eSAli Bahrami# 443*5253169eSAli Bahramimy $moddir = my $vermoddir = dirname($0); 444*5253169eSAli Bahrami$moddir = "$moddir/../lib/perl" if ! -f "$moddir/onbld_elfmod.pm"; 445*5253169eSAli Bahramirequire "$moddir/onbld_elfmod.pm"; 446*5253169eSAli Bahramiif ($opt{c}) { 447*5253169eSAli Bahrami require "$opt{c}"; 448*5253169eSAli Bahrami} else { 449*5253169eSAli Bahrami $vermoddir = "$vermoddir/../lib/perl" 450*5253169eSAli Bahrami if ! -f "$vermoddir/onbld_elfmod_vertype.pm"; 451*5253169eSAli Bahrami require "$vermoddir/onbld_elfmod_vertype.pm"; 452*5253169eSAli Bahrami} 453*5253169eSAli Bahrami 45475ce41a5SAli Bahrami# If -w, change working directory to given location 45575ce41a5SAli Bahrami!$opt{w} || chdir($opt{w}) || die "$Prog: can't cd to $opt{w}"; 45675ce41a5SAli Bahrami 45775ce41a5SAli Bahrami 45875ce41a5SAli Bahrami# Error messages go to stdout unless -E is specified. $ErrFH is a 45975ce41a5SAli Bahrami# file handle reference that points at the file handle where error messages 46075ce41a5SAli Bahrami# are sent. 46175ce41a5SAli Bahramiif ($opt{E}) { 46275ce41a5SAli Bahrami open(ERROR, ">$opt{E}") || die "$Prog: open failed: $opt{E}"; 46375ce41a5SAli Bahrami $ErrFH = \*ERROR; 46475ce41a5SAli Bahrami} else { 46575ce41a5SAli Bahrami $ErrFH = \*STDOUT; 46675ce41a5SAli Bahrami} 46775ce41a5SAli Bahrami 46875ce41a5SAli Bahrami# Locate and process the exceptions file 46975ce41a5SAli Bahramionbld_elfmod::LoadExceptionsToEXRE('interface_check'); 47075ce41a5SAli Bahrami 47175ce41a5SAli Bahrami# If creating an interface description output file, prepare it for use 47275ce41a5SAli Bahramiif ($opt{i}) { 47375ce41a5SAli Bahrami open (INTFILE, ">$opt{i}") || 47475ce41a5SAli Bahrami die "$Prog: Unable to create file: $opt{i}"; 47575ce41a5SAli Bahrami 47675ce41a5SAli Bahrami # Generate the output header 47775ce41a5SAli Bahrami onbld_elfmod::Header(\*INTFILE, $0, \@SaveArgv) if !$opt{h};; 47875ce41a5SAli Bahrami} 47975ce41a5SAli Bahrami 48075ce41a5SAli Bahrami# Number of OBJECTs output to INTFILE 48175ce41a5SAli Bahrami$ObjCnt = 0; 48275ce41a5SAli Bahrami 48375ce41a5SAli Bahrami# If we were passed a file previously produced by 'find_elf -r', use it. 48475ce41a5SAli BahramiProcFindElf($opt{f}) if $opt{f}; 48575ce41a5SAli Bahrami 486*5253169eSAli Bahrami# Process each argument: Run find_elf to find the files given by 487*5253169eSAli Bahrami# $Arg. If the argument is a regular file (not a directory) then disable 488*5253169eSAli Bahrami# find_elf's alias checking so that the file is processed whether or not 489*5253169eSAli Bahrami# it is a symlink. 49075ce41a5SAli Bahramiforeach my $Arg (@ARGV) { 491*5253169eSAli Bahrami my $flag_a = (-d $Arg) ? '' : '-a'; 492*5253169eSAli Bahrami ProcFindElf("find_elf -frs $flag_a $Arg|"); 49375ce41a5SAli Bahrami} 49475ce41a5SAli Bahrami 49575ce41a5SAli Bahrami# Close any working output files. 49675ce41a5SAli Bahramiclose INTFILE if $opt{i}; 49775ce41a5SAli Bahramiclose ERROR if $opt{E}; 49875ce41a5SAli Bahrami 49975ce41a5SAli Bahramiexit 0; 500