1*7c478bd9Sstevel@tonic-gate#!/usr/perl5/bin/perl -w 2*7c478bd9Sstevel@tonic-gate# 3*7c478bd9Sstevel@tonic-gate# CDDL HEADER START 4*7c478bd9Sstevel@tonic-gate# 5*7c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the 6*7c478bd9Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only 7*7c478bd9Sstevel@tonic-gate# (the "License"). You may not use this file except in compliance 8*7c478bd9Sstevel@tonic-gate# with the License. 9*7c478bd9Sstevel@tonic-gate# 10*7c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11*7c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 12*7c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions 13*7c478bd9Sstevel@tonic-gate# and limitations under the License. 14*7c478bd9Sstevel@tonic-gate# 15*7c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 16*7c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17*7c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 18*7c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 19*7c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 20*7c478bd9Sstevel@tonic-gate# 21*7c478bd9Sstevel@tonic-gate# CDDL HEADER END 22*7c478bd9Sstevel@tonic-gate# 23*7c478bd9Sstevel@tonic-gate# 24*7c478bd9Sstevel@tonic-gate# Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25*7c478bd9Sstevel@tonic-gate# Use is subject to license terms. 26*7c478bd9Sstevel@tonic-gate# 27*7c478bd9Sstevel@tonic-gate# ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate# 29*7c478bd9Sstevel@tonic-gate# Check ELF information. 30*7c478bd9Sstevel@tonic-gate# 31*7c478bd9Sstevel@tonic-gate# This script descends a directory hierarchy inspecting ELF dynamic executables 32*7c478bd9Sstevel@tonic-gate# and shared objects. The general theme is to verify that common Makefile rules 33*7c478bd9Sstevel@tonic-gate# have been used to build these objects. Typical failures occur when Makefile 34*7c478bd9Sstevel@tonic-gate# rules are re-invented rather than being inherited from "cmd/lib" Makefiles. 35*7c478bd9Sstevel@tonic-gate# 36*7c478bd9Sstevel@tonic-gate# As always, a number of components don't follow the rules, and these are 37*7c478bd9Sstevel@tonic-gate# excluded to reduce this scripts output. Pathnames used for this exclusion 38*7c478bd9Sstevel@tonic-gate# assume this script is being run over a "proto" area. The -a (all) option 39*7c478bd9Sstevel@tonic-gate# skips any exclusions. 40*7c478bd9Sstevel@tonic-gate# 41*7c478bd9Sstevel@tonic-gate# By default any file that has conditions that should be reported is first 42*7c478bd9Sstevel@tonic-gate# listed and then each condition follows. The -o (one-line) option produces a 43*7c478bd9Sstevel@tonic-gate# more terse output which is better for sorting/diffing with "nightly". 44*7c478bd9Sstevel@tonic-gate# 45*7c478bd9Sstevel@tonic-gate# NOTE: missing dependencies, symbols or versions are reported by running the 46*7c478bd9Sstevel@tonic-gate# file through ldd(1). As objects within a proto area are built to exist in a 47*7c478bd9Sstevel@tonic-gate# base system, standard use of ldd(1) will bind any objects to dependencies 48*7c478bd9Sstevel@tonic-gate# that exist in the base system. It is frequently the case that newer objects 49*7c478bd9Sstevel@tonic-gate# exist in the proto area that are required to satisfy other objects 50*7c478bd9Sstevel@tonic-gate# dependencies, and without using these newer objects an ldd(1) will produce 51*7c478bd9Sstevel@tonic-gate# misleading error messages. To compensate for this, the -d option (or the 52*7c478bd9Sstevel@tonic-gate# existence of the CODEMSG_WS/ROOT environment variables) cause the creation of 53*7c478bd9Sstevel@tonic-gate# alternative dependency mappings via crle(1) configuration files that establish 54*7c478bd9Sstevel@tonic-gate# any proto shared objects as alternatives to their base system location. Thus 55*7c478bd9Sstevel@tonic-gate# ldd(1) can be executed against these configuration files so that objects in a 56*7c478bd9Sstevel@tonic-gate# proto area bind to their dependencies in the same proto area. 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate# Define all global variables (required for strict) 60*7c478bd9Sstevel@tonic-gateuse vars qw($SkipDirs $SkipFiles $SkipTextrelFiles); 61*7c478bd9Sstevel@tonic-gateuse vars qw($SkipUndefDirs $SkipUndefFiles $SkipUnusedDirs $SkipUnusedFiles); 62*7c478bd9Sstevel@tonic-gateuse vars qw($SkipStripDirs $SkipNoStripFiles $SkipStabFiles $SkipNoExStkFiles); 63*7c478bd9Sstevel@tonic-gateuse vars qw($UnusedNoise $Prog $Mach $Isalist $Env $Ena64 $Tmpdir $Error); 64*7c478bd9Sstevel@tonic-gateuse vars qw($UnusedFiles $UnusedPaths $LddNoU $Crle32 $Crle64 $Conf32 $Conf64); 65*7c478bd9Sstevel@tonic-gateuse vars qw($SkipInterps $OldDeps %opt); 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gateuse strict; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate# Define any directories we should skip completely. 71*7c478bd9Sstevel@tonic-gate$SkipDirs = qr{ 72*7c478bd9Sstevel@tonic-gate etc/lib | # special - used for partial statics 73*7c478bd9Sstevel@tonic-gate usr/lib/devfsadm | # 4382889 74*7c478bd9Sstevel@tonic-gate usr/lib/libc | # optimized libc 75*7c478bd9Sstevel@tonic-gate usr/lib/rcm | # 4426119 76*7c478bd9Sstevel@tonic-gate usr/perl5 | # alan's taking care of these :-) 77*7c478bd9Sstevel@tonic-gate usr/src # no need to look at shipped source 78*7c478bd9Sstevel@tonic-gate}x; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate# Define any files we should skip completely. 81*7c478bd9Sstevel@tonic-gate$SkipFiles = qr{ ^(?: 82*7c478bd9Sstevel@tonic-gate ld\.so\.1 | # confusing but correct dependencies 83*7c478bd9Sstevel@tonic-gate lddstub | # lddstub has no dependencies 84*7c478bd9Sstevel@tonic-gate libmakestate\.so\.1 | # temporary; delivered by compiler group 85*7c478bd9Sstevel@tonic-gate libm\.so\.1 | # temporary; delivered by compiler group 86*7c478bd9Sstevel@tonic-gate libm\.so\.2 | # temporary; delivered by compiler group 87*7c478bd9Sstevel@tonic-gate geniconvtbl\.so | # 4384329 88*7c478bd9Sstevel@tonic-gate libssagent\.so\.1 | # 4328854 89*7c478bd9Sstevel@tonic-gate libdmi\.so\.1 | # " " 90*7c478bd9Sstevel@tonic-gate libdmici\.so\.1 | # " " 91*7c478bd9Sstevel@tonic-gate libdmimi\.so\.1 | # " " 92*7c478bd9Sstevel@tonic-gate libpsvcplugin_psr\.so\.1 | # 4385799 93*7c478bd9Sstevel@tonic-gate libpsvcpolicy_psr\.so\.1 | # " " 94*7c478bd9Sstevel@tonic-gate libpsvcpolicy\.so\.1 | # " " 95*7c478bd9Sstevel@tonic-gate picl_slm\.so | # " " 96*7c478bd9Sstevel@tonic-gate libcrypto_extra\.so\.0\.9\.7 | # OpenSSL SUNWcry filter lib 97*7c478bd9Sstevel@tonic-gate libssl_extra\.so\.0\.9\.7 | # OpenSSL SUNWcry filter lib 98*7c478bd9Sstevel@tonic-gate fcpackage\.so | # circular dependency on fcthread.so 99*7c478bd9Sstevel@tonic-gate grub 100*7c478bd9Sstevel@tonic-gate )$ 101*7c478bd9Sstevel@tonic-gate}x; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate# Define any files that are allowed text relocations. 104*7c478bd9Sstevel@tonic-gate$SkipTextrelFiles = qr{ ^(?: 105*7c478bd9Sstevel@tonic-gate unix | # kernel models are non-pic 106*7c478bd9Sstevel@tonic-gate mdb # relocations against __RTC (dbx) 107*7c478bd9Sstevel@tonic-gate )$ 108*7c478bd9Sstevel@tonic-gate}x; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate# Define any files that are allowed undefined references. 111*7c478bd9Sstevel@tonic-gate$SkipUndefDirs = qr{ 112*7c478bd9Sstevel@tonic-gate usr/lib/inet/ppp/ | # pppd plugins have callbacks 113*7c478bd9Sstevel@tonic-gate usr/lib/libp/ | # libc.so.1 requires _mcount 114*7c478bd9Sstevel@tonic-gate usr/lib/vold/ | # vold dependencies have callbacks 115*7c478bd9Sstevel@tonic-gate usr/lib/rmmount | # rmmount actions have callbacks 116*7c478bd9Sstevel@tonic-gate /lib/mdb/ | # mdb modules have callbacks 117*7c478bd9Sstevel@tonic-gate /lib/fm/fmd/plugins/ | # fmd modules have callbacks 118*7c478bd9Sstevel@tonic-gate /lib/fm/fmd/schemes/ # fmd schemes have callbacks 119*7c478bd9Sstevel@tonic-gate}x; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate$SkipUndefFiles = qr{ ^(?: 122*7c478bd9Sstevel@tonic-gate libthread_db\.so\.0 | # callbacks to proc service interface 123*7c478bd9Sstevel@tonic-gate libthread_db\.so\.1 | # " " " " 124*7c478bd9Sstevel@tonic-gate librtld_db\.so\.1 | # " " " " 125*7c478bd9Sstevel@tonic-gate libc_db\.so\.1 | # " " " " 126*7c478bd9Sstevel@tonic-gate libldstab\.so\.1 | # link-edit support libraries have 127*7c478bd9Sstevel@tonic-gate libld\.so\.3 | # callback to the link-editors 128*7c478bd9Sstevel@tonic-gate libld\.so\.2 | # " " " " 129*7c478bd9Sstevel@tonic-gate liblddbg\.so\.4 | # " " " " 130*7c478bd9Sstevel@tonic-gate librtld\.so\.1 | # " " " " 131*7c478bd9Sstevel@tonic-gate libnisdb\.so\.2 | # C++ 132*7c478bd9Sstevel@tonic-gate libsvm\.so\.1 | # libspmicommon.so.1 lacking 133*7c478bd9Sstevel@tonic-gate libwanboot\.so\.1 | # libcrypto.a and libssl.a 134*7c478bd9Sstevel@tonic-gate libwrap\.so\.1\.0 | # uses symbols provided by application 135*7c478bd9Sstevel@tonic-gate fcthread\.so | # uses symbols provided by application 136*7c478bd9Sstevel@tonic-gate fn\.so\.2 | # callback to automount 137*7c478bd9Sstevel@tonic-gate preen_md\.so\.1 | # callback to driver 138*7c478bd9Sstevel@tonic-gate libike\.so\.1 | # callbacks to in.iked for IKE policy 139*7c478bd9Sstevel@tonic-gate devfsadmd_mod\.so | # sysevent module callback to syseventd 140*7c478bd9Sstevel@tonic-gate sysevent_conf_mod\.so | # sysevent module callback to syseventd 141*7c478bd9Sstevel@tonic-gate sysevent_reg_mod\.so # sysevent module callback to syseventd 142*7c478bd9Sstevel@tonic-gate )$ 143*7c478bd9Sstevel@tonic-gate}x; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate# Define any files that have unused dependencies. 146*7c478bd9Sstevel@tonic-gate$SkipUnusedDirs = qr{ 147*7c478bd9Sstevel@tonic-gate lib/picl/plugins/ | # require devtree dependencies 148*7c478bd9Sstevel@tonic-gate /lib/libp # profile libc makes libm an unused 149*7c478bd9Sstevel@tonic-gate}x; # dependency of standard libc 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate$SkipUnusedFiles = qr{ ^(?: 152*7c478bd9Sstevel@tonic-gate devfsadm | # 4382889 153*7c478bd9Sstevel@tonic-gate disks | # " " 154*7c478bd9Sstevel@tonic-gate tapes | # " " 155*7c478bd9Sstevel@tonic-gate ports | # " " 156*7c478bd9Sstevel@tonic-gate audlinks | # " " 157*7c478bd9Sstevel@tonic-gate devlinks | # " " 158*7c478bd9Sstevel@tonic-gate drvconfig | # " " 159*7c478bd9Sstevel@tonic-gate ntptrace | # on intel doesn't need libmd5 160*7c478bd9Sstevel@tonic-gate rmmount | # 4418770, volmgt dependency is required 161*7c478bd9Sstevel@tonic-gate # to compensate for SunPCi. 162*7c478bd9Sstevel@tonic-gate ocfserv | # libsched unreference by libjvm, 163*7c478bd9Sstevel@tonic-gate poold | # see 4952319. 164*7c478bd9Sstevel@tonic-gate libc\.so\.1\.9 | # 4lib/libc versions have private 165*7c478bd9Sstevel@tonic-gate libc\.so\.2\.9 # copies of stuff from libc. 166*7c478bd9Sstevel@tonic-gate )$ 167*7c478bd9Sstevel@tonic-gate}x; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate# Define any files that can be stripped. 170*7c478bd9Sstevel@tonic-gate$SkipStripDirs = qr{ 171*7c478bd9Sstevel@tonic-gate /abi/ 172*7c478bd9Sstevel@tonic-gate}x; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate# Define any files that must not be stripped. 175*7c478bd9Sstevel@tonic-gate$SkipNoStripFiles = qr{ ^(?: 176*7c478bd9Sstevel@tonic-gate adb | 177*7c478bd9Sstevel@tonic-gate mdb | 178*7c478bd9Sstevel@tonic-gate unix 179*7c478bd9Sstevel@tonic-gate )$ 180*7c478bd9Sstevel@tonic-gate}x; 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate# Define any files that should contain debugging information. 183*7c478bd9Sstevel@tonic-gate$SkipStabFiles = qr{ ^(?: 184*7c478bd9Sstevel@tonic-gate abi_.* | 185*7c478bd9Sstevel@tonic-gate interceptors\.so\.1 | 186*7c478bd9Sstevel@tonic-gate unix 187*7c478bd9Sstevel@tonic-gate )$ 188*7c478bd9Sstevel@tonic-gate}x; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate# Define any files that don't require a non-executable stack definition. 191*7c478bd9Sstevel@tonic-gate$SkipNoExStkFiles = qr{ ^(?: 192*7c478bd9Sstevel@tonic-gate forth | 193*7c478bd9Sstevel@tonic-gate unix | 194*7c478bd9Sstevel@tonic-gate multiboot 195*7c478bd9Sstevel@tonic-gate )$ 196*7c478bd9Sstevel@tonic-gate}x; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate# Define any files that should only have unused (ldd -u) processing. 199*7c478bd9Sstevel@tonic-gate$UnusedPaths = qr{ 200*7c478bd9Sstevel@tonic-gate ucb/shutdown # libucb interposes on libc and makes 201*7c478bd9Sstevel@tonic-gate # dependencies on libc seem unnecessary 202*7c478bd9Sstevel@tonic-gate}x; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate$UnusedFiles = qr{ ^(?: 205*7c478bd9Sstevel@tonic-gate rpc\.nisd # CCNEEDED makes pthread unreferenced 206*7c478bd9Sstevel@tonic-gate )$ 207*7c478bd9Sstevel@tonic-gate}x; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate# Define unused dependencies we should ignore. 210*7c478bd9Sstevel@tonic-gate# libCrun has a unnecessary dependency on libw, and libmapmalloc is often 211*7c478bd9Sstevel@tonic-gate# defined to interpose on libc but isn't used by the application itself. 212*7c478bd9Sstevel@tonic-gate# Threads dependencies look unused if libc is bound first. 213*7c478bd9Sstevel@tonic-gate$UnusedNoise = qr{ 214*7c478bd9Sstevel@tonic-gate libw\.so\.1;\ unused | 215*7c478bd9Sstevel@tonic-gate unused\ object=.*libw\.so\.1 | 216*7c478bd9Sstevel@tonic-gate libthread\.so\.1;\ unused | 217*7c478bd9Sstevel@tonic-gate libpthread\.so\.1;\ unused | 218*7c478bd9Sstevel@tonic-gate unused\ object=.*libpthread\.so\.1 | 219*7c478bd9Sstevel@tonic-gate libnsl\.so\.1;\ unused\ dependency\ of\ .*libxslt\.so\.1 | 220*7c478bd9Sstevel@tonic-gate libdl\.so\.1;\ unused\ dependency\ of\ .*libspmicommon\.so\.1 | 221*7c478bd9Sstevel@tonic-gate libdl\.so\.1;\ unused\ dependency\ of\ .*libCrun\.so\.1 | 222*7c478bd9Sstevel@tonic-gate libfru\.so\.1;\ unused\ object=.*libdl\.so\.1 | 223*7c478bd9Sstevel@tonic-gate libfrupicl\.so\.1;\ unused\ object=.*libdl\.so\.1 | 224*7c478bd9Sstevel@tonic-gate libmapmalloc\.so\.1;\ unused 225*7c478bd9Sstevel@tonic-gate}x; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate# Define interpreters we should ignore. 229*7c478bd9Sstevel@tonic-gate$SkipInterps = qr{ 230*7c478bd9Sstevel@tonic-gate misc/krtld | 231*7c478bd9Sstevel@tonic-gate misc/amd64/krtld | 232*7c478bd9Sstevel@tonic-gate misc/sparcv9/krtld 233*7c478bd9Sstevel@tonic-gate}x; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate# Catch libintl and libw, although ld(1) will bind to these and thus determine 236*7c478bd9Sstevel@tonic-gate# they're needed, their content was moved into libc as of on297 build 7. 237*7c478bd9Sstevel@tonic-gate# libthread and libpthread were completely moved into libc as of on10 build 53. 238*7c478bd9Sstevel@tonic-gate# Also, catch libdl, whose content was moved into libc as of on10 build 49. 239*7c478bd9Sstevel@tonic-gate$OldDeps = qr{ ^(?: 240*7c478bd9Sstevel@tonic-gate libintl\.so\.1 | 241*7c478bd9Sstevel@tonic-gate libw\.so\.1 | 242*7c478bd9Sstevel@tonic-gate libthread\.so\.1 | 243*7c478bd9Sstevel@tonic-gate libpthread\.so\.1 | 244*7c478bd9Sstevel@tonic-gate libdl\.so\.1 245*7c478bd9Sstevel@tonic-gate )$ 246*7c478bd9Sstevel@tonic-gate}x; 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gateuse Getopt::Std; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate# ----------------------------------------------------------------------------- 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate# Reliably compare two OS revisions. Arguments are <ver1> <op> <ver2>. 253*7c478bd9Sstevel@tonic-gate# <op> is the string form of a normal numeric comparison operator. 254*7c478bd9Sstevel@tonic-gatesub cmp_os_ver { 255*7c478bd9Sstevel@tonic-gate my @ver1 = split(/\./, $_[0]); 256*7c478bd9Sstevel@tonic-gate my $op = $_[1]; 257*7c478bd9Sstevel@tonic-gate my @ver2 = split(/\./, $_[2]); 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate push @ver2, ("0") x $#ver1 - $#ver2; 260*7c478bd9Sstevel@tonic-gate push @ver1, ("0") x $#ver2 - $#ver1; 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate my $diff = 0; 263*7c478bd9Sstevel@tonic-gate while (@ver1 || @ver2) { 264*7c478bd9Sstevel@tonic-gate if (($diff = shift(@ver1) - shift(@ver2)) != 0) { 265*7c478bd9Sstevel@tonic-gate last; 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate return (eval "$diff $op 0" ? 1 : 0); 269*7c478bd9Sstevel@tonic-gate} 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate# Establish a program name for any error diagnostics. 272*7c478bd9Sstevel@tonic-gatechomp($Prog = `basename $0`); 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate# Determine what machinery is available. 275*7c478bd9Sstevel@tonic-gate$Mach = `uname -p`; 276*7c478bd9Sstevel@tonic-gate$Isalist = `isalist`; 277*7c478bd9Sstevel@tonic-gate$Env = ""; 278*7c478bd9Sstevel@tonic-gateif ($Mach =~ /sparc/) { 279*7c478bd9Sstevel@tonic-gate if ($Isalist =~ /sparcv9/) { 280*7c478bd9Sstevel@tonic-gate $Ena64 = "ok"; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate} elsif ($Mach =~ /i386/) { 283*7c478bd9Sstevel@tonic-gate if ($Isalist =~ /amd64/) { 284*7c478bd9Sstevel@tonic-gate $Ena64 = "ok"; 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate} 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate# Check that we have arguments. 289*7c478bd9Sstevel@tonic-gateif ((getopts('ad:imos', \%opt) == 0) || ($#ARGV == -1)) { 290*7c478bd9Sstevel@tonic-gate print "usage: $Prog [-a] [-d depdir] [-m] [-o] [-s] file | dir, ...\n"; 291*7c478bd9Sstevel@tonic-gate print "\t[-a]\t\tprocess all files (ignore any exception lists)\n"; 292*7c478bd9Sstevel@tonic-gate print "\t[-d dir]\testablish dependencies from under directory\n"; 293*7c478bd9Sstevel@tonic-gate print "\t[-i]\t\tproduce dynamic table entry information\n"; 294*7c478bd9Sstevel@tonic-gate print "\t[-m]\t\tprocess mcs(1) comments\n"; 295*7c478bd9Sstevel@tonic-gate print "\t[-o]\t\tproduce one-liner output (prefixed with pathname)\n"; 296*7c478bd9Sstevel@tonic-gate print "\t[-s]\t\tprocess .stab and .symtab entries\n"; 297*7c478bd9Sstevel@tonic-gate exit 1; 298*7c478bd9Sstevel@tonic-gate} else { 299*7c478bd9Sstevel@tonic-gate my($Proto); 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate if ($opt{d}) { 302*7c478bd9Sstevel@tonic-gate # User specified dependency directory - make sure it exists. 303*7c478bd9Sstevel@tonic-gate if (! -d $opt{d}) { 304*7c478bd9Sstevel@tonic-gate print "$Prog: $opt{d} is not a directory\n"; 305*7c478bd9Sstevel@tonic-gate exit 1; 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate $Proto = $opt{d}; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate } elsif ($ENV{CODEMGR_WS}) { 310*7c478bd9Sstevel@tonic-gate my($Root); 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate # Without a user specified dependency directory see if we're 313*7c478bd9Sstevel@tonic-gate # part of a codemanager workspace and if a proto area exists. 314*7c478bd9Sstevel@tonic-gate if (($Root = $ENV{ROOT}) && (-d $Root)) { 315*7c478bd9Sstevel@tonic-gate $Proto = $Root; 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (!($Tmpdir = $ENV{TMPDIR}) || (! -d $Tmpdir)) { 320*7c478bd9Sstevel@tonic-gate $Tmpdir = "/tmp"; 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate # Look for dependencies under $Proto. 324*7c478bd9Sstevel@tonic-gate if ($Proto) { 325*7c478bd9Sstevel@tonic-gate # To support alternative dependency mapping we'll need ldd(1)'s 326*7c478bd9Sstevel@tonic-gate # -e option. This is relatively new (s81_30), so make sure 327*7c478bd9Sstevel@tonic-gate # ldd(1)is capable before gathering any dependency information. 328*7c478bd9Sstevel@tonic-gate if (system('ldd -e /usr/lib/lddstub 2> /dev/null')) { 329*7c478bd9Sstevel@tonic-gate print "ldd: does not support -e, unable to "; 330*7c478bd9Sstevel@tonic-gate print "create alternative dependency mappingings.\n"; 331*7c478bd9Sstevel@tonic-gate print "ldd: option added under 4390308 (s81_30).\n\n"; 332*7c478bd9Sstevel@tonic-gate } else { 333*7c478bd9Sstevel@tonic-gate # Gather dependencies and construct a alternative 334*7c478bd9Sstevel@tonic-gate # dependency mapping via a crle(1) configuration file. 335*7c478bd9Sstevel@tonic-gate GetDeps($Proto, "/"); 336*7c478bd9Sstevel@tonic-gate GenConf(); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate # To support unreferenced dependency detection we'll need ldd(1)'s -U 341*7c478bd9Sstevel@tonic-gate # option. This is relatively new (4638070), and if not available we 342*7c478bd9Sstevel@tonic-gate # can still fall back to -u. Even with this option, don't use -U with 343*7c478bd9Sstevel@tonic-gate # releases prior to 5.10 as the cleanup for -U use only got integrated 344*7c478bd9Sstevel@tonic-gate # into 5.10 under 4642023. Note, that nightly doesn't typically set a 345*7c478bd9Sstevel@tonic-gate # RELEASE from the standard <env> files. Users who wish to disable use 346*7c478bd9Sstevel@tonic-gate # of ldd(1)'s -U should set (or uncomment) RELEASE in their <env> file 347*7c478bd9Sstevel@tonic-gate # if using nightly, or otherwise establish it in their environment. 348*7c478bd9Sstevel@tonic-gate if (system('ldd -U /usr/lib/lddstub 2> /dev/null')) { 349*7c478bd9Sstevel@tonic-gate $LddNoU = 1; 350*7c478bd9Sstevel@tonic-gate } else { 351*7c478bd9Sstevel@tonic-gate my($Release); 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate if (($Release = $ENV{RELEASE}) && 354*7c478bd9Sstevel@tonic-gate (cmp_os_ver($Release, "<", "5.10"))) { 355*7c478bd9Sstevel@tonic-gate $LddNoU = 1; 356*7c478bd9Sstevel@tonic-gate } else { 357*7c478bd9Sstevel@tonic-gate $LddNoU = 0; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate # For each argument determine if we're dealing with a file or directory. 362*7c478bd9Sstevel@tonic-gate foreach my $Arg (@ARGV) { 363*7c478bd9Sstevel@tonic-gate # Ignore symbolic links. 364*7c478bd9Sstevel@tonic-gate if (-l $Arg) { 365*7c478bd9Sstevel@tonic-gate next; 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate if (!stat($Arg)) { 369*7c478bd9Sstevel@tonic-gate next; 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate # Process simple files. 373*7c478bd9Sstevel@tonic-gate if (-f _) { 374*7c478bd9Sstevel@tonic-gate my($RelPath) = $Arg; 375*7c478bd9Sstevel@tonic-gate my($File) = $Arg; 376*7c478bd9Sstevel@tonic-gate my($Secure) = 0; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate $RelPath =~ s!^.*/!./!; 379*7c478bd9Sstevel@tonic-gate $File =~ s!^.*/!!; 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate if (-u _ || -g _) { 382*7c478bd9Sstevel@tonic-gate $Secure = 1; 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate ProcFile($Arg, $RelPath, $File, $Secure); 386*7c478bd9Sstevel@tonic-gate next; 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate # Process directories. 389*7c478bd9Sstevel@tonic-gate if (-d _) { 390*7c478bd9Sstevel@tonic-gate ProcDir($Arg, "."); 391*7c478bd9Sstevel@tonic-gate next; 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate print "$Arg is not a file or directory\n"; 395*7c478bd9Sstevel@tonic-gate $Error = 1; 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate # Cleanup 399*7c478bd9Sstevel@tonic-gate CleanUp(); 400*7c478bd9Sstevel@tonic-gate} 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate$Error = 0; 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate# Clean up and temporary files. 405*7c478bd9Sstevel@tonic-gatesub CleanUp { 406*7c478bd9Sstevel@tonic-gate if ($Crle64) { 407*7c478bd9Sstevel@tonic-gate unlink $Crle64; 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate if ($Conf64) { 410*7c478bd9Sstevel@tonic-gate unlink $Conf64; 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate if ($Crle32) { 413*7c478bd9Sstevel@tonic-gate unlink $Crle32; 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate if ($Conf32) { 416*7c478bd9Sstevel@tonic-gate unlink $Conf32; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate} 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate# Create an output message, either a one-liner (under -o) or preceded by the 421*7c478bd9Sstevel@tonic-gate# files relative pathname as a title. 422*7c478bd9Sstevel@tonic-gatesub OutMsg { 423*7c478bd9Sstevel@tonic-gate my($Ttl, $Path, $Msg) = @_; 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate if ($opt{o}) { 426*7c478bd9Sstevel@tonic-gate $Msg =~ s/^[ \t]*//; 427*7c478bd9Sstevel@tonic-gate print "$Path: $Msg\n"; 428*7c478bd9Sstevel@tonic-gate } else { 429*7c478bd9Sstevel@tonic-gate if ($Ttl eq 0) { 430*7c478bd9Sstevel@tonic-gate print "==== $Path ====\n"; 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate print "$Msg\n"; 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate} 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate# Determine whether this a ELF dynamic object and if so investigate its runtime 437*7c478bd9Sstevel@tonic-gate# attributes. 438*7c478bd9Sstevel@tonic-gatesub ProcFile { 439*7c478bd9Sstevel@tonic-gate my($FullPath, $RelPath, $File, $Secure) = @_; 440*7c478bd9Sstevel@tonic-gate my(@Elf, @Ldd, $Dyn, $Intp, $Dll, $Ttl, $Sym, $Interp, $Stack); 441*7c478bd9Sstevel@tonic-gate my($Sun, $Relsz, $Pltsz, $Uns, $Tex, $Stab, $Strip, $Lddopt); 442*7c478bd9Sstevel@tonic-gate my($Val, $Header, $SkipLdd, $IsX86, $RWX); 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate # Ignore symbolic links. 445*7c478bd9Sstevel@tonic-gate if (-l $FullPath) { 446*7c478bd9Sstevel@tonic-gate return; 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate $Ttl = 0; 450*7c478bd9Sstevel@tonic-gate @Ldd = 0; 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate # Determine whether we have access to inspect the file. 453*7c478bd9Sstevel@tonic-gate if (!(-r $FullPath)) { 454*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 455*7c478bd9Sstevel@tonic-gate "\tunable to inspect file: permission denied"); 456*7c478bd9Sstevel@tonic-gate return; 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate # Determine if this is a file we don't care about. 460*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 461*7c478bd9Sstevel@tonic-gate if ($File =~ $SkipFiles) { 462*7c478bd9Sstevel@tonic-gate return; 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate # Determine whether we have a executable (static or dynamic) or a 467*7c478bd9Sstevel@tonic-gate # shared object. 468*7c478bd9Sstevel@tonic-gate @Elf = split(/\n/, `elfdump -epdic $FullPath 2>&1`); 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate $Dyn = $Intp = $Dll = $Stack = $IsX86 = $RWX = 0; 471*7c478bd9Sstevel@tonic-gate $Interp = 1; 472*7c478bd9Sstevel@tonic-gate $Header = 'None'; 473*7c478bd9Sstevel@tonic-gate foreach my $Line (@Elf) { 474*7c478bd9Sstevel@tonic-gate # If we have an invalid file type (which we can tell from the 475*7c478bd9Sstevel@tonic-gate # first line), or we're processing an archive, bail. 476*7c478bd9Sstevel@tonic-gate if ($Header eq 'None') { 477*7c478bd9Sstevel@tonic-gate if (($Line =~ /invalid file/) || 478*7c478bd9Sstevel@tonic-gate ($Line =~ /$FullPath(.*):/)) { 479*7c478bd9Sstevel@tonic-gate return; 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate if ($Line =~ /^ELF Header/) { 484*7c478bd9Sstevel@tonic-gate $Header = 'Ehdr'; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate } elsif ($Line =~ /^Program Header/) { 487*7c478bd9Sstevel@tonic-gate $Header = 'Phdr'; 488*7c478bd9Sstevel@tonic-gate $RWX = 0; 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate } elsif ($Line =~ /^Interpreter/) { 491*7c478bd9Sstevel@tonic-gate $Header = 'Intp'; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate } elsif ($Line =~ /^Dynamic Section/) { 494*7c478bd9Sstevel@tonic-gate # A dynamic section indicates we're a dynamic object 495*7c478bd9Sstevel@tonic-gate # (this makes sure we don't check static executables). 496*7c478bd9Sstevel@tonic-gate $Dyn = 1; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate } elsif (($Header eq 'Ehdr') && ($Line =~ /e_type:/)) { 499*7c478bd9Sstevel@tonic-gate # The e_type field indicates whether this file is a 500*7c478bd9Sstevel@tonic-gate # shared object (ET_DYN) or an executable (ET_EXEC). 501*7c478bd9Sstevel@tonic-gate if ($Line =~ /ET_DYN/) { 502*7c478bd9Sstevel@tonic-gate $Dll = 1; 503*7c478bd9Sstevel@tonic-gate } elsif ($Line !~ /ET_EXEC/) { 504*7c478bd9Sstevel@tonic-gate return; 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate } elsif (($Header eq 'Ehdr') && ($Line =~ /ei_class:/)) { 507*7c478bd9Sstevel@tonic-gate # If we encounter a 64-bit object, but we're not running 508*7c478bd9Sstevel@tonic-gate # on a 64-bit system, suppress calling ldd(1). 509*7c478bd9Sstevel@tonic-gate if (($Line =~ /ELFCLASS64/) && !$Ena64) { 510*7c478bd9Sstevel@tonic-gate $SkipLdd = 1; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate } elsif (($Header eq 'Ehdr') && ($Line =~ /e_machine:/)) { 513*7c478bd9Sstevel@tonic-gate # If it's a X86 object, we need to enforce RW- data. 514*7c478bd9Sstevel@tonic-gate if (($Line =~ /(EM_AMD64|EM_386)/)) { 515*7c478bd9Sstevel@tonic-gate $IsX86 = 1; 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate } elsif (($Header eq 'Phdr') && 518*7c478bd9Sstevel@tonic-gate ($Line =~ /\[ PF_X PF_W PF_R \]/)) { 519*7c478bd9Sstevel@tonic-gate # RWX segment seen. 520*7c478bd9Sstevel@tonic-gate $RWX = 1; 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate } elsif (($Header eq 'Phdr') && 523*7c478bd9Sstevel@tonic-gate ($Line =~ /\[ PT_LOAD \]/ && $RWX && $IsX86)) { 524*7c478bd9Sstevel@tonic-gate # Seen an RWX PT_LOAD segment. 525*7c478bd9Sstevel@tonic-gate if ($File !~ $SkipNoExStkFiles) { 526*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 527*7c478bd9Sstevel@tonic-gate "\tapplication requires non-executable " . 528*7c478bd9Sstevel@tonic-gate "data\t<no -Mmapfile_noexdata?>"); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate } elsif (($Header eq 'Phdr') && 532*7c478bd9Sstevel@tonic-gate ($Line =~ /\[ PT_SUNWSTACK \]/)) { 533*7c478bd9Sstevel@tonic-gate # This object defines a non-executable stack. 534*7c478bd9Sstevel@tonic-gate $Stack = 1; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate } elsif (($Header eq 'Intp') && !$opt{a} && 537*7c478bd9Sstevel@tonic-gate ($Line =~ $SkipInterps)) { 538*7c478bd9Sstevel@tonic-gate # This object defines an interpretor we should skip. 539*7c478bd9Sstevel@tonic-gate $Interp = 0; 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate # Determine whether this ELF executable or shared object has a 544*7c478bd9Sstevel@tonic-gate # conforming mcs(1) comment section. If the correct $(POST_PROCESS) 545*7c478bd9Sstevel@tonic-gate # macros are used, only a 3 or 4 line .comment section should exist 546*7c478bd9Sstevel@tonic-gate # containing one or two "@(#)SunOS" identifying comments (one comment 547*7c478bd9Sstevel@tonic-gate # for a non-debug build, and two for a debug build). The results of 548*7c478bd9Sstevel@tonic-gate # the following split should be three or four lines, the last empty 549*7c478bd9Sstevel@tonic-gate # line being discarded by the split. 550*7c478bd9Sstevel@tonic-gate if ($opt{m}) { 551*7c478bd9Sstevel@tonic-gate my(@Mcs, $Con, $Dev); 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate @Mcs = split(/\n/, `mcs -p $FullPath 2>&1`); 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate $Con = $Dev = $Val = 0; 556*7c478bd9Sstevel@tonic-gate foreach my $Line (@Mcs) { 557*7c478bd9Sstevel@tonic-gate $Val++; 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate if (($Val == 3) && ($Line !~ /^@\(#\)SunOS/)) { 560*7c478bd9Sstevel@tonic-gate $Con = 1; 561*7c478bd9Sstevel@tonic-gate last; 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate if (($Val == 4) && ($Line =~ /^@\(#\)SunOS/)) { 564*7c478bd9Sstevel@tonic-gate $Dev = 1; 565*7c478bd9Sstevel@tonic-gate next; 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate if (($Dev == 0) && ($Val == 4)) { 568*7c478bd9Sstevel@tonic-gate $Con = 1; 569*7c478bd9Sstevel@tonic-gate last; 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate if (($Dev == 1) && ($Val == 5)) { 572*7c478bd9Sstevel@tonic-gate $Con = 1; 573*7c478bd9Sstevel@tonic-gate last; 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate if ($opt{m} && ($Con == 1)) { 577*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 578*7c478bd9Sstevel@tonic-gate "\tnon-conforming mcs(1) comment\t<no \$(POST_PROCESS)?>"); 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate # Applications should contain a non-executable stack definition. 583*7c478bd9Sstevel@tonic-gate if (($Dll == 0) && ($Stack == 0)) { 584*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 585*7c478bd9Sstevel@tonic-gate if ($File =~ $SkipNoExStkFiles) { 586*7c478bd9Sstevel@tonic-gate goto DYN; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 590*7c478bd9Sstevel@tonic-gate "\tapplication requires non-executable stack\t<no -Mmapfile_noexstk?>"); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gateDYN: 594*7c478bd9Sstevel@tonic-gate # Having caught any static executables in the mcs(1) check and non- 595*7c478bd9Sstevel@tonic-gate # executable stack definition check, continue with dynamic objects 596*7c478bd9Sstevel@tonic-gate # from now on. 597*7c478bd9Sstevel@tonic-gate if ($Dyn eq 0) { 598*7c478bd9Sstevel@tonic-gate return; 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate # Only use ldd unless we've encountered an interpreter that should 602*7c478bd9Sstevel@tonic-gate # ne skipped. 603*7c478bd9Sstevel@tonic-gate if (!$SkipLdd && $Interp) { 604*7c478bd9Sstevel@tonic-gate if ($Secure) { 605*7c478bd9Sstevel@tonic-gate # The execution of a secure application over an nfs file 606*7c478bd9Sstevel@tonic-gate # system mounted nosuid will result in warning messages 607*7c478bd9Sstevel@tonic-gate # being sent to /var/adm/messages. As this type of 608*7c478bd9Sstevel@tonic-gate # environment can occur with root builds, move the file 609*7c478bd9Sstevel@tonic-gate # being investigated to a safe place first. In addition 610*7c478bd9Sstevel@tonic-gate # remove its secure permission so that it can be 611*7c478bd9Sstevel@tonic-gate # influenced by any alternative dependency mappings. 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate my($TmpPath) = "$Tmpdir/$File"; 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate system('cp', $FullPath, $TmpPath); 616*7c478bd9Sstevel@tonic-gate chmod 0777, $TmpPath; 617*7c478bd9Sstevel@tonic-gate $FullPath = $TmpPath; 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate # Use ldd(1) to determine the objects relocatability and use. 621*7c478bd9Sstevel@tonic-gate # By default look for all unreferenced dependencies. However, 622*7c478bd9Sstevel@tonic-gate # some objects have legitimate dependencies that they do not 623*7c478bd9Sstevel@tonic-gate # reference. 624*7c478bd9Sstevel@tonic-gate if ($LddNoU || ($File =~ $UnusedFiles) || 625*7c478bd9Sstevel@tonic-gate ($RelPath =~ $UnusedPaths)) { 626*7c478bd9Sstevel@tonic-gate $Lddopt = "-ru"; 627*7c478bd9Sstevel@tonic-gate } else { 628*7c478bd9Sstevel@tonic-gate $Lddopt = "-rU"; 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate @Ldd = split(/\n/, `ldd $Lddopt $Env $FullPath 2>&1`); 631*7c478bd9Sstevel@tonic-gate if ($Secure) { 632*7c478bd9Sstevel@tonic-gate unlink $FullPath; 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate $Val = 0; 637*7c478bd9Sstevel@tonic-gate $Sym = 5; 638*7c478bd9Sstevel@tonic-gate $Uns = 1; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gateLDD: foreach my $Line (@Ldd) { 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate if ($Val == 0) { 643*7c478bd9Sstevel@tonic-gate $Val = 1; 644*7c478bd9Sstevel@tonic-gate # Make sure ldd(1) worked. One possible failure is that 645*7c478bd9Sstevel@tonic-gate # this is an old ldd(1) prior to -e addition (4390308). 646*7c478bd9Sstevel@tonic-gate if ($Line =~ /usage:/) { 647*7c478bd9Sstevel@tonic-gate $Line =~ s/$/\t<old ldd(1)?>/; 648*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, $Line); 649*7c478bd9Sstevel@tonic-gate last; 650*7c478bd9Sstevel@tonic-gate } elsif ($Line =~ /execution failed/) { 651*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, $Line); 652*7c478bd9Sstevel@tonic-gate last; 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate # It's possible this binary can't be executed, ie. we've 656*7c478bd9Sstevel@tonic-gate # found a sparc binary while running on an intel system, 657*7c478bd9Sstevel@tonic-gate # or a sparcv9 binary on a sparcv7/8 system. 658*7c478bd9Sstevel@tonic-gate if ($Line =~ /wrong class/) { 659*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 660*7c478bd9Sstevel@tonic-gate "\thas wrong class or data encoding"); 661*7c478bd9Sstevel@tonic-gate next; 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate # Historically, ldd(1) likes executable objects to have 665*7c478bd9Sstevel@tonic-gate # their execute bit set. Note that this test isn't 666*7c478bd9Sstevel@tonic-gate # applied unless the -a option is in effect, as any 667*7c478bd9Sstevel@tonic-gate # non-executable files are skipped by default to reduce 668*7c478bd9Sstevel@tonic-gate # the cost of running this script. 669*7c478bd9Sstevel@tonic-gate if ($Line =~ /not executable/) { 670*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 671*7c478bd9Sstevel@tonic-gate "\tis not executable"); 672*7c478bd9Sstevel@tonic-gate next; 673*7c478bd9Sstevel@tonic-gate } 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate # Look for "file" or "versions" that aren't found. Note that 677*7c478bd9Sstevel@tonic-gate # these lines will occur before we find any symbol referencing 678*7c478bd9Sstevel@tonic-gate # errors. 679*7c478bd9Sstevel@tonic-gate if (($Sym == 5) && ($Line =~ /not found\)/)) { 680*7c478bd9Sstevel@tonic-gate if ($Line =~ /file not found\)/) { 681*7c478bd9Sstevel@tonic-gate $Line =~ s/$/\t<no -zdefs?>/; 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, $Line); 684*7c478bd9Sstevel@tonic-gate next; 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate # Look for relocations whose symbols can't be found. Note, we 687*7c478bd9Sstevel@tonic-gate # only print out the first 5 relocations for any file as this 688*7c478bd9Sstevel@tonic-gate # output can be excessive. 689*7c478bd9Sstevel@tonic-gate if ($Sym && ($Line =~ /symbol not found/)) { 690*7c478bd9Sstevel@tonic-gate # Determine if this file is allowed undefined 691*7c478bd9Sstevel@tonic-gate # references. 692*7c478bd9Sstevel@tonic-gate if ($Sym == 5) { 693*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 694*7c478bd9Sstevel@tonic-gate if ($RelPath =~ $SkipUndefDirs) { 695*7c478bd9Sstevel@tonic-gate $Sym = 0; 696*7c478bd9Sstevel@tonic-gate next LDD; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate if ($File =~ $SkipUndefFiles) { 699*7c478bd9Sstevel@tonic-gate $Sym = 0; 700*7c478bd9Sstevel@tonic-gate next LDD; 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate if ($Sym-- == 1) { 705*7c478bd9Sstevel@tonic-gate if (!$opt{o}) { 706*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 707*7c478bd9Sstevel@tonic-gate "\tcontinued ..."); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate next; 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate # Just print the symbol name. 712*7c478bd9Sstevel@tonic-gate $Line =~ s/$/\t<no -zdefs?>/; 713*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, $Line); 714*7c478bd9Sstevel@tonic-gate next; 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate # Look for any unused dependencies. 717*7c478bd9Sstevel@tonic-gate if ($Uns && ($Line =~ /unused/)) { 718*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 719*7c478bd9Sstevel@tonic-gate if ($RelPath =~ $SkipUnusedDirs) { 720*7c478bd9Sstevel@tonic-gate $Uns = 0; 721*7c478bd9Sstevel@tonic-gate next LDD; 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate if ($File =~ $SkipUnusedFiles) { 724*7c478bd9Sstevel@tonic-gate $Uns = 0; 725*7c478bd9Sstevel@tonic-gate next LDD; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate # Remove any noise. 729*7c478bd9Sstevel@tonic-gate if ($Line =~ $UnusedNoise) { 730*7c478bd9Sstevel@tonic-gate $Uns = 0; 731*7c478bd9Sstevel@tonic-gate next LDD; 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate if ($Secure) { 735*7c478bd9Sstevel@tonic-gate $Line =~ s!$Tmpdir/!!; 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate $Line =~ s/^[ \t]*(.*)/\t$1\t<remove lib or -zignore?>/; 738*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, $Line); 739*7c478bd9Sstevel@tonic-gate next; 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate # Reuse the elfdump(1) data to investigate additional dynamic linking 744*7c478bd9Sstevel@tonic-gate # information. 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate $Sun = $Relsz = $Pltsz = $Dyn = $Stab = 0; 747*7c478bd9Sstevel@tonic-gate $Tex = $Strip = 1; 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate $Header = 'None'; 750*7c478bd9Sstevel@tonic-gateELF: foreach my $Line (@Elf) { 751*7c478bd9Sstevel@tonic-gate # We're only interested in the section headers and the dynamic 752*7c478bd9Sstevel@tonic-gate # section. 753*7c478bd9Sstevel@tonic-gate if ($Line =~ /^Section Header/) { 754*7c478bd9Sstevel@tonic-gate $Header = 'Shdr'; 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate if (($Sun == 0) && ($Line =~ /\.SUNW_reloc/)) { 757*7c478bd9Sstevel@tonic-gate # This object has a combined relocation section. 758*7c478bd9Sstevel@tonic-gate $Sun = 1; 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate } elsif (($Stab == 0) && ($Line =~ /\.stab/)) { 761*7c478bd9Sstevel@tonic-gate # This object contain .stabs sections 762*7c478bd9Sstevel@tonic-gate $Stab = 1; 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate if (($Strip == 1) && ($Line =~ /\.symtab/)) { 766*7c478bd9Sstevel@tonic-gate # This object contains a complete symbol table. 767*7c478bd9Sstevel@tonic-gate $Strip = 0; 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate next; 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate } elsif ($Line =~ /^Dynamic Section/) { 772*7c478bd9Sstevel@tonic-gate $Header = 'Dyn'; 773*7c478bd9Sstevel@tonic-gate next; 774*7c478bd9Sstevel@tonic-gate } elsif ($Header ne 'Dyn') { 775*7c478bd9Sstevel@tonic-gate next; 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate # Does this object contain text relocations. 779*7c478bd9Sstevel@tonic-gate if ($Tex && ($Line =~ /TEXTREL/)) { 780*7c478bd9Sstevel@tonic-gate # Determine if this file is allowed text relocations. 781*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 782*7c478bd9Sstevel@tonic-gate if ($File =~ $SkipTextrelFiles) { 783*7c478bd9Sstevel@tonic-gate $Tex = 0; 784*7c478bd9Sstevel@tonic-gate next ELF; 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate } 787*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 788*7c478bd9Sstevel@tonic-gate "\tTEXTREL .dynamic tag\t\t\t<no -Kpic?>"); 789*7c478bd9Sstevel@tonic-gate $Tex = 0; 790*7c478bd9Sstevel@tonic-gate next; 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate # Does this file have any relocation sections (there are a few 794*7c478bd9Sstevel@tonic-gate # psr libraries with no relocations at all, thus a .SUNW_reloc 795*7c478bd9Sstevel@tonic-gate # section won't exist either). 796*7c478bd9Sstevel@tonic-gate if (($Relsz == 0) && ($Line =~ / RELA?SZ/)) { 797*7c478bd9Sstevel@tonic-gate $Relsz = hex((split(' ', $Line))[2]); 798*7c478bd9Sstevel@tonic-gate next; 799*7c478bd9Sstevel@tonic-gate } 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate # Does this file have any plt relocations. If the plt size is 802*7c478bd9Sstevel@tonic-gate # equivalent to the total relocation size then we don't have 803*7c478bd9Sstevel@tonic-gate # any relocations suitable for combining into a .SUNW_reloc 804*7c478bd9Sstevel@tonic-gate # section. 805*7c478bd9Sstevel@tonic-gate if (($Pltsz == 0) && ($Line =~ / PLTRELSZ/)) { 806*7c478bd9Sstevel@tonic-gate $Pltsz = hex((split(' ', $Line))[2]); 807*7c478bd9Sstevel@tonic-gate next; 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate # Under the -i (information) option print out any useful dynamic 811*7c478bd9Sstevel@tonic-gate # entries. 812*7c478bd9Sstevel@tonic-gate # Does this object have any dependencies. 813*7c478bd9Sstevel@tonic-gate if ($opt{i} && ($Line =~ /NEEDED/)) { 814*7c478bd9Sstevel@tonic-gate my($Need) = (split(' ', $Line))[3]; 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate # Catch any old (unnecessary) dependencies. 817*7c478bd9Sstevel@tonic-gate if ($Need =~ $OldDeps) { 818*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 819*7c478bd9Sstevel@tonic-gate "\tNEEDED=$Need\t<dependency no longer necessary>"); 820*7c478bd9Sstevel@tonic-gate } else { 821*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, "\tNEEDED=$Need"); 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate next; 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate # Does this object specify a runpath. 827*7c478bd9Sstevel@tonic-gate if ($opt{i} && ($Line =~ /RPATH/)) { 828*7c478bd9Sstevel@tonic-gate my($Rpath) = (split(' ', $Line))[3]; 829*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, "\tRPATH=$Rpath"); 830*7c478bd9Sstevel@tonic-gate next; 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate # A shared object, that contains non-plt relocations, should have a 835*7c478bd9Sstevel@tonic-gate # combined relocation section indicating it was built with -z combreloc. 836*7c478bd9Sstevel@tonic-gate if ($Dll && $Relsz && ($Relsz != $Pltsz) && ($Sun == 0)) { 837*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 838*7c478bd9Sstevel@tonic-gate "\tSUNW_reloc section missing\t\t<no -zcombreloc?>"); 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate # No objects released to a customer should have any .stabs sections 842*7c478bd9Sstevel@tonic-gate # remaining, they should be stripped. 843*7c478bd9Sstevel@tonic-gate if ($opt{s} && $Stab) { 844*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 845*7c478bd9Sstevel@tonic-gate if ($File =~ $SkipStabFiles) { 846*7c478bd9Sstevel@tonic-gate goto DONESTAB; 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 850*7c478bd9Sstevel@tonic-gate "\tdebugging sections should be deleted\t<no -s or strip -x?>"); 851*7c478bd9Sstevel@tonic-gate } 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gateDONESTAB: 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate # Shared objects should have a full symbol table to provide complete 856*7c478bd9Sstevel@tonic-gate # debugging stack traces. 857*7c478bd9Sstevel@tonic-gate if ($opt{s} && $Dll && $Strip) { 858*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 859*7c478bd9Sstevel@tonic-gate if ($RelPath =~ $SkipStripDirs) { 860*7c478bd9Sstevel@tonic-gate goto DONESTRIP; 861*7c478bd9Sstevel@tonic-gate } 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 864*7c478bd9Sstevel@tonic-gate "\tsymbol table should not be stripped\t<remove -s?>"); 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate # No other dynamic object should have a .symtab symbol table. 868*7c478bd9Sstevel@tonic-gate if ($opt{s} && ($Dll == 0) && ($Strip == 0)) { 869*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 870*7c478bd9Sstevel@tonic-gate if ($File =~ $SkipNoStripFiles) { 871*7c478bd9Sstevel@tonic-gate goto DONESTRIP; 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate OutMsg($Ttl++, $RelPath, 875*7c478bd9Sstevel@tonic-gate "\tsymbol table should be stripped\t<no -s?>"); 876*7c478bd9Sstevel@tonic-gate } 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gateDONESTRIP: 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate} 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gatesub ProcDir { 884*7c478bd9Sstevel@tonic-gate my($FullDir, $RelDir) = @_; 885*7c478bd9Sstevel@tonic-gate my($NewFull, $NewRel); 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate # Determine if this is a directory we don't care about. 888*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 889*7c478bd9Sstevel@tonic-gate if ($RelDir =~ $SkipDirs) { 890*7c478bd9Sstevel@tonic-gate return; 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate # Open the directory and read each entry, omit files starting with "." 895*7c478bd9Sstevel@tonic-gate if (opendir(DIR, $FullDir)) { 896*7c478bd9Sstevel@tonic-gate foreach my $Entry (readdir(DIR)) { 897*7c478bd9Sstevel@tonic-gate if ($Entry =~ /^\./) { 898*7c478bd9Sstevel@tonic-gate next; 899*7c478bd9Sstevel@tonic-gate } 900*7c478bd9Sstevel@tonic-gate $NewFull = "$FullDir/$Entry"; 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate # Ignore symlinks. 903*7c478bd9Sstevel@tonic-gate if (-l $NewFull) { 904*7c478bd9Sstevel@tonic-gate next; 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate if (!stat($NewFull)) { 907*7c478bd9Sstevel@tonic-gate next; 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate $NewRel = "$RelDir/$Entry"; 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate # Descend into and process any directories. 912*7c478bd9Sstevel@tonic-gate if (-d _) { 913*7c478bd9Sstevel@tonic-gate ProcDir($NewFull, $NewRel); 914*7c478bd9Sstevel@tonic-gate next; 915*7c478bd9Sstevel@tonic-gate } 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate # Typically dynamic objects are executable, so we can 918*7c478bd9Sstevel@tonic-gate # reduce the overall cost of this script (a lot!) by 919*7c478bd9Sstevel@tonic-gate # screening out non-executables here, rather than pass 920*7c478bd9Sstevel@tonic-gate # them to file(1) later. However, it has been known 921*7c478bd9Sstevel@tonic-gate # for shared objects to be mistakenly left non- 922*7c478bd9Sstevel@tonic-gate # executable, so with -a let all files through so that 923*7c478bd9Sstevel@tonic-gate # this requirement can be verified (see ProcFile()). 924*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 925*7c478bd9Sstevel@tonic-gate if (! -x _) { 926*7c478bd9Sstevel@tonic-gate next; 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate } 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate # Process any standard files. 931*7c478bd9Sstevel@tonic-gate if (-f _) { 932*7c478bd9Sstevel@tonic-gate my($Secure) = 0; 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate if (-u _ || -g _) { 935*7c478bd9Sstevel@tonic-gate $Secure = 1; 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate ProcFile($NewFull, $NewRel, $Entry, $Secure); 939*7c478bd9Sstevel@tonic-gate next; 940*7c478bd9Sstevel@tonic-gate } 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate closedir(DIR); 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate} 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate# Create a crle(1) script for any 64-bit dependencies we locate. A runtime 948*7c478bd9Sstevel@tonic-gate# configuration file will be generated to establish alternative dependency 949*7c478bd9Sstevel@tonic-gate# mappings for all these dependencies. 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gatesub Entercrle64 { 952*7c478bd9Sstevel@tonic-gate my($FullDir, $RelDir, $Entry) = @_; 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate if (!$Crle64) { 955*7c478bd9Sstevel@tonic-gate # Create and initialize the script if is doesn't already exit. 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate $Crle64 = "$Tmpdir/$Prog.crle64.$$"; 958*7c478bd9Sstevel@tonic-gate open(CRLE64, "> $Crle64") || 959*7c478bd9Sstevel@tonic-gate die "$Prog: open failed: $Crle64: $!"; 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate print CRLE64 "#!/bin/sh\ncrle -64\\\n"; 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate print CRLE64 "\t-o $FullDir -a $RelDir/$Entry \\\n"; 964*7c478bd9Sstevel@tonic-gate} 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate# Create a crle(1) script for any 32-bit dependencies we locate. A runtime 967*7c478bd9Sstevel@tonic-gate# configuration file will be generated to establish alternative dependency 968*7c478bd9Sstevel@tonic-gate# mappings for all these dependencies. 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gatesub Entercrle32 { 971*7c478bd9Sstevel@tonic-gate my($FullDir, $RelDir, $Entry) = @_; 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if (!$Crle32) { 974*7c478bd9Sstevel@tonic-gate # Create and initialize the script if is doesn't already exit. 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate $Crle32 = "$Tmpdir/$Prog.crle32.$$"; 977*7c478bd9Sstevel@tonic-gate open(CRLE32, "> $Crle32") || 978*7c478bd9Sstevel@tonic-gate die "$Prog: open failed: $Crle32: $!"; 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate print CRLE32 "#!/bin/sh\ncrle \\\n"; 981*7c478bd9Sstevel@tonic-gate } 982*7c478bd9Sstevel@tonic-gate print CRLE32 "\t-o $FullDir -a $RelDir/$Entry \\\n"; 983*7c478bd9Sstevel@tonic-gate} 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate# Having finished gathering dependencies, complete any crle(1) scripts and 986*7c478bd9Sstevel@tonic-gate# execute them to generate the associated runtime configuration files. In 987*7c478bd9Sstevel@tonic-gate# addition establish the environment variable required to pass the configuration 988*7c478bd9Sstevel@tonic-gate# files to ldd(1). 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gatesub GenConf { 991*7c478bd9Sstevel@tonic-gate if ($Crle64) { 992*7c478bd9Sstevel@tonic-gate $Conf64 = "$Tmpdir/$Prog.conf64.$$"; 993*7c478bd9Sstevel@tonic-gate print CRLE64 "\t-c $Conf64\n"; 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate chmod 0755, $Crle64; 996*7c478bd9Sstevel@tonic-gate close CRLE64; 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate if (system($Crle64)) { 999*7c478bd9Sstevel@tonic-gate undef $Conf64; 1000*7c478bd9Sstevel@tonic-gate } 1001*7c478bd9Sstevel@tonic-gate } 1002*7c478bd9Sstevel@tonic-gate if ($Crle32) { 1003*7c478bd9Sstevel@tonic-gate $Conf32 = "$Tmpdir/$Prog.conf32.$$"; 1004*7c478bd9Sstevel@tonic-gate print CRLE32 "\t-c $Conf32\n"; 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate chmod 0755, $Crle32; 1007*7c478bd9Sstevel@tonic-gate close CRLE32; 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate if (system($Crle32)) { 1010*7c478bd9Sstevel@tonic-gate undef $Conf32; 1011*7c478bd9Sstevel@tonic-gate } 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate if ($Crle64 && $Conf64 && $Crle32 && $Conf32) { 1015*7c478bd9Sstevel@tonic-gate $Env = "-e LD_FLAGS=config_64=$Conf64,config_32=$Conf32"; 1016*7c478bd9Sstevel@tonic-gate } elsif ($Crle64 && $Conf64) { 1017*7c478bd9Sstevel@tonic-gate $Env = "-e LD_FLAGS=config_64=$Conf64"; 1018*7c478bd9Sstevel@tonic-gate } elsif ($Crle32 && $Conf32) { 1019*7c478bd9Sstevel@tonic-gate $Env = "-e LD_FLAGS=config_32=$Conf32"; 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate} 1022*7c478bd9Sstevel@tonic-gate 1023*7c478bd9Sstevel@tonic-gate# Recurse through a directory hierarchy looking for appropriate dependencies. 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gatesub GetDeps { 1026*7c478bd9Sstevel@tonic-gate my($FullDir, $RelDir) = @_; 1027*7c478bd9Sstevel@tonic-gate my($NewFull); 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate # Open the directory and read each entry, omit files starting with "." 1030*7c478bd9Sstevel@tonic-gate if (opendir(DIR, $FullDir)) { 1031*7c478bd9Sstevel@tonic-gate foreach my $Entry (readdir(DIR)) { 1032*7c478bd9Sstevel@tonic-gate if ($Entry =~ /^\./) { 1033*7c478bd9Sstevel@tonic-gate next; 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate $NewFull = "$FullDir/$Entry"; 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate # We need to follow links so that any dependencies 1038*7c478bd9Sstevel@tonic-gate # are expressed in all their available forms. 1039*7c478bd9Sstevel@tonic-gate # Bail on symlinks like 32 -> . 1040*7c478bd9Sstevel@tonic-gate if (-l $NewFull) { 1041*7c478bd9Sstevel@tonic-gate if (readlink($NewFull) =~ /^\.$/) { 1042*7c478bd9Sstevel@tonic-gate next; 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate if (!stat($NewFull)) { 1046*7c478bd9Sstevel@tonic-gate next; 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate # If this is a directory descend into it. 1050*7c478bd9Sstevel@tonic-gate if (-d _) { 1051*7c478bd9Sstevel@tonic-gate my($NewRel); 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate if ($RelDir =~ /^\/$/) { 1054*7c478bd9Sstevel@tonic-gate $NewRel = "$RelDir$Entry"; 1055*7c478bd9Sstevel@tonic-gate } else { 1056*7c478bd9Sstevel@tonic-gate $NewRel = "$RelDir/$Entry"; 1057*7c478bd9Sstevel@tonic-gate } 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate GetDeps($NewFull, $NewRel); 1060*7c478bd9Sstevel@tonic-gate next; 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate # If this is a regular file determine if its a 1064*7c478bd9Sstevel@tonic-gate # valid ELF dependency. 1065*7c478bd9Sstevel@tonic-gate if (-f _) { 1066*7c478bd9Sstevel@tonic-gate my($File); 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate # Typically shared object dependencies end with 1069*7c478bd9Sstevel@tonic-gate # ".so" or ".so.?", hence we can reduce the cost 1070*7c478bd9Sstevel@tonic-gate # of this script (a lot!) by screening out files 1071*7c478bd9Sstevel@tonic-gate # that don't follow this pattern. 1072*7c478bd9Sstevel@tonic-gate if (!$opt{a}) { 1073*7c478bd9Sstevel@tonic-gate if ($Entry !~ /\.so(?:\.\d+)*$/) { 1074*7c478bd9Sstevel@tonic-gate next; 1075*7c478bd9Sstevel@tonic-gate } 1076*7c478bd9Sstevel@tonic-gate } 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate $File = `file $NewFull`; 1079*7c478bd9Sstevel@tonic-gate if ($File !~ /dynamic lib/) { 1080*7c478bd9Sstevel@tonic-gate next; 1081*7c478bd9Sstevel@tonic-gate } 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate if ($File =~ /32-bit/) { 1084*7c478bd9Sstevel@tonic-gate Entercrle32($FullDir, $RelDir, $Entry); 1085*7c478bd9Sstevel@tonic-gate } elsif ($Ena64) { 1086*7c478bd9Sstevel@tonic-gate Entercrle64($FullDir, $RelDir, $Entry); 1087*7c478bd9Sstevel@tonic-gate } 1088*7c478bd9Sstevel@tonic-gate next; 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate closedir(DIR); 1092*7c478bd9Sstevel@tonic-gate } 1093*7c478bd9Sstevel@tonic-gate} 1094*7c478bd9Sstevel@tonic-gateexit $Error 1095