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# Link Analysis of Runtime Interfaces. 30*7c478bd9Sstevel@tonic-gate# 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate# Define all global variables (required for strict) 33*7c478bd9Sstevel@tonic-gateuse vars qw($Prog $DestDir $ObjRef $ObjFlag $ObjSize $TmpDir $LddArgs); 34*7c478bd9Sstevel@tonic-gateuse vars qw($Glob $Intp $Cpyr $Prot $Extn $Self $Filt $Dirc $Plta $User $Func); 35*7c478bd9Sstevel@tonic-gateuse vars qw($Objt $UndefSym $IgnSyms $Rtld $MultSyms $CrtSyms $GlobWeak); 36*7c478bd9Sstevel@tonic-gateuse vars qw($DbgSeed %opt %Symbols %Objects %Versioned %DemSyms); 37*7c478bd9Sstevel@tonic-gateuse vars qw($Platform $Nodi $Osft $Oaft $Ssft $Saft $Msft); 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gateuse strict; 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gateuse Getopt::Std; 42*7c478bd9Sstevel@tonic-gateuse File::Basename; 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate# Pattern match to skip objects. 45*7c478bd9Sstevel@tonic-gate$Rtld = qr{ ^(?: 46*7c478bd9Sstevel@tonic-gate /lib/ld\.so\.1 | 47*7c478bd9Sstevel@tonic-gate /usr/lib/ld\.so\.1 | 48*7c478bd9Sstevel@tonic-gate /lib/sparcv9/ld\.so\.1 | 49*7c478bd9Sstevel@tonic-gate /usr/lib/sparcv9/ld\.so\.1 50*7c478bd9Sstevel@tonic-gate )$ 51*7c478bd9Sstevel@tonic-gate}x; 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate# Pattern matching required to determine a global symbol. 54*7c478bd9Sstevel@tonic-gate$GlobWeak = qr{ ^(?: 55*7c478bd9Sstevel@tonic-gate GLOB | 56*7c478bd9Sstevel@tonic-gate WEAK 57*7c478bd9Sstevel@tonic-gate )$ 58*7c478bd9Sstevel@tonic-gate}x; 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate# Pattern matching to determine link-editor specific symbols and those common 61*7c478bd9Sstevel@tonic-gate# to the compilation environment (ie. provided by all crt's). 62*7c478bd9Sstevel@tonic-gate$MultSyms = qr{ ^(?: 63*7c478bd9Sstevel@tonic-gate _DYNAMIC | 64*7c478bd9Sstevel@tonic-gate _GLOBAL_OFFSET_TABLE_ | 65*7c478bd9Sstevel@tonic-gate _PROCEDURE_LINKAGE_TABLE_ | 66*7c478bd9Sstevel@tonic-gate _etext | 67*7c478bd9Sstevel@tonic-gate _edata | 68*7c478bd9Sstevel@tonic-gate _end | 69*7c478bd9Sstevel@tonic-gate _init | 70*7c478bd9Sstevel@tonic-gate _fini | 71*7c478bd9Sstevel@tonic-gate _lib_version | # Defined in values 72*7c478bd9Sstevel@tonic-gate __xpg4 | # Defined in values 73*7c478bd9Sstevel@tonic-gate __xpg6 # Defined in values 74*7c478bd9Sstevel@tonic-gate )$ 75*7c478bd9Sstevel@tonic-gate}x; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate$CrtSyms = qr{ ^(?: 78*7c478bd9Sstevel@tonic-gate ___Argv | # Defined in crt 79*7c478bd9Sstevel@tonic-gate __environ_lock | # Defined in crt 80*7c478bd9Sstevel@tonic-gate _environ | # Defined in crt 81*7c478bd9Sstevel@tonic-gate environ # Defined in crt 82*7c478bd9Sstevel@tonic-gate )$ 83*7c478bd9Sstevel@tonic-gate}x; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate# Pattern match to remove undefined, NOTY and versioning symbols. 86*7c478bd9Sstevel@tonic-gate$UndefSym = qr{ ^(?: 87*7c478bd9Sstevel@tonic-gate UNDEF 88*7c478bd9Sstevel@tonic-gate )$ 89*7c478bd9Sstevel@tonic-gate}x; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate$IgnSyms = qr{ ^(?: 92*7c478bd9Sstevel@tonic-gate NOTY | 93*7c478bd9Sstevel@tonic-gate ABS 94*7c478bd9Sstevel@tonic-gate )$ 95*7c478bd9Sstevel@tonic-gate}x; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate# Symbol flags. 98*7c478bd9Sstevel@tonic-gate$Glob = 0x00001; # symbol is global 99*7c478bd9Sstevel@tonic-gate$Intp = 0x00010; # symbol originates for explicit interposer 100*7c478bd9Sstevel@tonic-gate$Dirc = 0x00020; # symbol bound to directly 101*7c478bd9Sstevel@tonic-gate$Cpyr = 0x00040; # symbol bound to copy-relocation reference 102*7c478bd9Sstevel@tonic-gate$Prot = 0x00080; # symbol is protected (symbolic) 103*7c478bd9Sstevel@tonic-gate$Extn = 0x00100; # symbol has been bound to from an external reference 104*7c478bd9Sstevel@tonic-gate$Self = 0x00200; # symbol has been bound to from the same object 105*7c478bd9Sstevel@tonic-gate$Filt = 0x00400; # symbol bound to a filtee 106*7c478bd9Sstevel@tonic-gate$Plta = 0x00800; # symbol bound to executables plt address 107*7c478bd9Sstevel@tonic-gate$User = 0x01000; # symbol binding originates from user (dlsym) request 108*7c478bd9Sstevel@tonic-gate$Func = 0x02000; # symbol is of type function 109*7c478bd9Sstevel@tonic-gate$Objt = 0x04000; # symbol is of type object 110*7c478bd9Sstevel@tonic-gate$Nodi = 0x08000; # symbol prohibits direct binding 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate$Osft = 0x10000; # symbol is an standard object filter 113*7c478bd9Sstevel@tonic-gate$Oaft = 0x20000; # symbol is an auxiliary object filter 114*7c478bd9Sstevel@tonic-gate$Ssft = 0x40000; # symbol is a per-symbol standard filter 115*7c478bd9Sstevel@tonic-gate$Saft = 0x80000; # symbol is a per-symbol auxilary filter 116*7c478bd9Sstevel@tonic-gate$Msft = 0xf0000; # filter mask 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate# Offsets into $Symbols{$SymName}{$Obj} array. 119*7c478bd9Sstevel@tonic-gate$ObjRef = 0; 120*7c478bd9Sstevel@tonic-gate$ObjFlag = 1; 121*7c478bd9Sstevel@tonic-gate$ObjSize = 2; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate# Establish locale 125*7c478bd9Sstevel@tonic-gateuse POSIX qw(locale_h); 126*7c478bd9Sstevel@tonic-gateuse Sun::Solaris::Utils qw(textdomain gettext); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gatesetlocale(LC_ALL, ""); 129*7c478bd9Sstevel@tonic-gatetextdomain("SUNW_OST_SGS"); 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate# Establish a program name for any error diagnostics. 132*7c478bd9Sstevel@tonic-gate$Prog = basename($0); 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gatesub inappropriate { 135*7c478bd9Sstevel@tonic-gate my ($Opt1, $Opt2, $Flag) = @_; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate if ($Flag) { 138*7c478bd9Sstevel@tonic-gate printf STDERR 139*7c478bd9Sstevel@tonic-gate gettext("%s: inappropriate use of %s with %s: %s ignored\n"), 140*7c478bd9Sstevel@tonic-gate $Prog, $Opt1, $Opt2, $Opt1; 141*7c478bd9Sstevel@tonic-gate } else { 142*7c478bd9Sstevel@tonic-gate printf STDERR 143*7c478bd9Sstevel@tonic-gate gettext("%s: inappropriate use of %s without %s: %s ignored\n"), 144*7c478bd9Sstevel@tonic-gate $Prog, $Opt1, $Opt2, $Opt1; 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate} 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate# Cleanup any temporary files on interruption 149*7c478bd9Sstevel@tonic-gatesub Cleanup { 150*7c478bd9Sstevel@tonic-gate my ($Sig) = @_; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate $SIG{$Sig} = 'IGNORE'; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate if ($DbgSeed ne "") { 155*7c478bd9Sstevel@tonic-gate foreach my $File (<\Q${DbgSeed}\E.*>) { 156*7c478bd9Sstevel@tonic-gate if ($File =~ /^\Q$DbgSeed\E\.\d+$/) { 157*7c478bd9Sstevel@tonic-gate unlink($File); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate exit 1; 162*7c478bd9Sstevel@tonic-gate} 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate# Check that we have arguments. 165*7c478bd9Sstevel@tonic-gateif ((getopts('abCDd:imosv', \%opt) == 0) || ($#ARGV < 0)) { 166*7c478bd9Sstevel@tonic-gate printf STDERR gettext("usage:\n"); 167*7c478bd9Sstevel@tonic-gate printf STDERR 168*7c478bd9Sstevel@tonic-gate gettext(" %s [-bCDsv] [-a | -i | -o ] file | dir ...\n"), $Prog; 169*7c478bd9Sstevel@tonic-gate printf STDERR 170*7c478bd9Sstevel@tonic-gate gettext(" %s [-CDosv] [-m [-d mapdir]] file\n"), $Prog; 171*7c478bd9Sstevel@tonic-gate print STDERR 172*7c478bd9Sstevel@tonic-gate gettext("\t[-a] print diagnostics for all symbols\n"); 173*7c478bd9Sstevel@tonic-gate print STDERR 174*7c478bd9Sstevel@tonic-gate gettext("\t[-b] print diagnostics for multiple-bound " . 175*7c478bd9Sstevel@tonic-gate "symbols\n"); 176*7c478bd9Sstevel@tonic-gate print STDERR 177*7c478bd9Sstevel@tonic-gate gettext("\t[-C] print demangled symbol names also\n"); 178*7c478bd9Sstevel@tonic-gate print STDERR 179*7c478bd9Sstevel@tonic-gate gettext("\t[-D] read debugging information from \"file\"\n"); 180*7c478bd9Sstevel@tonic-gate print STDERR 181*7c478bd9Sstevel@tonic-gate gettext("\t[-d dir] create mapfiles in \"mapdir\"\n"); 182*7c478bd9Sstevel@tonic-gate print STDERR 183*7c478bd9Sstevel@tonic-gate gettext("\t[-i] print interesting information (default)\n"); 184*7c478bd9Sstevel@tonic-gate print STDERR 185*7c478bd9Sstevel@tonic-gate gettext("\t[-m] create mapfiles for interface requirements\n"); 186*7c478bd9Sstevel@tonic-gate print STDERR 187*7c478bd9Sstevel@tonic-gate gettext("\t[-o] print overhead information\n"); 188*7c478bd9Sstevel@tonic-gate print STDERR 189*7c478bd9Sstevel@tonic-gate gettext("\t[-s] save bindings information created by ldd(1)\n"); 190*7c478bd9Sstevel@tonic-gate print STDERR 191*7c478bd9Sstevel@tonic-gate gettext("\t[-v] ignore versioned objects\n"); 192*7c478bd9Sstevel@tonic-gate exit 1; 193*7c478bd9Sstevel@tonic-gate} else { 194*7c478bd9Sstevel@tonic-gate my ($Mult, $Error); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate # Catch any incompatible argument usage. 197*7c478bd9Sstevel@tonic-gate if ($opt{m}) { 198*7c478bd9Sstevel@tonic-gate if ($opt{a}) { 199*7c478bd9Sstevel@tonic-gate inappropriate("-a", "-m", 1); 200*7c478bd9Sstevel@tonic-gate $opt{a} = 0; 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate if ($opt{i}) { 203*7c478bd9Sstevel@tonic-gate inappropriate("-i", "-m", 1); 204*7c478bd9Sstevel@tonic-gate $opt{i} = 0; 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate } else { 207*7c478bd9Sstevel@tonic-gate if ($opt{d}) { 208*7c478bd9Sstevel@tonic-gate inappropriate("-d", "-m", 0); 209*7c478bd9Sstevel@tonic-gate $opt{d} = 0; 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate if ($opt{a}) { 213*7c478bd9Sstevel@tonic-gate if ($opt{o}) { 214*7c478bd9Sstevel@tonic-gate inappropriate("-a", "-o", 1); 215*7c478bd9Sstevel@tonic-gate $opt{o} = 0; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate if ($opt{i}) { 218*7c478bd9Sstevel@tonic-gate inappropriate("-a", "-i", 1); 219*7c478bd9Sstevel@tonic-gate $opt{i} = 0; 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate if ($opt{o} && $opt{i}) { 223*7c478bd9Sstevel@tonic-gate inappropriate("-o", "-i", 1); 224*7c478bd9Sstevel@tonic-gate $opt{i} = 0; 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate # If -m is used, only one input file is applicable. 228*7c478bd9Sstevel@tonic-gate if ($opt{m} && ($#ARGV != 0)) { 229*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: only one input file is allowed " . 230*7c478bd9Sstevel@tonic-gate "with the -m option\n"), $Prog; 231*7c478bd9Sstevel@tonic-gate exit 1; 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate # Insure any specified directory exists, or apply a default. 235*7c478bd9Sstevel@tonic-gate if ($opt{d}) { 236*7c478bd9Sstevel@tonic-gate # User specified directory - make sure it exists. 237*7c478bd9Sstevel@tonic-gate if (! -d $opt{d}) { 238*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s is not a directory\n"), 239*7c478bd9Sstevel@tonic-gate $Prog, $opt{d}; 240*7c478bd9Sstevel@tonic-gate exit 1; 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate $DestDir = $opt{d}; 243*7c478bd9Sstevel@tonic-gate } else { 244*7c478bd9Sstevel@tonic-gate $DestDir = "."; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate # Establish a temporary directory if necessary. 248*7c478bd9Sstevel@tonic-gate if (!$opt{D}) { 249*7c478bd9Sstevel@tonic-gate if (!($TmpDir = $ENV{TMPDIR}) || (! -d $TmpDir)) { 250*7c478bd9Sstevel@tonic-gate $TmpDir = "/tmp"; 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate # Establish any initial ldd(1) argument requirements. 255*7c478bd9Sstevel@tonic-gate if ($LddArgs = $ENV{LARI_LDD_ARGS}) { 256*7c478bd9Sstevel@tonic-gate $LddArgs = $LddArgs . ' -r -e LD_DEBUG=bindings,files,detail'; 257*7c478bd9Sstevel@tonic-gate } else { 258*7c478bd9Sstevel@tonic-gate $LddArgs = '-r -e LD_DEBUG=bindings,files,detail'; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate # If we've been asked to demangle symbols, make sure we can find the 262*7c478bd9Sstevel@tonic-gate # demangler. 263*7c478bd9Sstevel@tonic-gate if ($opt{C}) { 264*7c478bd9Sstevel@tonic-gate my ($DemName) = `dem XXXX 2> /dev/null`; 265*7c478bd9Sstevel@tonic-gate if (!$DemName) { 266*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: can not locate demangler: " . 267*7c478bd9Sstevel@tonic-gate "-C ignored\n"), $Prog; 268*7c478bd9Sstevel@tonic-gate $opt{C} = 0; 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate # If -a or -o hasn't been specified, default to -i. 273*7c478bd9Sstevel@tonic-gate if (!$opt{a} && !$opt{o}) { 274*7c478bd9Sstevel@tonic-gate $opt{i} = 1; 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate # Determine whether we have a multiple input files. 278*7c478bd9Sstevel@tonic-gate if ($#ARGV == 0) { 279*7c478bd9Sstevel@tonic-gate $Mult = 0; 280*7c478bd9Sstevel@tonic-gate } else { 281*7c478bd9Sstevel@tonic-gate $Mult = 1; 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate # Determine what platform we're running on - some inappropriate 285*7c478bd9Sstevel@tonic-gate # platform specific dependencies are better skipped. 286*7c478bd9Sstevel@tonic-gate chomp($Platform = `uname -i`); 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate # Establish signal handlers 289*7c478bd9Sstevel@tonic-gate $SIG{INT} = \&Cleanup; 290*7c478bd9Sstevel@tonic-gate $SIG{QUIT} = \&Cleanup; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate $DbgSeed = ""; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate # For each argument determine if we're dealing with a file or directory. 295*7c478bd9Sstevel@tonic-gate $Error = 0; 296*7c478bd9Sstevel@tonic-gate foreach my $Arg (@ARGV) { 297*7c478bd9Sstevel@tonic-gate if (!stat($Arg)) { 298*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: unable to stat file\n"), 299*7c478bd9Sstevel@tonic-gate $Prog, $Arg; 300*7c478bd9Sstevel@tonic-gate $Error = 1; 301*7c478bd9Sstevel@tonic-gate next; 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate # Process simple files. 305*7c478bd9Sstevel@tonic-gate if (-f _) { 306*7c478bd9Sstevel@tonic-gate if (!-r _) { 307*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: unable to " . 308*7c478bd9Sstevel@tonic-gate "read file\n"), $Prog, $Arg; 309*7c478bd9Sstevel@tonic-gate $Error = 1; 310*7c478bd9Sstevel@tonic-gate next; 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate if (!$opt{D}) { 313*7c478bd9Sstevel@tonic-gate if (ProcFile($Arg, $Mult, 1) == 0) { 314*7c478bd9Sstevel@tonic-gate $Error = 1; 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate } else { 317*7c478bd9Sstevel@tonic-gate # If the -D option is specified, read the 318*7c478bd9Sstevel@tonic-gate # bindings debugging information from the 319*7c478bd9Sstevel@tonic-gate # specified file. 320*7c478bd9Sstevel@tonic-gate if ($Mult) { 321*7c478bd9Sstevel@tonic-gate print STDOUT "$Arg:\n"; 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate ProcBindings($Arg, $Mult, $Arg); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate next; 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate # Process directories. 329*7c478bd9Sstevel@tonic-gate if (-d _) { 330*7c478bd9Sstevel@tonic-gate ProcDir($Arg); 331*7c478bd9Sstevel@tonic-gate next; 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: is not a file or directory\n"), 335*7c478bd9Sstevel@tonic-gate $Prog, $Arg; 336*7c478bd9Sstevel@tonic-gate $Error = 1; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate exit $Error; 339*7c478bd9Sstevel@tonic-gate} 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gatesub ProcDir { 342*7c478bd9Sstevel@tonic-gate my ($Dir) = @_; 343*7c478bd9Sstevel@tonic-gate my ($File); 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate # Open the directory and read each entry, omit "." and "..". Sorting 346*7c478bd9Sstevel@tonic-gate # the directory listing makes analyzing different source hierarchies 347*7c478bd9Sstevel@tonic-gate # easier. 348*7c478bd9Sstevel@tonic-gate if (opendir(DIR, $Dir)) { 349*7c478bd9Sstevel@tonic-gate foreach my $Entry (sort(readdir(DIR))) { 350*7c478bd9Sstevel@tonic-gate if (($Entry eq '.') || ($Entry eq '..')) { 351*7c478bd9Sstevel@tonic-gate next; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate # If we're decending into a platform directory, ignore 355*7c478bd9Sstevel@tonic-gate # any inappropriate platform specific files. These 356*7c478bd9Sstevel@tonic-gate # files can have dependencies that in turn bring in the 357*7c478bd9Sstevel@tonic-gate # appropriate platform specific file, resulting in more 358*7c478bd9Sstevel@tonic-gate # than one dependency offering the same interfaces. In 359*7c478bd9Sstevel@tonic-gate # practice, the non-appropriate platform specific file 360*7c478bd9Sstevel@tonic-gate # wouldn't be loaded with a process. 361*7c478bd9Sstevel@tonic-gate if (($Dir =~ /\/platform$/) && 362*7c478bd9Sstevel@tonic-gate ($Entry !~ /^$Platform$/)) { 363*7c478bd9Sstevel@tonic-gate next; 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate $File = "$Dir/$Entry"; 367*7c478bd9Sstevel@tonic-gate if (!lstat($File)) { 368*7c478bd9Sstevel@tonic-gate next; 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate # Ignore symlinks. 371*7c478bd9Sstevel@tonic-gate if (-l _) { 372*7c478bd9Sstevel@tonic-gate next; 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate # Descend into, and process any directories. 376*7c478bd9Sstevel@tonic-gate if (-d _) { 377*7c478bd9Sstevel@tonic-gate ProcDir($File); 378*7c478bd9Sstevel@tonic-gate next; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate # Process any standard files. 382*7c478bd9Sstevel@tonic-gate if (-f _ && -r _) { 383*7c478bd9Sstevel@tonic-gate ProcFile($File, 1, 0); 384*7c478bd9Sstevel@tonic-gate next; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate closedir(DIR); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate} 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate# Process a file. If the file was explicitly defined on the command-line, and 393*7c478bd9Sstevel@tonic-gate# an error occurs, tell the user. Otherwise, this file probably came about from 394*7c478bd9Sstevel@tonic-gate# scanning a directory, in which case just skip it and move on. 395*7c478bd9Sstevel@tonic-gatesub ProcFile { 396*7c478bd9Sstevel@tonic-gate my ($File, $Mult, $CmdLine) = @_; 397*7c478bd9Sstevel@tonic-gate my (@Ldd, $NoFound, $DbgFile, @DbgGlob, $Type); 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate $Type = `LC_ALL=C file '$File' 2>&1`; 400*7c478bd9Sstevel@tonic-gate if (($Type !~ /dynamically linked/) || ($Type =~ /Sun demand paged/)) { 401*7c478bd9Sstevel@tonic-gate if ($CmdLine) { 402*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: is an invalid file " . 403*7c478bd9Sstevel@tonic-gate "type\n"), $Prog, $File; 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate return 0; 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate # Create a temporary filename for capturing binding information. 409*7c478bd9Sstevel@tonic-gate $DbgSeed = basename($File); 410*7c478bd9Sstevel@tonic-gate $DbgSeed = "$TmpDir/lari.dbg.$$.$DbgSeed"; 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate # Exercise the file under ldd(1), capturing all the bindings. 413*7c478bd9Sstevel@tonic-gate @Ldd = split(/\n/, 414*7c478bd9Sstevel@tonic-gate `LC_ALL=C ldd $LddArgs -e LD_DEBUG_OUTPUT='$DbgSeed' '$File' 2>&1`); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate # If ldd isn't -e capable we'll get a usage message. The -e option was 417*7c478bd9Sstevel@tonic-gate # introduced in Solaris 9 and related patches. Also, make sure the user 418*7c478bd9Sstevel@tonic-gate # sees any ldd errors. 419*7c478bd9Sstevel@tonic-gate $NoFound = 0; 420*7c478bd9Sstevel@tonic-gate for my $Line (@Ldd) { 421*7c478bd9Sstevel@tonic-gate if ($Line =~ /^usage: ldd/) { 422*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: ldd: does not support -e, " . 423*7c478bd9Sstevel@tonic-gate "unable to capture bindings output\n"), $Prog; 424*7c478bd9Sstevel@tonic-gate exit 1; 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate if ($Line =~ /not found/) { 427*7c478bd9Sstevel@tonic-gate $NoFound = 1; 428*7c478bd9Sstevel@tonic-gate last; 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate # The runtime linker will have appended a process id to the debug file. 433*7c478bd9Sstevel@tonic-gate # As we have to intuit the name, make sure there is only one debug 434*7c478bd9Sstevel@tonic-gate # file match, otherwise there must be some clutter in the output 435*7c478bd9Sstevel@tonic-gate # directory that is going to mess up our analysis. 436*7c478bd9Sstevel@tonic-gate foreach my $Match (<\Q${DbgSeed}\E.*>) { 437*7c478bd9Sstevel@tonic-gate if ($Match =~ /^\Q$DbgSeed\E\.\d+$/) { 438*7c478bd9Sstevel@tonic-gate push(@DbgGlob, $Match); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate if (@DbgGlob == 0) { 442*7c478bd9Sstevel@tonic-gate # If there is no debug file, bail. This can occur if the file 443*7c478bd9Sstevel@tonic-gate # being processed is secure. 444*7c478bd9Sstevel@tonic-gate if ($CmdLine) { 445*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: unable to capture " . 446*7c478bd9Sstevel@tonic-gate "bindings output - possible secure application?\n"), 447*7c478bd9Sstevel@tonic-gate $Prog, $File; 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate return 0; 450*7c478bd9Sstevel@tonic-gate } elsif (@DbgGlob > 1) { 451*7c478bd9Sstevel@tonic-gate # Too many debug files found. 452*7c478bd9Sstevel@tonic-gate if ($CmdLine) { 453*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: multiple bindings " . 454*7c478bd9Sstevel@tonic-gate "output files exist: %s: clean up temporary " . 455*7c478bd9Sstevel@tonic-gate "directory\n"), $Prog, $File, $DbgSeed; 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate return 0; 458*7c478bd9Sstevel@tonic-gate } else { 459*7c478bd9Sstevel@tonic-gate $DbgFile = $DbgGlob[0]; 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate # Ok, we're ready to process the bindings information. Print a header 463*7c478bd9Sstevel@tonic-gate # if necessary, and if there were any ldd(1) errors push some of them 464*7c478bd9Sstevel@tonic-gate # out before any bindings information. Limit the output, as it can 465*7c478bd9Sstevel@tonic-gate # sometimes be excessive. If there are errors, the bindings information 466*7c478bd9Sstevel@tonic-gate # is likely to be incomplete. 467*7c478bd9Sstevel@tonic-gate if ($Mult) { 468*7c478bd9Sstevel@tonic-gate print STDOUT "$File:\n"; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate if ($NoFound) { 471*7c478bd9Sstevel@tonic-gate my ($Cnt) = 4; 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate for my $Line (@Ldd) { 474*7c478bd9Sstevel@tonic-gate if ($Line =~ /not found/) { 475*7c478bd9Sstevel@tonic-gate print STDOUT "$Line\n"; 476*7c478bd9Sstevel@tonic-gate $Cnt--; 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate if ($Cnt == 0) { 479*7c478bd9Sstevel@tonic-gate print STDOUT gettext("\tcontinued ...\n"); 480*7c478bd9Sstevel@tonic-gate last; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate # If the user wants the original debugging file left behind, rename it 486*7c478bd9Sstevel@tonic-gate # so that it doesn't get re-read by another instance of lari processing 487*7c478bd9Sstevel@tonic-gate # this file. 488*7c478bd9Sstevel@tonic-gate if ($opt{s}) { 489*7c478bd9Sstevel@tonic-gate rename($DbgFile, $DbgSeed); 490*7c478bd9Sstevel@tonic-gate $DbgFile = $DbgSeed; 491*7c478bd9Sstevel@tonic-gate printf STDOUT gettext("%s: %s: bindings information " . 492*7c478bd9Sstevel@tonic-gate "saved as: %s\n"), $Prog, $File, $DbgFile; 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate ProcBindings($File, $Mult, $DbgFile); 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate # Now that we've finished with the debugging file, nuke it if necessary. 498*7c478bd9Sstevel@tonic-gate if (!$opt{s}) { 499*7c478bd9Sstevel@tonic-gate unlink($DbgFile); 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate $DbgSeed = ""; 502*7c478bd9Sstevel@tonic-gate return 1; 503*7c478bd9Sstevel@tonic-gate} 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gatesub ProcBindings { 506*7c478bd9Sstevel@tonic-gate my ($File, $Mult, $DbgFile) = @_; 507*7c478bd9Sstevel@tonic-gate my (%Filtees, $FileHandle); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate # Reinitialize our arrays when we're dealing with multiple files. 510*7c478bd9Sstevel@tonic-gate if ($Mult) { 511*7c478bd9Sstevel@tonic-gate %Symbols = (); 512*7c478bd9Sstevel@tonic-gate %Objects = (); 513*7c478bd9Sstevel@tonic-gate %Versioned = (); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate # As debugging output can be significant, read a line at a time. 517*7c478bd9Sstevel@tonic-gate open($FileHandle, "<$DbgFile"); 518*7c478bd9Sstevel@tonic-gate while (defined(my $Line = <$FileHandle>)) { 519*7c478bd9Sstevel@tonic-gate chomp($Line); 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate # If we find a relationship between a filter and filtee, save 522*7c478bd9Sstevel@tonic-gate # it, we'll come back to this once we've gathered everybodies 523*7c478bd9Sstevel@tonic-gate # symbols. 524*7c478bd9Sstevel@tonic-gate if ($Line =~ /; filtered by /) { 525*7c478bd9Sstevel@tonic-gate my ($Filtee) = $Line; 526*7c478bd9Sstevel@tonic-gate my ($Filter) = $Line; 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate # Separate the filter and filtee names, ignore the 529*7c478bd9Sstevel@tonic-gate # runtime linker. 530*7c478bd9Sstevel@tonic-gate $Filtee =~ s/^.*: file=(.*); filtered by .*/$1/; 531*7c478bd9Sstevel@tonic-gate if ($Filtee =~ $Rtld) { 532*7c478bd9Sstevel@tonic-gate next; 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate $Filter =~ s/^.*; filtered by //; 535*7c478bd9Sstevel@tonic-gate $Filtees{$Filtee}{$Filter} = 1; 536*7c478bd9Sstevel@tonic-gate next; 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate # If we find a configuration alternative, determine whether it 540*7c478bd9Sstevel@tonic-gate # is for one of our filtees, and if so record it. 541*7c478bd9Sstevel@tonic-gate if ($Line =~ / configuration alternate found:/) { 542*7c478bd9Sstevel@tonic-gate my ($Orig) = $Line; 543*7c478bd9Sstevel@tonic-gate my ($Altr) = $Line; 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate # Separate the original and alternative names. 546*7c478bd9Sstevel@tonic-gate $Orig =~ s/^.*: file=(.*) .*$/$1/; 547*7c478bd9Sstevel@tonic-gate $Altr =~ s/^.* configuration alternate found: (.*)$/$1/; 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate for my $Filtee (keys(%Filtees)) { 550*7c478bd9Sstevel@tonic-gate if ($Filtee ne $Orig) { 551*7c478bd9Sstevel@tonic-gate next; 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate for my $Filter (keys(%{$Filtees{$Filtee}})) { 554*7c478bd9Sstevel@tonic-gate $Filtees{$Altr}{$Filter} = 1; 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate next; 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate # Collect the symbols from any file analyzed. 561*7c478bd9Sstevel@tonic-gate if ($Line =~ /^.*: file=(.*); analyzing .*/) { 562*7c478bd9Sstevel@tonic-gate GetAllSymbols($1); 563*7c478bd9Sstevel@tonic-gate next; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate # Process any symbolic relocations that bind to a file. 567*7c478bd9Sstevel@tonic-gate if ($Line =~ /: binding file=.* to file=/) { 568*7c478bd9Sstevel@tonic-gate my ($RefFile, $DstFile, $SymName); 569*7c478bd9Sstevel@tonic-gate my (@Syms, $Found, @Fields); 570*7c478bd9Sstevel@tonic-gate my ($BndInfo) = 0; 571*7c478bd9Sstevel@tonic-gate my ($Offset) = 1; 572*7c478bd9Sstevel@tonic-gate my ($Dlsym) = 0; 573*7c478bd9Sstevel@tonic-gate my ($Detail) = 0; 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate # For greatest flexibility, split the line into fields 576*7c478bd9Sstevel@tonic-gate # and walk each field until we find what we need. 577*7c478bd9Sstevel@tonic-gate @Fields = split(' ', $Line); 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate # The referencing file, "... binding file=".*". 580*7c478bd9Sstevel@tonic-gate while ($Fields[$Offset]) { 581*7c478bd9Sstevel@tonic-gate if ($Fields[$Offset] =~ /^file=(.*)/) { 582*7c478bd9Sstevel@tonic-gate $RefFile = $1; 583*7c478bd9Sstevel@tonic-gate $Offset++; 584*7c478bd9Sstevel@tonic-gate last; 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate $Offset++; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate # The referencing offset, typically this is the address 589*7c478bd9Sstevel@tonic-gate # of the reference, "(0x1234...)", but in the case of a 590*7c478bd9Sstevel@tonic-gate # user lookup it's the string "(dlsym)". If we don't 591*7c478bd9Sstevel@tonic-gate # find this offset information we've been given a debug 592*7c478bd9Sstevel@tonic-gate # file that didn't user the "datail" token, in which case 593*7c478bd9Sstevel@tonic-gate # we're not getting all the information we need. 594*7c478bd9Sstevel@tonic-gate if ($Fields[$Offset] =~ /^\((.*)\)/) { 595*7c478bd9Sstevel@tonic-gate if ($1 eq 'dlsym') { 596*7c478bd9Sstevel@tonic-gate $Dlsym = 1; 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate $Detail = 1; 599*7c478bd9Sstevel@tonic-gate $Offset++; 600*7c478bd9Sstevel@tonic-gate } 601*7c478bd9Sstevel@tonic-gate # The destination file, "... to file=".*". 602*7c478bd9Sstevel@tonic-gate while ($Fields[$Offset]) { 603*7c478bd9Sstevel@tonic-gate if ($Fields[$Offset] =~ /^file=(.*)/) { 604*7c478bd9Sstevel@tonic-gate $DstFile = $1; 605*7c478bd9Sstevel@tonic-gate $Offset++; 606*7c478bd9Sstevel@tonic-gate last; 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate $Offset++; 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate # The symbol being bound, "... symbol `.*' ...". 611*7c478bd9Sstevel@tonic-gate while ($Fields[$Offset]) { 612*7c478bd9Sstevel@tonic-gate if ($Fields[$Offset] =~ /^\`(.*)\'$/) { 613*7c478bd9Sstevel@tonic-gate $SymName = $1; 614*7c478bd9Sstevel@tonic-gate $Offset++; 615*7c478bd9Sstevel@tonic-gate last; 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate $Offset++; 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate # Possible trailing binding info, "... (direct,.*)$". 620*7c478bd9Sstevel@tonic-gate while ($Fields[$Offset]) { 621*7c478bd9Sstevel@tonic-gate if ($Fields[$Offset] =~ /^\((.*)\)$/) { 622*7c478bd9Sstevel@tonic-gate $BndInfo = $1; 623*7c478bd9Sstevel@tonic-gate $Offset++; 624*7c478bd9Sstevel@tonic-gate last; 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate $Offset++; 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate if ($Detail == 0) { 630*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: debug file " . 631*7c478bd9Sstevel@tonic-gate "does not contain `detail' information\n"), 632*7c478bd9Sstevel@tonic-gate $Prog, $DbgFile; 633*7c478bd9Sstevel@tonic-gate return; 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate # Collect the symbols from each object. 637*7c478bd9Sstevel@tonic-gate GetAllSymbols($RefFile); 638*7c478bd9Sstevel@tonic-gate GetAllSymbols($DstFile); 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate # Identify that this definition has been bound to. 641*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjRef]++; 642*7c478bd9Sstevel@tonic-gate if ($RefFile eq $DstFile) { 643*7c478bd9Sstevel@tonic-gate # If the reference binds to a definition within 644*7c478bd9Sstevel@tonic-gate # the same file this symbol may be a candidate 645*7c478bd9Sstevel@tonic-gate # for reducing to local. 646*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Self; 647*7c478bd9Sstevel@tonic-gate $Objects{$DstFile}{$SymName} |= $Self; 648*7c478bd9Sstevel@tonic-gate } else { 649*7c478bd9Sstevel@tonic-gate # This symbol is required to satisfy an external 650*7c478bd9Sstevel@tonic-gate # reference. 651*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Extn; 652*7c478bd9Sstevel@tonic-gate $Objects{$DstFile}{$SymName} |= $Extn; 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate # Assign any other state indicated by the binding info 656*7c478bd9Sstevel@tonic-gate # associated with the diagnostic output. 657*7c478bd9Sstevel@tonic-gate if (!$BndInfo) { 658*7c478bd9Sstevel@tonic-gate next; 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate if ($BndInfo =~ /direct/) { 662*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Dirc; 663*7c478bd9Sstevel@tonic-gate $Objects{$DstFile}{$SymName} |= $Dirc; 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate if ($BndInfo =~ /copy-ref/) { 666*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Cpyr; 667*7c478bd9Sstevel@tonic-gate $Objects{$DstFile}{$SymName} |= $Cpyr; 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate if ($BndInfo =~ /filtee/) { 670*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Filt; 671*7c478bd9Sstevel@tonic-gate $Objects{$DstFile}{$SymName} |= $Filt; 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate if ($BndInfo =~ /interpose/) { 674*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Intp; 675*7c478bd9Sstevel@tonic-gate $Objects{$DstFile}{$SymName} |= $Intp; 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate if ($BndInfo =~ /plt-addr/) { 678*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Plta; 679*7c478bd9Sstevel@tonic-gate $Objects{$DstFile}{$SymName} |= $Plta; 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate if ($Dlsym) { 682*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $User; 683*7c478bd9Sstevel@tonic-gate $Objects{$DstFile}{$SymName} |= $User; 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate close($FileHandle); 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate # Now that we've processed all objects, complete any auxiliary filtee 690*7c478bd9Sstevel@tonic-gate # tagging. For each filtee, determine which of the symbols it exports 691*7c478bd9Sstevel@tonic-gate # are also defined in its filters. If a filtee is bound to, the 692*7c478bd9Sstevel@tonic-gate # runtime linkers diagnostics will indicate a filtee binding. However, 693*7c478bd9Sstevel@tonic-gate # some of the filtee symbols may not be bound to, so here we mark them 694*7c478bd9Sstevel@tonic-gate # all so as to remove them from any interesting output. 695*7c478bd9Sstevel@tonic-gate for my $Filtee (keys(%Filtees)) { 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate # Standard filters aren't captured at all, as nothing can bind 698*7c478bd9Sstevel@tonic-gate # to them. 699*7c478bd9Sstevel@tonic-gate if (!exists($Objects{$Filtee})) { 700*7c478bd9Sstevel@tonic-gate next; 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate # Determine what symbols this filtee offers. 704*7c478bd9Sstevel@tonic-gate foreach my $SymName (keys(%{$Objects{$Filtee}})) { 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate # Ignore the usual reserved stuff. 707*7c478bd9Sstevel@tonic-gate if (!$opt{a} && (($SymName =~ $MultSyms) || 708*7c478bd9Sstevel@tonic-gate ($SymName =~ $CrtSyms))) { 709*7c478bd9Sstevel@tonic-gate next; 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate # Determine whether this symbol exists in our filter. 713*7c478bd9Sstevel@tonic-gate for my $Filter (keys(%{$Filtees{$Filtee}})) { 714*7c478bd9Sstevel@tonic-gate if (!$Symbols{$SymName}{$Filter}) { 715*7c478bd9Sstevel@tonic-gate next; 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate if (!($Symbols{$SymName}{$Filter}[$ObjFlag] & 718*7c478bd9Sstevel@tonic-gate $Msft)) { 719*7c478bd9Sstevel@tonic-gate next; 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$Filtee}[$ObjFlag] |= $Filt; 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate # Process objects and their symbols as required. 727*7c478bd9Sstevel@tonic-gate if ($opt{m}) { 728*7c478bd9Sstevel@tonic-gate # If we're creating a mapfile, traverse each object we've 729*7c478bd9Sstevel@tonic-gate # collected. 730*7c478bd9Sstevel@tonic-gate foreach my $Obj (keys(%Objects)) { 731*7c478bd9Sstevel@tonic-gate my ($File, $Path); 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate # Skip any objects that should be ignored 734*7c478bd9Sstevel@tonic-gate if ($Obj =~ $Rtld) { 735*7c478bd9Sstevel@tonic-gate next; 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate # Skip any versioned objects if required. 739*7c478bd9Sstevel@tonic-gate if ($opt{v} && $Versioned{$Obj}) { 740*7c478bd9Sstevel@tonic-gate next; 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate # Open the mapfile if required. 744*7c478bd9Sstevel@tonic-gate $File = basename($Obj); 745*7c478bd9Sstevel@tonic-gate $Path = "$DestDir/mapfile-$File"; 746*7c478bd9Sstevel@tonic-gate if (!open(MAPOUT, "> $Path")) { 747*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: open failed:" . 748*7c478bd9Sstevel@tonic-gate "%s\n"), $Prog, $Path, $!; 749*7c478bd9Sstevel@tonic-gate exit 1; 750*7c478bd9Sstevel@tonic-gate } 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate # Establish the mapfile preamble. 753*7c478bd9Sstevel@tonic-gate print MAPOUT "#\n# Interface Definition mapfile for:\n"; 754*7c478bd9Sstevel@tonic-gate print MAPOUT "#\tDynamic Object: $Obj\n"; 755*7c478bd9Sstevel@tonic-gate print MAPOUT "#\tProcess: $File\n#\n\n"; 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate # Process each global symbol. 758*7c478bd9Sstevel@tonic-gate print MAPOUT "$File {\n\tglobal:\n"; 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate foreach my $SymName (sort(keys(%{$Objects{$Obj}}))) { 761*7c478bd9Sstevel@tonic-gate my ($Flag) = $Objects{$Obj}{$SymName}; 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate # For the first pass we're only interested in 764*7c478bd9Sstevel@tonic-gate # symbols that have been bound to from an 765*7c478bd9Sstevel@tonic-gate # external object, or must be global to enable 766*7c478bd9Sstevel@tonic-gate # a binding to an interposing definition. 767*7c478bd9Sstevel@tonic-gate # Skip bindings to ourself as these are 768*7c478bd9Sstevel@tonic-gate # candidates for demoting to local. 769*7c478bd9Sstevel@tonic-gate if (!($Flag & ($Extn | $Intp))) { 770*7c478bd9Sstevel@tonic-gate next; 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate if (($Flag & ($Extn | $Self)) == $Self) { 773*7c478bd9Sstevel@tonic-gate next; 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate # Add the demangled name as a comment if 777*7c478bd9Sstevel@tonic-gate # required. 778*7c478bd9Sstevel@tonic-gate if ($opt{C}) { 779*7c478bd9Sstevel@tonic-gate my ($DemName) = Demangle($SymName); 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate if ($DemName ne "") { 782*7c478bd9Sstevel@tonic-gate print MAPOUT "\t\t#$DemName\n"; 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate print MAPOUT "\t\t$SymName;\n"; 786*7c478bd9Sstevel@tonic-gate } 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate # Process each local demotion. 789*7c478bd9Sstevel@tonic-gate print MAPOUT "\tlocal:\n"; 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate if ($opt{o}) { 792*7c478bd9Sstevel@tonic-gate foreach my $SymName 793*7c478bd9Sstevel@tonic-gate (sort(keys(%{$Objects{$Obj}}))) { 794*7c478bd9Sstevel@tonic-gate my ($Flag) = $Objects{$Obj}{$SymName}; 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate # For this pass we're only interested 797*7c478bd9Sstevel@tonic-gate # in symbol definitions that haven't 798*7c478bd9Sstevel@tonic-gate # been bound to, or have only been 799*7c478bd9Sstevel@tonic-gate # bound to from the same object. 800*7c478bd9Sstevel@tonic-gate if ($Flag & $Extn) { 801*7c478bd9Sstevel@tonic-gate next; 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate # Add the demangled name as a comment if 805*7c478bd9Sstevel@tonic-gate # required. 806*7c478bd9Sstevel@tonic-gate if ($opt{C}) { 807*7c478bd9Sstevel@tonic-gate my ($DemName) = 808*7c478bd9Sstevel@tonic-gate Demangle($SymName); 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate if ($DemName ne "") { 811*7c478bd9Sstevel@tonic-gate print MAPOUT 812*7c478bd9Sstevel@tonic-gate "\t\t#$DemName\n"; 813*7c478bd9Sstevel@tonic-gate } 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate print MAPOUT "\t\t$SymName;\n"; 816*7c478bd9Sstevel@tonic-gate } 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate # Capture everything else as local. 820*7c478bd9Sstevel@tonic-gate print MAPOUT "\t\t\*;\n};\n"; 821*7c478bd9Sstevel@tonic-gate close MAPOUT; 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate } else { 825*7c478bd9Sstevel@tonic-gate # If we're gathering information regarding the symbols used by 826*7c478bd9Sstevel@tonic-gate # the process, automatically sort any standard output using the 827*7c478bd9Sstevel@tonic-gate # symbol name. 828*7c478bd9Sstevel@tonic-gate if (!open(SORT, "| sort +1")) { 829*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: fork failed: %s\n"), 830*7c478bd9Sstevel@tonic-gate $Prog, $!; 831*7c478bd9Sstevel@tonic-gate exit 1; 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate foreach my $SymName (keys(%Symbols)) { 835*7c478bd9Sstevel@tonic-gate my ($Cnt); 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate # If we're looking for interesting symbols, inspect 838*7c478bd9Sstevel@tonic-gate # each definition of each symbol. If one is found to 839*7c478bd9Sstevel@tonic-gate # be interesting, the whole family are printed. 840*7c478bd9Sstevel@tonic-gate if (($Cnt = Interesting($SymName)) == 0) { 841*7c478bd9Sstevel@tonic-gate next; 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate # We've found something interesting, or all symbols 845*7c478bd9Sstevel@tonic-gate # should be output. List all objects that define this 846*7c478bd9Sstevel@tonic-gate # symbol. 847*7c478bd9Sstevel@tonic-gate foreach my $Obj (keys(%{$Symbols{$SymName}})) { 848*7c478bd9Sstevel@tonic-gate my ($DemName, $Type); 849*7c478bd9Sstevel@tonic-gate my ($Flag) = $Symbols{$SymName}{$Obj}[$ObjFlag]; 850*7c478bd9Sstevel@tonic-gate my ($Str) = "$Cnt:"; 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate # Do we just want overhead symbols. Consider 853*7c478bd9Sstevel@tonic-gate # copy-relocations, and plt address binding, 854*7c478bd9Sstevel@tonic-gate # as overhead too. 855*7c478bd9Sstevel@tonic-gate if ($opt{o} && (($Flag & 856*7c478bd9Sstevel@tonic-gate ($Extn | $Cpyr | $Plta)) == $Extn)) { 857*7c478bd9Sstevel@tonic-gate next; 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate # Do we just want all symbols that have been 861*7c478bd9Sstevel@tonic-gate # bound to. 862*7c478bd9Sstevel@tonic-gate if (($opt{a} || $opt{o}) && $opt{b} && 863*7c478bd9Sstevel@tonic-gate (($Flag & ($Extn | $Self | $Prot)) == 0)) { 864*7c478bd9Sstevel@tonic-gate next; 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate # If we haven't been asked for all symbols, only 868*7c478bd9Sstevel@tonic-gate # print those reserved symbols that have been 869*7c478bd9Sstevel@tonic-gate # bound to, as the number of reserved symbols 870*7c478bd9Sstevel@tonic-gate # can be quite excessive. 871*7c478bd9Sstevel@tonic-gate if (!$opt{a} && ((($SymName =~ $MultSyms) && 872*7c478bd9Sstevel@tonic-gate (($Flag & ($Extn | $Self)) == 0)) || 873*7c478bd9Sstevel@tonic-gate (($SymName =~ $CrtSyms) && (($Flag & 874*7c478bd9Sstevel@tonic-gate ($Extn | $Self | $Prot)) == 0)))) { 875*7c478bd9Sstevel@tonic-gate next; 876*7c478bd9Sstevel@tonic-gate } 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate # Skip any versioned objects if required. 879*7c478bd9Sstevel@tonic-gate if ($opt{v} && $Versioned{$Obj}) { 880*7c478bd9Sstevel@tonic-gate next; 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate # Display this symbol. 884*7c478bd9Sstevel@tonic-gate if ($Symbols{$SymName}{$Obj}[$ObjRef]) { 885*7c478bd9Sstevel@tonic-gate $Str = $Str . 886*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$Obj}[$ObjRef]; 887*7c478bd9Sstevel@tonic-gate } else { 888*7c478bd9Sstevel@tonic-gate $Str = $Str . '0'; 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate # Has the symbol been bound to externally 892*7c478bd9Sstevel@tonic-gate if ($Flag & $Extn) { 893*7c478bd9Sstevel@tonic-gate $Str = $Str . 'E'; 894*7c478bd9Sstevel@tonic-gate } 895*7c478bd9Sstevel@tonic-gate # Has the symbol been bound to from the same 896*7c478bd9Sstevel@tonic-gate # object. 897*7c478bd9Sstevel@tonic-gate if ($Flag & $Self) { 898*7c478bd9Sstevel@tonic-gate $Str = $Str . 'S'; 899*7c478bd9Sstevel@tonic-gate } 900*7c478bd9Sstevel@tonic-gate # Has the symbol been bound to directly. 901*7c478bd9Sstevel@tonic-gate if ($Flag & $Dirc) { 902*7c478bd9Sstevel@tonic-gate $Str = $Str . 'D'; 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate # Does this symbol originate for an explicit 905*7c478bd9Sstevel@tonic-gate # interposer. 906*7c478bd9Sstevel@tonic-gate if ($Flag & $Intp) { 907*7c478bd9Sstevel@tonic-gate $Str = $Str . 'I'; 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate # Is this symbol the reference data of a copy 910*7c478bd9Sstevel@tonic-gate # relocation. 911*7c478bd9Sstevel@tonic-gate if ($Flag & $Cpyr) { 912*7c478bd9Sstevel@tonic-gate $Str = $Str . 'C'; 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate # Is this symbol part of filtee. 915*7c478bd9Sstevel@tonic-gate if ($Flag & $Filt) { 916*7c478bd9Sstevel@tonic-gate $Str = $Str . 'F'; 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate # Is this symbol protected (in which case there 919*7c478bd9Sstevel@tonic-gate # may be a symbolic binding within the same 920*7c478bd9Sstevel@tonic-gate # object to this symbol). 921*7c478bd9Sstevel@tonic-gate if ($Flag & $Prot) { 922*7c478bd9Sstevel@tonic-gate $Str = $Str . 'P'; 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate # Is this symbol an executables .plt address. 925*7c478bd9Sstevel@tonic-gate if ($Flag & $Plta) { 926*7c478bd9Sstevel@tonic-gate $Str = $Str . 'A'; 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate # Does this binding originate from a user 929*7c478bd9Sstevel@tonic-gate # (dlsym) request. 930*7c478bd9Sstevel@tonic-gate if ($Flag & $User) { 931*7c478bd9Sstevel@tonic-gate $Str = $Str . 'U'; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate # Does this definition redirect the binding. 934*7c478bd9Sstevel@tonic-gate if ($Flag & $Msft) { 935*7c478bd9Sstevel@tonic-gate $Str = $Str . 'R'; 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate # Does this definition explicity define no 938*7c478bd9Sstevel@tonic-gate # direct binding. 939*7c478bd9Sstevel@tonic-gate if ($Flag & $Nodi) { 940*7c478bd9Sstevel@tonic-gate $Str = $Str . 'N'; 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate # Determine whether this is a function or a data 944*7c478bd9Sstevel@tonic-gate # object. For the latter, display the symbol 945*7c478bd9Sstevel@tonic-gate # size. Otherwise, the symbol is a reserved 946*7c478bd9Sstevel@tonic-gate # label, and is left untyped. 947*7c478bd9Sstevel@tonic-gate if ($Flag & $Func) { 948*7c478bd9Sstevel@tonic-gate $Type = '()'; 949*7c478bd9Sstevel@tonic-gate } elsif ($Flag & $Objt) { 950*7c478bd9Sstevel@tonic-gate $Type = '[' . 951*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$Obj}[$ObjSize] . 952*7c478bd9Sstevel@tonic-gate ']'; 953*7c478bd9Sstevel@tonic-gate } else { 954*7c478bd9Sstevel@tonic-gate $Type = ""; 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate # Demangle the symbol name if desired. 958*7c478bd9Sstevel@tonic-gate $DemName = Demangle($SymName); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate if ($Mult) { 961*7c478bd9Sstevel@tonic-gate print SORT " [$Str]: " . 962*7c478bd9Sstevel@tonic-gate "$SymName$Type$DemName: $Obj\n"; 963*7c478bd9Sstevel@tonic-gate } else { 964*7c478bd9Sstevel@tonic-gate print SORT "[$Str]: " . 965*7c478bd9Sstevel@tonic-gate "$SymName$Type$DemName: $Obj\n"; 966*7c478bd9Sstevel@tonic-gate } 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate close SORT; 970*7c478bd9Sstevel@tonic-gate } 971*7c478bd9Sstevel@tonic-gate} 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate# Heuristics to determine whether a symbol binding is interesting. In most 974*7c478bd9Sstevel@tonic-gate# applications there can be a large amount of symbol binding information to 975*7c478bd9Sstevel@tonic-gate# wade through. The most typical binding, to a single definition, probably 976*7c478bd9Sstevel@tonic-gate# isn't interesting or the cause of unexpected behavior. Here, we try and 977*7c478bd9Sstevel@tonic-gate# determine those bindings that may can cause unexpected behavior. 978*7c478bd9Sstevel@tonic-gate# 979*7c478bd9Sstevel@tonic-gate# Note, this routine is actually called for all symbols so that their count 980*7c478bd9Sstevel@tonic-gate# can be calculated in one place. 981*7c478bd9Sstevel@tonic-gatesub Interesting 982*7c478bd9Sstevel@tonic-gate{ 983*7c478bd9Sstevel@tonic-gate my ($SymName) = @_; 984*7c478bd9Sstevel@tonic-gate my ($ObjCnt, $GFlags, $BndCnt, $FltCnt, $NodiCnt, $RdirCnt, $ExRef); 985*7c478bd9Sstevel@tonic-gate 986*7c478bd9Sstevel@tonic-gate # Scan all definitions of this symbol, thus determining the definition 987*7c478bd9Sstevel@tonic-gate # count, the number of filters, redirections, executable references 988*7c478bd9Sstevel@tonic-gate # (copy-relocations, or plt addresses), no-direct bindings, and the 989*7c478bd9Sstevel@tonic-gate # number of definitions that have been bound to. 990*7c478bd9Sstevel@tonic-gate $ObjCnt = $GFlags = $BndCnt = $FltCnt = 991*7c478bd9Sstevel@tonic-gate $NodiCnt = $RdirCnt = $ExRef = 0; 992*7c478bd9Sstevel@tonic-gate foreach my $Obj (keys(%{$Symbols{$SymName}})) { 993*7c478bd9Sstevel@tonic-gate my ($Flag) = $Symbols{$SymName}{$Obj}[$ObjFlag]; 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate # Ignore standard filters when determining the symbol count, as 996*7c478bd9Sstevel@tonic-gate # a standard filter can never be bound to. 997*7c478bd9Sstevel@tonic-gate if (($Flag & ($Osft | $Ssft)) == 0) { 998*7c478bd9Sstevel@tonic-gate $ObjCnt++; 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate $GFlags |= $Flag; 1002*7c478bd9Sstevel@tonic-gate if ($Flag & $Filt) { 1003*7c478bd9Sstevel@tonic-gate $FltCnt++; 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate if ($Flag & $Nodi) { 1006*7c478bd9Sstevel@tonic-gate $NodiCnt++; 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate if ($Flag & ($Cpyr | $Plta)) { 1009*7c478bd9Sstevel@tonic-gate $ExRef++; 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate if ($Flag & $Msft) { 1012*7c478bd9Sstevel@tonic-gate $RdirCnt++; 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate 1015*7c478bd9Sstevel@tonic-gate # Ignore bindings to undefined .plts, and copy-relocation 1016*7c478bd9Sstevel@tonic-gate # references. These are implementation details, rather than 1017*7c478bd9Sstevel@tonic-gate # a truly interesting multiple-binding. If a symbol is tagged 1018*7c478bd9Sstevel@tonic-gate # as protected, count it as having bound to itself, even though 1019*7c478bd9Sstevel@tonic-gate # we can't tell if it's really been used. 1020*7c478bd9Sstevel@tonic-gate if (($Flag & ($Self | $Extn | $Prot)) && 1021*7c478bd9Sstevel@tonic-gate (($Flag & ($Plta | $Cpyr)) == 0)) { 1022*7c478bd9Sstevel@tonic-gate $BndCnt++; 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate # If we want all symbols, return the count. 1027*7c478bd9Sstevel@tonic-gate if (!$opt{i}) { 1028*7c478bd9Sstevel@tonic-gate return $ObjCnt; 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate # Single instance symbol definitions aren't very interesting. 1032*7c478bd9Sstevel@tonic-gate if ($ObjCnt == 1) { 1033*7c478bd9Sstevel@tonic-gate return 0; 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate # Traverse each symbol definition looking for the following: 1037*7c478bd9Sstevel@tonic-gate # 1038*7c478bd9Sstevel@tonic-gate # . Multiple symbols are bound to externally. 1039*7c478bd9Sstevel@tonic-gate # . A symbol is bound to externally, and possibly symbolically. 1040*7c478bd9Sstevel@tonic-gate # 1041*7c478bd9Sstevel@tonic-gate # Two symbol bindings are acceptable in some cases, and thus aren't 1042*7c478bd9Sstevel@tonic-gate # interesting: 1043*7c478bd9Sstevel@tonic-gate # 1044*7c478bd9Sstevel@tonic-gate # . Copy relocations. Here, the executable binds to a shared object 1045*7c478bd9Sstevel@tonic-gate # to access the data definition, which is then copied to the 1046*7c478bd9Sstevel@tonic-gate # executable. All other references should then bind to the copied 1047*7c478bd9Sstevel@tonic-gate # data. 1048*7c478bd9Sstevel@tonic-gate # . Non-plt relocations to functions that are referenced by the 1049*7c478bd9Sstevel@tonic-gate # executable will bind to the .plt in the executable. This 1050*7c478bd9Sstevel@tonic-gate # provides for address comparison calculations (although plainly 1051*7c478bd9Sstevel@tonic-gate # an overhead). 1052*7c478bd9Sstevel@tonic-gate # 1053*7c478bd9Sstevel@tonic-gate # Multiple symbol bindings are acceptable in some cases, and thus aren't 1054*7c478bd9Sstevel@tonic-gate # interesting: 1055*7c478bd9Sstevel@tonic-gate # 1056*7c478bd9Sstevel@tonic-gate # . Filtees. Multiple filtees may exist for one filter. 1057*7c478bd9Sstevel@tonic-gate # 1058*7c478bd9Sstevel@tonic-gate if ((($ObjCnt == 2) && ($GFlags & ($Cpyr | $Plta))) || 1059*7c478bd9Sstevel@tonic-gate ($ObjCnt == ($FltCnt + 1))) { 1060*7c478bd9Sstevel@tonic-gate return 0; 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate # If we're only interested in multiply-bound symbols. 1064*7c478bd9Sstevel@tonic-gate if (($opt{b} || ($SymName =~ $MultSyms) || ($SymName =~ $CrtSyms)) && 1065*7c478bd9Sstevel@tonic-gate ($BndCnt < 2)) { 1066*7c478bd9Sstevel@tonic-gate return (0); 1067*7c478bd9Sstevel@tonic-gate } 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate # Multiple instances of a definition, where all but one are filter 1070*7c478bd9Sstevel@tonic-gate # references and/or copy relocations, are also uninteresting. 1071*7c478bd9Sstevel@tonic-gate # Effectively, only one symbol is providing the final binding. 1072*7c478bd9Sstevel@tonic-gate if (($FltCnt && $RdirCnt) && 1073*7c478bd9Sstevel@tonic-gate (($FltCnt + $RdirCnt + $ExRef) == $ObjCnt)) { 1074*7c478bd9Sstevel@tonic-gate return (0); 1075*7c478bd9Sstevel@tonic-gate } 1076*7c478bd9Sstevel@tonic-gate 1077*7c478bd9Sstevel@tonic-gate # Multiple instances of explicitly defined no-direct binding symbols 1078*7c478bd9Sstevel@tonic-gate # are known to occur, and their no-binding definition indicates they 1079*7c478bd9Sstevel@tonic-gate # are expected and accounted for. Thus, these aren't interesting. 1080*7c478bd9Sstevel@tonic-gate if (($ExRef + $NodiCnt) == $ObjCnt) { 1081*7c478bd9Sstevel@tonic-gate return (0); 1082*7c478bd9Sstevel@tonic-gate } 1083*7c478bd9Sstevel@tonic-gate 1084*7c478bd9Sstevel@tonic-gate # We have an interesting symbol, returns its count. 1085*7c478bd9Sstevel@tonic-gate return $ObjCnt; 1086*7c478bd9Sstevel@tonic-gate} 1087*7c478bd9Sstevel@tonic-gate 1088*7c478bd9Sstevel@tonic-gate# Obtain the global symbol definitions of an object and determine whether the 1089*7c478bd9Sstevel@tonic-gate# object has been versioned. 1090*7c478bd9Sstevel@tonic-gatesub GetAllSymbols { 1091*7c478bd9Sstevel@tonic-gate my ($Obj) = @_; 1092*7c478bd9Sstevel@tonic-gate my (@Elfd, @Elfs, @Elfr, $Type, $Exec, $FileHandle); 1093*7c478bd9Sstevel@tonic-gate my (%AddrToName, %NameToAddr); 1094*7c478bd9Sstevel@tonic-gate my ($Vers) = 0; 1095*7c478bd9Sstevel@tonic-gate my ($Symb) = 0; 1096*7c478bd9Sstevel@tonic-gate my ($Copy) = 0; 1097*7c478bd9Sstevel@tonic-gate my ($Interpose) = 0; 1098*7c478bd9Sstevel@tonic-gate my ($Fltr) = 0; 1099*7c478bd9Sstevel@tonic-gate 1100*7c478bd9Sstevel@tonic-gate # Determine whether we've already retrieved this object's symbols. 1101*7c478bd9Sstevel@tonic-gate # Also, ignore the runtime linker, it's on a separate link-map, and 1102*7c478bd9Sstevel@tonic-gate # except for the filtee symbols that might be bound via libdl, is 1103*7c478bd9Sstevel@tonic-gate # uninteresting. 1104*7c478bd9Sstevel@tonic-gate if (($Objects{$Obj}) || ($Obj =~ $Rtld)) { 1105*7c478bd9Sstevel@tonic-gate return; 1106*7c478bd9Sstevel@tonic-gate } 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate # Get the dynamic information. 1109*7c478bd9Sstevel@tonic-gate @Elfd = split(/\n/, `LC_ALL=C elfdump -d '$Obj' 2> /dev/null`); 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate # If there's no information, it's possible we've been given a debug 1112*7c478bd9Sstevel@tonic-gate # output file and are processing it from a location from which the 1113*7c478bd9Sstevel@tonic-gate # dependencies specified in the debug file aren't accessible. 1114*7c478bd9Sstevel@tonic-gate if (!@Elfd) { 1115*7c478bd9Sstevel@tonic-gate printf STDERR gettext("%s: %s: unable to process ELF file\n"), 1116*7c478bd9Sstevel@tonic-gate $Prog, $Obj; 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate # Add the file to our list, so that we don't create the same 1119*7c478bd9Sstevel@tonic-gate # message again. Processing should continue so that we can 1120*7c478bd9Sstevel@tonic-gate # flush out as many error messages as possible. 1121*7c478bd9Sstevel@tonic-gate $Objects{$Obj}{"DoesNotExist"} = 0; 1122*7c478bd9Sstevel@tonic-gate return; 1123*7c478bd9Sstevel@tonic-gate } 1124*7c478bd9Sstevel@tonic-gate 1125*7c478bd9Sstevel@tonic-gate # If we're processing a filter there's no need to save any symbols, as 1126*7c478bd9Sstevel@tonic-gate # no bindings will occur to this object. 1127*7c478bd9Sstevel@tonic-gate # 1128*7c478bd9Sstevel@tonic-gate # Determine whether we've got a symbolicly bound object. With newer 1129*7c478bd9Sstevel@tonic-gate # linkers all symbols will be marked as protected ("P"), but with older 1130*7c478bd9Sstevel@tonic-gate # linkers this state could only be intuited from the symbolic dynamic 1131*7c478bd9Sstevel@tonic-gate # tag. 1132*7c478bd9Sstevel@tonic-gate foreach my $Line (@Elfd) { 1133*7c478bd9Sstevel@tonic-gate my (@Fields); 1134*7c478bd9Sstevel@tonic-gate @Fields = split(' ', $Line); 1135*7c478bd9Sstevel@tonic-gate 1136*7c478bd9Sstevel@tonic-gate # Determine if the FILTER tag is set. 1137*7c478bd9Sstevel@tonic-gate if ($#Fields == 3) { 1138*7c478bd9Sstevel@tonic-gate if ($Fields[1] eq "FILTER") { 1139*7c478bd9Sstevel@tonic-gate $Fltr |= $Osft; 1140*7c478bd9Sstevel@tonic-gate next; 1141*7c478bd9Sstevel@tonic-gate } 1142*7c478bd9Sstevel@tonic-gate if ($Fields[1] eq "AUXILIARY") { 1143*7c478bd9Sstevel@tonic-gate $Fltr |= $Oaft; 1144*7c478bd9Sstevel@tonic-gate next; 1145*7c478bd9Sstevel@tonic-gate } 1146*7c478bd9Sstevel@tonic-gate next; 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate # We're only interested in the FLAGS entry. 1150*7c478bd9Sstevel@tonic-gate if (($#Fields < 4) || ($Fields[1] !~ "^FLAGS")) { 1151*7c478bd9Sstevel@tonic-gate next; 1152*7c478bd9Sstevel@tonic-gate } 1153*7c478bd9Sstevel@tonic-gate if (($Fields[1] eq "FLAGS") && ($Line =~ " SYMBOLIC ")) { 1154*7c478bd9Sstevel@tonic-gate $Symb = 1; 1155*7c478bd9Sstevel@tonic-gate next; 1156*7c478bd9Sstevel@tonic-gate } 1157*7c478bd9Sstevel@tonic-gate if (($Fields[1] eq "FLAGS_1") && ($Line =~ " INTERPOSE ")) { 1158*7c478bd9Sstevel@tonic-gate $Interpose = 1; 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate } 1161*7c478bd9Sstevel@tonic-gate 1162*7c478bd9Sstevel@tonic-gate # If this file is a dynamic executable, determine if this object has 1163*7c478bd9Sstevel@tonic-gate # any copy relocations so that any associated bindings can be labeled 1164*7c478bd9Sstevel@tonic-gate # more meaningfully. 1165*7c478bd9Sstevel@tonic-gate $Type = `LC_ALL=C file '$Obj'`; 1166*7c478bd9Sstevel@tonic-gate if ($Type =~ /executable/) { 1167*7c478bd9Sstevel@tonic-gate $Exec = 1; 1168*7c478bd9Sstevel@tonic-gate # Obtain any copy relocations. 1169*7c478bd9Sstevel@tonic-gate @Elfr = split(/\n/, `LC_ALL=C elfdump -r '$Obj' 2>&1`); 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate foreach my $Rel (@Elfr) { 1172*7c478bd9Sstevel@tonic-gate my ($SymName, @Fields); 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate if ($Rel !~ /^\s+R_\S+_COPY /) { 1175*7c478bd9Sstevel@tonic-gate next; 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate @Fields = split(' ', $Rel); 1178*7c478bd9Sstevel@tonic-gate if ($Fields[0] eq 'R_SPARC_COPY') { 1179*7c478bd9Sstevel@tonic-gate $SymName = $Fields[4]; 1180*7c478bd9Sstevel@tonic-gate } elsif ($Fields[0] eq 'R_386_COPY') { 1181*7c478bd9Sstevel@tonic-gate $SymName = $Fields[3]; 1182*7c478bd9Sstevel@tonic-gate } else { 1183*7c478bd9Sstevel@tonic-gate next; 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate $Symbols{$SymName}{$Obj}[$ObjFlag] |= $Cpyr; 1187*7c478bd9Sstevel@tonic-gate $Objects{$Obj}{$SymName} |= $Cpyr; 1188*7c478bd9Sstevel@tonic-gate $Copy = 1; 1189*7c478bd9Sstevel@tonic-gate } 1190*7c478bd9Sstevel@tonic-gate } else { 1191*7c478bd9Sstevel@tonic-gate $Exec = 0; 1192*7c478bd9Sstevel@tonic-gate } 1193*7c478bd9Sstevel@tonic-gate 1194*7c478bd9Sstevel@tonic-gate # Obtain the dynamic symbol table for this object. Symbol tables can 1195*7c478bd9Sstevel@tonic-gate # be quite large, so open the elfump command through a pipe. 1196*7c478bd9Sstevel@tonic-gate open($FileHandle, "LC_ALL=C elfdump -sN.dynsym '$Obj' 2> /dev/null |"); 1197*7c478bd9Sstevel@tonic-gate 1198*7c478bd9Sstevel@tonic-gate # Now process all symbols. 1199*7c478bd9Sstevel@tonic-gate while (defined(my $Line = <$FileHandle>)) { 1200*7c478bd9Sstevel@tonic-gate chomp($Line); 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate my (@Fields) = split(' ', $Line); 1203*7c478bd9Sstevel@tonic-gate my ($Flags); 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate # We're only interested in defined non-reserved symbol entries. 1206*7c478bd9Sstevel@tonic-gate # Note, ABS and NOTY symbols of non-zero size have been known to 1207*7c478bd9Sstevel@tonic-gate # occur, so capture them. 1208*7c478bd9Sstevel@tonic-gate if (($#Fields < 8) || ($Fields[4] !~ $GlobWeak) || 1209*7c478bd9Sstevel@tonic-gate ($Fields[7] =~ $UndefSym) || (!$opt{a} && 1210*7c478bd9Sstevel@tonic-gate ($Fields[7] =~ $IgnSyms) && (oct($Fields[2]) eq 0))) { 1211*7c478bd9Sstevel@tonic-gate next; 1212*7c478bd9Sstevel@tonic-gate } 1213*7c478bd9Sstevel@tonic-gate 1214*7c478bd9Sstevel@tonic-gate # If we're found copy relocations, save the address and names 1215*7c478bd9Sstevel@tonic-gate # of any OBJT definitions, together with the copy symbol. 1216*7c478bd9Sstevel@tonic-gate if ($Copy && ($Fields[3] eq 'OBJT')) { 1217*7c478bd9Sstevel@tonic-gate push(@{$AddrToName{$Fields[1]}}, $Fields[8]); 1218*7c478bd9Sstevel@tonic-gate } 1219*7c478bd9Sstevel@tonic-gate if (($Symbols{$Fields[8]}{$Obj}) && 1220*7c478bd9Sstevel@tonic-gate ($Symbols{$Fields[8]}{$Obj}[$ObjFlag] & $Cpyr)) { 1221*7c478bd9Sstevel@tonic-gate $NameToAddr{$Fields[8]} = $Fields[1]; 1222*7c478bd9Sstevel@tonic-gate } 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate # If the symbol visibility is protected, this is an internal 1225*7c478bd9Sstevel@tonic-gate # symbolic binding (NOTE, an INTERNAL visibility for a global 1226*7c478bd9Sstevel@tonic-gate # symbol is invalid, but for a while ld(1) was setting this 1227*7c478bd9Sstevel@tonic-gate # attribute mistakenly for protected). 1228*7c478bd9Sstevel@tonic-gate # If this is a dynamic executable, mark its symbols as protected 1229*7c478bd9Sstevel@tonic-gate # (they can't be interposed on any more than symbols defined 1230*7c478bd9Sstevel@tonic-gate # protected within shared objects). 1231*7c478bd9Sstevel@tonic-gate $Flags = $Glob | $Fltr; 1232*7c478bd9Sstevel@tonic-gate if (($Fields[5] =~ /^[IP]$/) || $Symb || $Exec) { 1233*7c478bd9Sstevel@tonic-gate $Flags |= $Prot; 1234*7c478bd9Sstevel@tonic-gate } 1235*7c478bd9Sstevel@tonic-gate 1236*7c478bd9Sstevel@tonic-gate # If this object is marked as an interposer, tag each symbol. 1237*7c478bd9Sstevel@tonic-gate if ($Interpose) { 1238*7c478bd9Sstevel@tonic-gate $Flags |= $Intp; 1239*7c478bd9Sstevel@tonic-gate } 1240*7c478bd9Sstevel@tonic-gate 1241*7c478bd9Sstevel@tonic-gate # Identify the symbol as a function or data type, and for the 1242*7c478bd9Sstevel@tonic-gate # latter, capture the symbol size. Ignore the standard 1243*7c478bd9Sstevel@tonic-gate # symbolic labels, as we don't want to type them. 1244*7c478bd9Sstevel@tonic-gate if ($Fields[8] !~ $MultSyms) { 1245*7c478bd9Sstevel@tonic-gate if ($Fields[3] =~ /^FUNC$/) { 1246*7c478bd9Sstevel@tonic-gate $Flags |= $Func; 1247*7c478bd9Sstevel@tonic-gate } elsif ($Fields[3] =~ /^OBJT$/) { 1248*7c478bd9Sstevel@tonic-gate my ($Size) = $Fields[2]; 1249*7c478bd9Sstevel@tonic-gate 1250*7c478bd9Sstevel@tonic-gate if (oct($Size) eq 0) { 1251*7c478bd9Sstevel@tonic-gate $Size = "0"; 1252*7c478bd9Sstevel@tonic-gate } else { 1253*7c478bd9Sstevel@tonic-gate $Size =~ s/0x0*/0x/; 1254*7c478bd9Sstevel@tonic-gate } 1255*7c478bd9Sstevel@tonic-gate $Flags |= $Objt; 1256*7c478bd9Sstevel@tonic-gate $Symbols{$Fields[8]}{$Obj}[$ObjSize] = $Size; 1257*7c478bd9Sstevel@tonic-gate } 1258*7c478bd9Sstevel@tonic-gate } 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate $Symbols{$Fields[8]}{$Obj}[$ObjFlag] |= $Flags; 1261*7c478bd9Sstevel@tonic-gate $Objects{$Obj}{$Fields[8]} |= $Flags; 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate # If the version field is non-null this object has already been 1264*7c478bd9Sstevel@tonic-gate # versioned. 1265*7c478bd9Sstevel@tonic-gate if (($Vers == 0) && ($Fields[6] ne '0')) { 1266*7c478bd9Sstevel@tonic-gate $Versioned{$Obj} = 1; 1267*7c478bd9Sstevel@tonic-gate $Vers = 1; 1268*7c478bd9Sstevel@tonic-gate } 1269*7c478bd9Sstevel@tonic-gate } 1270*7c478bd9Sstevel@tonic-gate close($FileHandle); 1271*7c478bd9Sstevel@tonic-gate 1272*7c478bd9Sstevel@tonic-gate # Obtain any symbol information table for this object. Symbol tables can 1273*7c478bd9Sstevel@tonic-gate # be quite large, so open the elfump command through a pipe. 1274*7c478bd9Sstevel@tonic-gate open($FileHandle, "LC_ALL=C elfdump -y '$Obj' 2> /dev/null |"); 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate # Now process all symbols. 1277*7c478bd9Sstevel@tonic-gate while (defined(my $Line = <$FileHandle>)) { 1278*7c478bd9Sstevel@tonic-gate chomp($Line); 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate my (@Fields) = split(' ', $Line); 1281*7c478bd9Sstevel@tonic-gate my ($Flags) = 0; 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate # Binding attributes are in the second column. 1284*7c478bd9Sstevel@tonic-gate if ($#Fields < 1) { 1285*7c478bd9Sstevel@tonic-gate next; 1286*7c478bd9Sstevel@tonic-gate } 1287*7c478bd9Sstevel@tonic-gate if ($Fields[1] =~ /N/) { 1288*7c478bd9Sstevel@tonic-gate $Flags |= $Nodi 1289*7c478bd9Sstevel@tonic-gate } 1290*7c478bd9Sstevel@tonic-gate if ($Fields[1] =~ /F/) { 1291*7c478bd9Sstevel@tonic-gate $Flags |= $Ssft; 1292*7c478bd9Sstevel@tonic-gate } 1293*7c478bd9Sstevel@tonic-gate if ($Fields[1] =~ /A/) { 1294*7c478bd9Sstevel@tonic-gate $Flags |= $Saft; 1295*7c478bd9Sstevel@tonic-gate } 1296*7c478bd9Sstevel@tonic-gate 1297*7c478bd9Sstevel@tonic-gate # Determine the symbol name based upon the number of fields. 1298*7c478bd9Sstevel@tonic-gate if ($Flags && $Symbols{$Fields[$#Fields]}{$Obj}) { 1299*7c478bd9Sstevel@tonic-gate $Symbols{$Fields[$#Fields]}{$Obj}[$ObjFlag] |= $Flags; 1300*7c478bd9Sstevel@tonic-gate $Objects{$Obj}{$Fields[$#Fields]} |= $Flags; 1301*7c478bd9Sstevel@tonic-gate } 1302*7c478bd9Sstevel@tonic-gate } 1303*7c478bd9Sstevel@tonic-gate close($FileHandle); 1304*7c478bd9Sstevel@tonic-gate 1305*7c478bd9Sstevel@tonic-gate # If this symbol has already been marked as a copy-relocation reference, 1306*7c478bd9Sstevel@tonic-gate # see if this symbol has any aliases, which should also be marked. 1307*7c478bd9Sstevel@tonic-gate if ($Copy) { 1308*7c478bd9Sstevel@tonic-gate foreach my $SymName (keys(%NameToAddr)) { 1309*7c478bd9Sstevel@tonic-gate my ($Addr) = $NameToAddr{$SymName}; 1310*7c478bd9Sstevel@tonic-gate 1311*7c478bd9Sstevel@tonic-gate # Determine all symbols that have the same address. 1312*7c478bd9Sstevel@tonic-gate foreach my $AliasName (@{$AddrToName{$Addr}}) { 1313*7c478bd9Sstevel@tonic-gate if ($SymName eq $AliasName) { 1314*7c478bd9Sstevel@tonic-gate next; 1315*7c478bd9Sstevel@tonic-gate } 1316*7c478bd9Sstevel@tonic-gate $Symbols{$AliasName}{$Obj}[$ObjFlag] |= $Cpyr; 1317*7c478bd9Sstevel@tonic-gate $Objects{$Obj}{$AliasName} |= $Cpyr; 1318*7c478bd9Sstevel@tonic-gate } 1319*7c478bd9Sstevel@tonic-gate } 1320*7c478bd9Sstevel@tonic-gate } 1321*7c478bd9Sstevel@tonic-gate} 1322*7c478bd9Sstevel@tonic-gate 1323*7c478bd9Sstevel@tonic-gate# Demangle a symbol name if required. 1324*7c478bd9Sstevel@tonic-gatesub Demangle 1325*7c478bd9Sstevel@tonic-gate{ 1326*7c478bd9Sstevel@tonic-gate my ($SymName) = @_; 1327*7c478bd9Sstevel@tonic-gate my ($DemName); 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate if ($opt{C}) { 1330*7c478bd9Sstevel@tonic-gate my (@Dem); 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate # Determine if we've already demangled this name. 1333*7c478bd9Sstevel@tonic-gate if (exists($DemSyms{$SymName})) { 1334*7c478bd9Sstevel@tonic-gate return $DemSyms{$SymName}; 1335*7c478bd9Sstevel@tonic-gate } 1336*7c478bd9Sstevel@tonic-gate 1337*7c478bd9Sstevel@tonic-gate @Dem = split(/\n/, `dem '$SymName'`); 1338*7c478bd9Sstevel@tonic-gate foreach my $Line (@Dem) { 1339*7c478bd9Sstevel@tonic-gate my (@Fields) = split(' ', $Line); 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate if (($#Fields < 2) || ($Fields[1] ne '==') || 1342*7c478bd9Sstevel@tonic-gate ($Fields[0] eq $Fields[2])) { 1343*7c478bd9Sstevel@tonic-gate next; 1344*7c478bd9Sstevel@tonic-gate } 1345*7c478bd9Sstevel@tonic-gate $DemName = $Line; 1346*7c478bd9Sstevel@tonic-gate $DemName =~ s/.*== (.*)$/ \[$1]/; 1347*7c478bd9Sstevel@tonic-gate $DemSyms{$SymName} = $DemName; 1348*7c478bd9Sstevel@tonic-gate return($DemName); 1349*7c478bd9Sstevel@tonic-gate } 1350*7c478bd9Sstevel@tonic-gate } 1351*7c478bd9Sstevel@tonic-gate $DemSyms{$SymName} = ""; 1352*7c478bd9Sstevel@tonic-gate return(""); 1353*7c478bd9Sstevel@tonic-gate} 1354