1*75ce41a5SAli Bahrami#!/usr/bin/perl -w 2*75ce41a5SAli Bahrami# 3*75ce41a5SAli Bahrami# CDDL HEADER START 4*75ce41a5SAli Bahrami# 5*75ce41a5SAli Bahrami# The contents of this file are subject to the terms of the 6*75ce41a5SAli Bahrami# Common Development and Distribution License (the "License"). 7*75ce41a5SAli Bahrami# You may not use this file except in compliance with the License. 8*75ce41a5SAli Bahrami# 9*75ce41a5SAli Bahrami# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*75ce41a5SAli Bahrami# or http://www.opensolaris.org/os/licensing. 11*75ce41a5SAli Bahrami# See the License for the specific language governing permissions 12*75ce41a5SAli Bahrami# and limitations under the License. 13*75ce41a5SAli Bahrami# 14*75ce41a5SAli Bahrami# When distributing Covered Code, include this CDDL HEADER in each 15*75ce41a5SAli Bahrami# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*75ce41a5SAli Bahrami# If applicable, add the following below this CDDL HEADER, with the 17*75ce41a5SAli Bahrami# fields enclosed by brackets "[]" replaced with your own identifying 18*75ce41a5SAli Bahrami# information: Portions Copyright [yyyy] [name of copyright owner] 19*75ce41a5SAli Bahrami# 20*75ce41a5SAli Bahrami# CDDL HEADER END 21*75ce41a5SAli Bahrami# 22*75ce41a5SAli Bahrami 23*75ce41a5SAli Bahrami# 24*75ce41a5SAli Bahrami# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25*75ce41a5SAli Bahrami# Use is subject to license terms. 26*75ce41a5SAli Bahrami# 27*75ce41a5SAli Bahrami 28*75ce41a5SAli Bahrami# 29*75ce41a5SAli Bahrami# Check versioning information. 30*75ce41a5SAli Bahrami# 31*75ce41a5SAli Bahrami# This script descends a directory hierarchy inspecting ELF shared objects for 32*75ce41a5SAli Bahrami# version definitions. The general theme is to verify that common versioning 33*75ce41a5SAli Bahrami# rules have been used to build these objects. 34*75ce41a5SAli Bahrami# 35*75ce41a5SAli Bahrami# As always, a number of components don't follow the rules, or require 36*75ce41a5SAli Bahrami# special handling. An exceptions file is used to specify these cases. 37*75ce41a5SAli Bahrami# 38*75ce41a5SAli Bahrami# By default any file that has conditions that should be reported is first 39*75ce41a5SAli Bahrami# listed and then each condition follows. The -o (one-line) option produces a 40*75ce41a5SAli Bahrami# more terse output which is better for sorting/diffing with "nightly". 41*75ce41a5SAli Bahrami# 42*75ce41a5SAli Bahrami# Besides the default operation of checking the files within a directory 43*75ce41a5SAli Bahrami# hierarchy, a detailed analysis of each files versions can be created with the 44*75ce41a5SAli Bahrami# -d option. The database created is useful for auditing the difference between 45*75ce41a5SAli Bahrami# different builds, and for thus monitoring that versioning changes are made in 46*75ce41a5SAli Bahrami# a compatible manner. 47*75ce41a5SAli Bahrami 48*75ce41a5SAli Bahrami 49*75ce41a5SAli Bahrami# Define all global variables (required for strict) 50*75ce41a5SAli Bahramiuse vars qw($Prog $Intfdir); 51*75ce41a5SAli Bahramiuse vars qw(%opt @SaveArgv $ErrFH $ObjCnt); 52*75ce41a5SAli Bahrami 53*75ce41a5SAli Bahrami 54*75ce41a5SAli Bahrami# An exception file is used to specify regular expressions to match 55*75ce41a5SAli Bahrami# objects. These directives specify special attributes of the object. 56*75ce41a5SAli Bahrami# The regular expressions are read from the file and compiled into the 57*75ce41a5SAli Bahrami# regular expression variables. 58*75ce41a5SAli Bahrami# 59*75ce41a5SAli Bahrami# The name of each regular expression variable is of the form 60*75ce41a5SAli Bahrami# 61*75ce41a5SAli Bahrami# $EXRE_xxx 62*75ce41a5SAli Bahrami# 63*75ce41a5SAli Bahrami# where xxx is the name of the exception in lower case. For example, 64*75ce41a5SAli Bahrami# the regular expression variable for PLUGINS is $EXRE_plugins. 65*75ce41a5SAli Bahrami# 66*75ce41a5SAli Bahrami# onbld_elfmod::LoadExceptionsToEXRE() depends on this naming convention 67*75ce41a5SAli Bahrami# to initialize the regular expression variables, and to detect invalid 68*75ce41a5SAli Bahrami# exception names. 69*75ce41a5SAli Bahrami# 70*75ce41a5SAli Bahrami# If a given exception is not used in the exception file, its regular 71*75ce41a5SAli Bahrami# expression variable will be undefined. Users of these variables must 72*75ce41a5SAli Bahrami# test the variable with defined() prior to use: 73*75ce41a5SAli Bahrami# 74*75ce41a5SAli Bahrami# defined($EXRE_plugins) && ($foo =~ $EXRE_plugins) 75*75ce41a5SAli Bahrami# 76*75ce41a5SAli Bahrami# ---- 77*75ce41a5SAli Bahrami# 78*75ce41a5SAli Bahrami# The exceptions are: 79*75ce41a5SAli Bahrami# 80*75ce41a5SAli Bahrami# NONSTD_VERNAME 81*75ce41a5SAli Bahrami# Objects are expected to use standard names for versions. 82*75ce41a5SAli Bahrami# This directive is used to relax that requirement. 83*75ce41a5SAli Bahrami# 84*75ce41a5SAli Bahrami# NOVERDEF 85*75ce41a5SAli Bahrami# Objects that are not required to have a versioned name. Note that 86*75ce41a5SAli Bahrami# PLUGINS objects are implicitly NOVERDEF, so this directive is 87*75ce41a5SAli Bahrami# for use with non-plugin objects. 88*75ce41a5SAli Bahrami# 89*75ce41a5SAli Bahrami# PLUGINS 90*75ce41a5SAli Bahrami# Plugin objects are not required to have a versioned name, and are 91*75ce41a5SAli Bahrami# not required to be internally versioned. 92*75ce41a5SAli Bahrami# 93*75ce41a5SAli Bahramiuse vars qw($EXRE_nonstd_vername $EXRE_noverdef $EXRE_plugin); 94*75ce41a5SAli Bahrami 95*75ce41a5SAli Bahramiuse strict; 96*75ce41a5SAli Bahrami 97*75ce41a5SAli Bahramiuse POSIX qw(getenv); 98*75ce41a5SAli Bahramiuse Getopt::Std; 99*75ce41a5SAli Bahramiuse File::Basename; 100*75ce41a5SAli Bahrami 101*75ce41a5SAli Bahrami 102*75ce41a5SAli Bahrami 103*75ce41a5SAli Bahrami 104*75ce41a5SAli Bahrami## ProcFile(BasePath, RelPath, Class, Type, Verdef, Alias) 105*75ce41a5SAli Bahrami# 106*75ce41a5SAli Bahrami# Investigate runtime attributes of a sharable object 107*75ce41a5SAli Bahrami# 108*75ce41a5SAli Bahrami# entry: 109*75ce41a5SAli Bahrami# BasePath - Base path from which relative paths are taken 110*75ce41a5SAli Bahrami# RelPath - Path of object taken relative to BasePath 111*75ce41a5SAli Bahrami# Class - ELFCLASS of object 112*75ce41a5SAli Bahrami# Type - ELF type of object 113*75ce41a5SAli Bahrami# Verdef - VERDEF if object defines versions, NOVERDEF otherwise 114*75ce41a5SAli Bahrami# Alias - Alias lines corresponding to the object, or an empty ('') 115*75ce41a5SAli Bahrami# string if there are no aliases. 116*75ce41a5SAli Bahrami# 117*75ce41a5SAli Bahramisub ProcFile { 118*75ce41a5SAli Bahrami my($BasePath, $RelPath, $Class, $Type, $Verdef, $Alias) = @_; 119*75ce41a5SAli Bahrami 120*75ce41a5SAli Bahrami my($File, $FullPath, %Vers, $VersCnt, %TopVer); 121*75ce41a5SAli Bahrami my($Val, $Ttl, $NotPlugin); 122*75ce41a5SAli Bahrami 123*75ce41a5SAli Bahrami $FullPath = "$BasePath/$RelPath"; 124*75ce41a5SAli Bahrami @_ = split /\//, $RelPath; 125*75ce41a5SAli Bahrami $File = $_[$#_]; 126*75ce41a5SAli Bahrami 127*75ce41a5SAli Bahrami $Ttl = 0; 128*75ce41a5SAli Bahrami 129*75ce41a5SAli Bahrami # If this object does not follow the runtime versioned name convention, 130*75ce41a5SAli Bahrami # and it does not reside underneath a directory identified as 131*75ce41a5SAli Bahrami # containing plugin objects intended for use with dlopen() only, 132*75ce41a5SAli Bahrami # issue a warning. 133*75ce41a5SAli Bahrami $NotPlugin = !defined($EXRE_plugin) || ($RelPath !~ $EXRE_plugin); 134*75ce41a5SAli Bahrami if (($File !~ /\.so\./) && $NotPlugin) { 135*75ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 136*75ce41a5SAli Bahrami "does not have a versioned name"); 137*75ce41a5SAli Bahrami } 138*75ce41a5SAli Bahrami 139*75ce41a5SAli Bahrami # If there are no versions in the file we're done. 140*75ce41a5SAli Bahrami if ($Verdef eq 'NOVERDEF') { 141*75ce41a5SAli Bahrami # Report the lack of versioning, unless the object is 142*75ce41a5SAli Bahrami # a known plugin, or is explicitly exempt. 143*75ce41a5SAli Bahrami if ($NotPlugin && 144*75ce41a5SAli Bahrami (!defined($EXRE_noverdef) || ($RelPath !~ $EXRE_noverdef))) { 145*75ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 146*75ce41a5SAli Bahrami "no versions found"); 147*75ce41a5SAli Bahrami } 148*75ce41a5SAli Bahrami return; 149*75ce41a5SAli Bahrami } 150*75ce41a5SAli Bahrami 151*75ce41a5SAli Bahrami # Get a hash of the top versions in the inheritance chains. 152*75ce41a5SAli Bahrami %TopVer = (); 153*75ce41a5SAli Bahrami foreach my $Line (split(/\n/, `pvs -don $FullPath 2>&1`)) { 154*75ce41a5SAli Bahrami $Line =~ s/^.*-\s*(.*);/$1/; 155*75ce41a5SAli Bahrami $TopVer{$Line} = 1; 156*75ce41a5SAli Bahrami } 157*75ce41a5SAli Bahrami 158*75ce41a5SAli Bahrami # First determine what versions exist that offer interfaces. pvs -dos 159*75ce41a5SAli Bahrami # will list these. Note that other versions may exist, ones that 160*75ce41a5SAli Bahrami # don't offer interfaces ... we'll get to those next. 161*75ce41a5SAli Bahrami %Vers = (); 162*75ce41a5SAli Bahrami $VersCnt = 0; 163*75ce41a5SAli Bahrami my %TopSUNWVers = (); 164*75ce41a5SAli Bahrami foreach my $Line (split(/\n/, `pvs -dos $FullPath 2>&1`)) { 165*75ce41a5SAli Bahrami my($Ver) = $Line; 166*75ce41a5SAli Bahrami 167*75ce41a5SAli Bahrami $Ver =~ s/^.*-\t(.*): .*/$1/; # isolate version 168*75ce41a5SAli Bahrami 169*75ce41a5SAli Bahrami # See if we've already caught this version name. We only look 170*75ce41a5SAli Bahrami # at each version once. 171*75ce41a5SAli Bahrami next if ($Vers{$Ver}) ; 172*75ce41a5SAli Bahrami 173*75ce41a5SAli Bahrami # Note that the non-empty version has been seen 174*75ce41a5SAli Bahrami $Vers{$Ver} = 1; 175*75ce41a5SAli Bahrami $VersCnt++; 176*75ce41a5SAli Bahrami 177*75ce41a5SAli Bahrami # We expect the public SUNW_major.minor.micro versions to use 178*75ce41a5SAli Bahrami # inheritance, so there should only be one top version for 179*75ce41a5SAli Bahrami # each major number. It is possible, though rare, to have 180*75ce41a5SAli Bahrami # more than one top version if the major numbers differ. 181*75ce41a5SAli Bahrami # 182*75ce41a5SAli Bahrami # %TopSUNWVers uses the major name as the key, with each 183*75ce41a5SAli Bahrami # value yielding an array reference to the top versions for 184*75ce41a5SAli Bahrami # that major number. 185*75ce41a5SAli Bahrami if ($Ver =~ /^(SUNW_[0-9]+)[0-9.]+$/) { 186*75ce41a5SAli Bahrami push @{$TopSUNWVers{$1}}, $Ver if $TopVer{$Ver}; 187*75ce41a5SAli Bahrami next; 188*75ce41a5SAli Bahrami } 189*75ce41a5SAli Bahrami 190*75ce41a5SAli Bahrami # Having already handled SUNW_ public versions above, is it 191*75ce41a5SAli Bahrami # a different version name that we recognise? 192*75ce41a5SAli Bahrami # 193*75ce41a5SAli Bahrami # Along with the standard version names, each object exports 194*75ce41a5SAli Bahrami # a "base" version which contains the linker generated symbols 195*75ce41a5SAli Bahrami # _etext, _edata, etc., and is named using the objects SONAME. 196*75ce41a5SAli Bahrami # This name should typically match the file name. 197*75ce41a5SAli Bahrami next if (($Ver =~ /^SYSVABI_1.[23]$/) || 198*75ce41a5SAli Bahrami ($Ver =~ /^SISCD_2.3[ab]*$/) || 199*75ce41a5SAli Bahrami ($Ver =~ /^SUNWprivate(_[0-9.]+)?$/) || 200*75ce41a5SAli Bahrami ($Ver =~ /$File/)); 201*75ce41a5SAli Bahrami 202*75ce41a5SAli Bahrami # If we get here, it's a non-standard version. 203*75ce41a5SAli Bahrami if (!defined($EXRE_nonstd_vername) || 204*75ce41a5SAli Bahrami ($RelPath !~ $EXRE_nonstd_vername)) { 205*75ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 206*75ce41a5SAli Bahrami "non-standard version name: $Ver"); 207*75ce41a5SAli Bahrami } 208*75ce41a5SAli Bahrami next; 209*75ce41a5SAli Bahrami } 210*75ce41a5SAli Bahrami 211*75ce41a5SAli Bahrami # If this file has been scoped, but not versioned (i.e., a mapfile was 212*75ce41a5SAli Bahrami # used to demote symbols but no version name was applied to the 213*75ce41a5SAli Bahrami # global interfaces) then it's another non-standard case. 214*75ce41a5SAli Bahrami if ($VersCnt eq 0) { 215*75ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 216*75ce41a5SAli Bahrami "scoped object contains no versions"); 217*75ce41a5SAli Bahrami return; 218*75ce41a5SAli Bahrami } 219*75ce41a5SAli Bahrami 220*75ce41a5SAli Bahrami # If this file has multiple inheritance chains with the public 221*75ce41a5SAli Bahrami # SUNW_ name, that's wrong. 222*75ce41a5SAli Bahrami foreach my $Ver (sort keys %TopSUNWVers) { 223*75ce41a5SAli Bahrami if (scalar(@{$TopSUNWVers{$Ver}}) > 1) { 224*75ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, \$Ttl, $RelPath, 225*75ce41a5SAli Bahrami "multiple $Ver inheritance chains (missing " . 226*75ce41a5SAli Bahrami "inheritance?): " . 227*75ce41a5SAli Bahrami join(', ', @{$TopSUNWVers{$Ver}})); 228*75ce41a5SAli Bahrami } 229*75ce41a5SAli Bahrami } 230*75ce41a5SAli Bahrami 231*75ce41a5SAli Bahrami 232*75ce41a5SAli Bahrami # Produce an interface description for the object. 233*75ce41a5SAli Bahrami # For each version, generate a VERSION declaration of the form: 234*75ce41a5SAli Bahrami # 235*75ce41a5SAli Bahrami # [TOP_]VERSION version direct-count total-count 236*75ce41a5SAli Bahrami # symname1 237*75ce41a5SAli Bahrami # symname2 238*75ce41a5SAli Bahrami # ... 239*75ce41a5SAli Bahrami # 240*75ce41a5SAli Bahrami # There are two types of version that we suppress from this 241*75ce41a5SAli Bahrami # output: 242*75ce41a5SAli Bahrami # 243*75ce41a5SAli Bahrami # BASE 244*75ce41a5SAli Bahrami # The "base" version is used to hold symbols that must be 245*75ce41a5SAli Bahrami # public, but which are not part of the versioning interface 246*75ce41a5SAli Bahrami # (_end, _GLOBAL_OFFSET_TABLE_, _PROCEDURE_LINKAGE_TABLE_, etc). 247*75ce41a5SAli Bahrami # 248*75ce41a5SAli Bahrami # Private 249*75ce41a5SAli Bahrami # Any version with "private" in its name is skipped. We 250*75ce41a5SAli Bahrami # expect these to be SUNWprivate, but are extra lenient in 251*75ce41a5SAli Bahrami # what we accept. 252*75ce41a5SAli Bahrami # 253*75ce41a5SAli Bahrami # If an object only has base or private versions, we do not produce 254*75ce41a5SAli Bahrami # an interface description for that object. 255*75ce41a5SAli Bahrami # 256*75ce41a5SAli Bahrami if ($opt{i}) { 257*75ce41a5SAli Bahrami my $header_done = 0; 258*75ce41a5SAli Bahrami 259*75ce41a5SAli Bahrami # The use of 'pvs -v' is to identify the BASE version 260*75ce41a5SAli Bahrami foreach my $Line (split(/\n/, `pvs -dv $FullPath 2>&1`)) { 261*75ce41a5SAli Bahrami # Skip base version 262*75ce41a5SAli Bahrami next if ($Line =~ /\[BASE\]/); 263*75ce41a5SAli Bahrami 264*75ce41a5SAli Bahrami # Skip private versions 265*75ce41a5SAli Bahrami next if ($Line =~ /private/i); 266*75ce41a5SAli Bahrami 267*75ce41a5SAli Bahrami # Directly inherited versions follow the version name 268*75ce41a5SAli Bahrami # in a comma separated list within {} brackets. Capture 269*75ce41a5SAli Bahrami # that information, for use with our VERSION line. 270*75ce41a5SAli Bahrami my $InheritVers = ($Line =~ /(\{.*\});$/) ? "\t$1" : ''; 271*75ce41a5SAli Bahrami 272*75ce41a5SAli Bahrami $Line =~ s/^\s*([^;: ]*).*/$1/; 273*75ce41a5SAli Bahrami 274*75ce41a5SAli Bahrami # Older versions of pvs have a bug that prevents 275*75ce41a5SAli Bahrami # them from printing [BASE] on the base version. 276*75ce41a5SAli Bahrami # Work around this by excluding versions that end 277*75ce41a5SAli Bahrami # with a '.so.*' suffix. 278*75ce41a5SAli Bahrami # SONAME of the object. 279*75ce41a5SAli Bahrami next if $Line =~ /\.so\.\d+$/; 280*75ce41a5SAli Bahrami 281*75ce41a5SAli Bahrami # We want to output the symbols in sorted order, so 282*75ce41a5SAli Bahrami # we gather them first, and then sort the results. 283*75ce41a5SAli Bahrami # An array would suffice, but we have observed objects 284*75ce41a5SAli Bahrami # with odd inheritance chains in which the same 285*75ce41a5SAli Bahrami # sub-version gets inherited more than once, leading 286*75ce41a5SAli Bahrami # to the same symbol showing up more than once. Using 287*75ce41a5SAli Bahrami # a hash instead of an array thins out the duplicates. 288*75ce41a5SAli Bahrami my %Syms = (); 289*75ce41a5SAli Bahrami my $symitem = $opt{I} ? 'NEW' : 'SYMBOL'; 290*75ce41a5SAli Bahrami my $version_cnt = 0; 291*75ce41a5SAli Bahrami foreach my $Sym 292*75ce41a5SAli Bahrami (split(/\n/, `pvs -ds -N $Line $FullPath 2>&1`)) { 293*75ce41a5SAli Bahrami if ($Sym =~ /:$/) { 294*75ce41a5SAli Bahrami $version_cnt++; 295*75ce41a5SAli Bahrami # If this is an inherited sub-version, 296*75ce41a5SAli Bahrami # we don't need to continue unless 297*75ce41a5SAli Bahrami # generating output in -I mode. 298*75ce41a5SAli Bahrami if ($version_cnt >= 2) { 299*75ce41a5SAli Bahrami last if !$opt{I}; 300*75ce41a5SAli Bahrami $symitem = 'INHERIT'; 301*75ce41a5SAli Bahrami } 302*75ce41a5SAli Bahrami next; 303*75ce41a5SAli Bahrami } 304*75ce41a5SAli Bahrami $Sym =~ s/[ \t]*(.*);$/$1/; 305*75ce41a5SAli Bahrami $Sym =~ s/ .*$//; # remove any data size 306*75ce41a5SAli Bahrami $Syms{$Sym} = $symitem; 307*75ce41a5SAli Bahrami } 308*75ce41a5SAli Bahrami 309*75ce41a5SAli Bahrami if (!$header_done) { 310*75ce41a5SAli Bahrami print INTFILE "\n" if !$opt{h} && ($ObjCnt != 0); 311*75ce41a5SAli Bahrami $ObjCnt++; 312*75ce41a5SAli Bahrami print INTFILE "OBJECT\t$RelPath\n"; 313*75ce41a5SAli Bahrami print INTFILE "CLASS\tELFCLASS$Class\n"; 314*75ce41a5SAli Bahrami print INTFILE "TYPE\tET_$Type\n"; 315*75ce41a5SAli Bahrami print INTFILE $Alias if ($Alias ne ''); 316*75ce41a5SAli Bahrami $header_done = 1; 317*75ce41a5SAli Bahrami } 318*75ce41a5SAli Bahrami 319*75ce41a5SAli Bahrami my $item = $TopVer{$Line} ? 'TOP_VERSION' : 'VERSION'; 320*75ce41a5SAli Bahrami print INTFILE "$item\t$Line$InheritVers\n"; 321*75ce41a5SAli Bahrami 322*75ce41a5SAli Bahrami # Output symbols in sorted order 323*75ce41a5SAli Bahrami foreach my $Sym (sort keys %Syms) { 324*75ce41a5SAli Bahrami print INTFILE "\t$Syms{$Sym}\t$Sym\n"; 325*75ce41a5SAli Bahrami } 326*75ce41a5SAli Bahrami } 327*75ce41a5SAli Bahrami } 328*75ce41a5SAli Bahrami} 329*75ce41a5SAli Bahrami 330*75ce41a5SAli Bahrami## ProcFindElf(file) 331*75ce41a5SAli Bahrami# 332*75ce41a5SAli Bahrami# Open the specified file, which must be produced by "find_elf -r", 333*75ce41a5SAli Bahrami# and process the files it describes. 334*75ce41a5SAli Bahramisub ProcFindElf { 335*75ce41a5SAli Bahrami my $file = $_[0]; 336*75ce41a5SAli Bahrami my $line; 337*75ce41a5SAli Bahrami my $LineNum = 0; 338*75ce41a5SAli Bahrami my $prefix; 339*75ce41a5SAli Bahrami my @ObjList = (); 340*75ce41a5SAli Bahrami my %ObjToAlias = (); 341*75ce41a5SAli Bahrami 342*75ce41a5SAli Bahrami open(FIND_ELF, $file) || die "$Prog: Unable to open $file"; 343*75ce41a5SAli Bahrami 344*75ce41a5SAli Bahrami # This script requires relative paths, created by the 'find_elf -r' 345*75ce41a5SAli Bahrami # option. When this is done, the first non-comment line will always 346*75ce41a5SAli Bahrami # be PREFIX. Obtain that line, or issue a fatal error. 347*75ce41a5SAli Bahrami while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) { 348*75ce41a5SAli Bahrami if ($line =~ /^PREFIX\s+(.*)$/) { 349*75ce41a5SAli Bahrami $prefix = $1; 350*75ce41a5SAli Bahrami last; 351*75ce41a5SAli Bahrami } 352*75ce41a5SAli Bahrami 353*75ce41a5SAli Bahrami die "$file: PREFIX expected on line $LineNum\n"; 354*75ce41a5SAli Bahrami } 355*75ce41a5SAli Bahrami 356*75ce41a5SAli Bahrami 357*75ce41a5SAli Bahrami # Process the remainder of the file. 358*75ce41a5SAli Bahrami while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) { 359*75ce41a5SAli Bahrami if ($line =~ /^OBJECT\s/i) { 360*75ce41a5SAli Bahrami push @ObjList, $line; 361*75ce41a5SAli Bahrami next; 362*75ce41a5SAli Bahrami } 363*75ce41a5SAli Bahrami 364*75ce41a5SAli Bahrami if ($line =~ /^ALIAS\s/i) { 365*75ce41a5SAli Bahrami my ($item, $obj, $alias) = split(/\s+/, $line, 3); 366*75ce41a5SAli Bahrami my $str = "ALIAS\t$alias\n"; 367*75ce41a5SAli Bahrami 368*75ce41a5SAli Bahrami if (defined($ObjToAlias{$obj})) { 369*75ce41a5SAli Bahrami $ObjToAlias{$obj} .= $str; 370*75ce41a5SAli Bahrami } else { 371*75ce41a5SAli Bahrami $ObjToAlias{$obj} = $str; 372*75ce41a5SAli Bahrami } 373*75ce41a5SAli Bahrami } 374*75ce41a5SAli Bahrami } 375*75ce41a5SAli Bahrami 376*75ce41a5SAli Bahrami foreach $line (@ObjList) { 377*75ce41a5SAli Bahrami my ($item, $class, $type, $verdef, $obj) = 378*75ce41a5SAli Bahrami split(/\s+/, $line, 5); 379*75ce41a5SAli Bahrami 380*75ce41a5SAli Bahrami my $alias = defined($ObjToAlias{$obj}) ? $ObjToAlias{$obj} : ''; 381*75ce41a5SAli Bahrami 382*75ce41a5SAli Bahrami # We are only interested in sharable objects. We may see 383*75ce41a5SAli Bahrami # other file types if processing a list of objects 384*75ce41a5SAli Bahrami # supplied via the -f option. 385*75ce41a5SAli Bahrami next if ($type ne 'DYN'); 386*75ce41a5SAli Bahrami 387*75ce41a5SAli Bahrami ProcFile($prefix, $obj, $class, $type, $verdef, $alias); 388*75ce41a5SAli Bahrami } 389*75ce41a5SAli Bahrami 390*75ce41a5SAli Bahrami close FIND_ELF; 391*75ce41a5SAli Bahrami} 392*75ce41a5SAli Bahrami 393*75ce41a5SAli Bahrami 394*75ce41a5SAli Bahrami# ----------------------------------------------------------------------------- 395*75ce41a5SAli Bahrami 396*75ce41a5SAli Bahrami# Establish a program name for any error diagnostics. 397*75ce41a5SAli Bahramichomp($Prog = `basename $0`); 398*75ce41a5SAli Bahrami 399*75ce41a5SAli Bahrami# The onbld_elfmod package is maintained in the same directory as this 400*75ce41a5SAli Bahrami# script, and is installed in ../lib/perl. Use the local one if present, 401*75ce41a5SAli Bahrami# and the installed one otherwise. 402*75ce41a5SAli Bahramimy $moddir = dirname($0); 403*75ce41a5SAli Bahrami$moddir = "$moddir/../lib/perl" if ! -f "$moddir/onbld_elfmod.pm"; 404*75ce41a5SAli Bahramirequire "$moddir/onbld_elfmod.pm"; 405*75ce41a5SAli Bahrami 406*75ce41a5SAli Bahrami# Check that we have arguments. 407*75ce41a5SAli Bahrami@SaveArgv = @ARGV; 408*75ce41a5SAli Bahramiif ((getopts('E:e:f:hIi:ow:', \%opt) == 0) || (!$opt{f} && ($#ARGV == -1))) { 409*75ce41a5SAli Bahrami print "usage: $Prog [-hIo] [-E errfile] [-e exfile] [-f listfile]\n"; 410*75ce41a5SAli Bahrami print "\t\t[-i intffile] [-w outdir] file | dir, ...\n"; 411*75ce41a5SAli Bahrami print "\n"; 412*75ce41a5SAli Bahrami print "\t[-E errfile]\tdirect error output to file\n"; 413*75ce41a5SAli Bahrami print "\t[-e exfile]\texceptions file\n"; 414*75ce41a5SAli Bahrami print "\t[-f listfile]\tuse file list produced by find_elf -r\n"; 415*75ce41a5SAli Bahrami print "\t[-h]\tdo not produce a CDDL/Copyright header comment\n"; 416*75ce41a5SAli Bahrami print "\t[-I]\tExpand inheritance in -i output (debugging)\n"; 417*75ce41a5SAli Bahrami print "\t[-i intffile]\tcreate interface description output file\n"; 418*75ce41a5SAli Bahrami print "\t[-o]\t\tproduce one-liner output (prefixed with pathname)\n"; 419*75ce41a5SAli Bahrami print "\t[-w outdir]\tinterpret all files relative to given directory\n"; 420*75ce41a5SAli Bahrami exit 1; 421*75ce41a5SAli Bahrami} 422*75ce41a5SAli Bahrami 423*75ce41a5SAli Bahrami# If -w, change working directory to given location 424*75ce41a5SAli Bahrami!$opt{w} || chdir($opt{w}) || die "$Prog: can't cd to $opt{w}"; 425*75ce41a5SAli Bahrami 426*75ce41a5SAli Bahrami 427*75ce41a5SAli Bahrami# Error messages go to stdout unless -E is specified. $ErrFH is a 428*75ce41a5SAli Bahrami# file handle reference that points at the file handle where error messages 429*75ce41a5SAli Bahrami# are sent. 430*75ce41a5SAli Bahramiif ($opt{E}) { 431*75ce41a5SAli Bahrami open(ERROR, ">$opt{E}") || die "$Prog: open failed: $opt{E}"; 432*75ce41a5SAli Bahrami $ErrFH = \*ERROR; 433*75ce41a5SAli Bahrami} else { 434*75ce41a5SAli Bahrami $ErrFH = \*STDOUT; 435*75ce41a5SAli Bahrami} 436*75ce41a5SAli Bahrami 437*75ce41a5SAli Bahrami# Locate and process the exceptions file 438*75ce41a5SAli Bahramionbld_elfmod::LoadExceptionsToEXRE('interface_check'); 439*75ce41a5SAli Bahrami 440*75ce41a5SAli Bahrami# If creating an interface description output file, prepare it for use 441*75ce41a5SAli Bahramiif ($opt{i}) { 442*75ce41a5SAli Bahrami open (INTFILE, ">$opt{i}") || 443*75ce41a5SAli Bahrami die "$Prog: Unable to create file: $opt{i}"; 444*75ce41a5SAli Bahrami 445*75ce41a5SAli Bahrami # Generate the output header 446*75ce41a5SAli Bahrami onbld_elfmod::Header(\*INTFILE, $0, \@SaveArgv) if !$opt{h};; 447*75ce41a5SAli Bahrami} 448*75ce41a5SAli Bahrami 449*75ce41a5SAli Bahrami# Number of OBJECTs output to INTFILE 450*75ce41a5SAli Bahrami$ObjCnt = 0; 451*75ce41a5SAli Bahrami 452*75ce41a5SAli Bahrami# If we were passed a file previously produced by 'find_elf -r', use it. 453*75ce41a5SAli BahramiProcFindElf($opt{f}) if $opt{f}; 454*75ce41a5SAli Bahrami 455*75ce41a5SAli Bahrami# Process each argument 456*75ce41a5SAli Bahramiforeach my $Arg (@ARGV) { 457*75ce41a5SAli Bahrami # Run find_elf to find the files given by $Arg and process them 458*75ce41a5SAli Bahrami ProcFindElf("find_elf -frs $Arg|"); 459*75ce41a5SAli Bahrami} 460*75ce41a5SAli Bahrami 461*75ce41a5SAli Bahrami# Close any working output files. 462*75ce41a5SAli Bahramiclose INTFILE if $opt{i}; 463*75ce41a5SAli Bahramiclose ERROR if $opt{E}; 464*75ce41a5SAli Bahrami 465*75ce41a5SAli Bahramiexit 0; 466