17c478bd9Sstevel@tonic-gate#!/usr/perl5/bin/perl -w 27c478bd9Sstevel@tonic-gate# 37c478bd9Sstevel@tonic-gate# CDDL HEADER START 47c478bd9Sstevel@tonic-gate# 57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the 6749f21d3Swesolows# Common Development and Distribution License (the "License"). 7749f21d3Swesolows# You may not use this file except in compliance with the License. 87c478bd9Sstevel@tonic-gate# 97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate# and limitations under the License. 137c478bd9Sstevel@tonic-gate# 147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate# 207c478bd9Sstevel@tonic-gate# CDDL HEADER END 217c478bd9Sstevel@tonic-gate# 22749f21d3Swesolows 237c478bd9Sstevel@tonic-gate# 245253169eSAli Bahrami# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 256112cec5SJoshua M. Clulow# Copyright 2020 Oxide Computer Company 267c478bd9Sstevel@tonic-gate# 27749f21d3Swesolows 28749f21d3Swesolows# 297c478bd9Sstevel@tonic-gate# Check ELF information. 307c478bd9Sstevel@tonic-gate# 310910f6b5SRichard Lowe# This script descends a directory hierarchy inspecting ELF objects. The 320910f6b5SRichard Lowe# general theme is to verify that common Makefile rules have been used to 330910f6b5SRichard Lowe# build these objects. Typical failures occur when Makefile rules are 340910f6b5SRichard Lowe# re-invented rather than being inherited from "cmd/lib" Makefiles. 357c478bd9Sstevel@tonic-gate# 367c478bd9Sstevel@tonic-gate# As always, a number of components don't follow the rules, and these are 3775ce41a5SAli Bahrami# excluded to reduce this scripts output. 387c478bd9Sstevel@tonic-gate# 397c478bd9Sstevel@tonic-gate# By default any file that has conditions that should be reported is first 407c478bd9Sstevel@tonic-gate# listed and then each condition follows. The -o (one-line) option produces a 417c478bd9Sstevel@tonic-gate# more terse output which is better for sorting/diffing with "nightly". 427c478bd9Sstevel@tonic-gate# 437c478bd9Sstevel@tonic-gate# NOTE: missing dependencies, symbols or versions are reported by running the 447c478bd9Sstevel@tonic-gate# file through ldd(1). As objects within a proto area are built to exist in a 457c478bd9Sstevel@tonic-gate# base system, standard use of ldd(1) will bind any objects to dependencies 467c478bd9Sstevel@tonic-gate# that exist in the base system. It is frequently the case that newer objects 477c478bd9Sstevel@tonic-gate# exist in the proto area that are required to satisfy other objects 487c478bd9Sstevel@tonic-gate# dependencies, and without using these newer objects an ldd(1) will produce 4975ce41a5SAli Bahrami# misleading error messages. To compensate for this, the -D/-d options, or the 5075ce41a5SAli Bahrami# existence of the CODEMSG_WS/ROOT environment variables, cause the creation of 517c478bd9Sstevel@tonic-gate# alternative dependency mappings via crle(1) configuration files that establish 527c478bd9Sstevel@tonic-gate# any proto shared objects as alternatives to their base system location. Thus 537c478bd9Sstevel@tonic-gate# ldd(1) can be executed against these configuration files so that objects in a 547c478bd9Sstevel@tonic-gate# proto area bind to their dependencies in the same proto area. 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate# Define all global variables (required for strict) 5813bb1409SRichard Loweuse vars qw($Prog $Env $Ena64 $Tmpdir); 5975ce41a5SAli Bahramiuse vars qw($LddNoU $Conf32 $Conf64); 6075ce41a5SAli Bahramiuse vars qw(%opt); 6175ce41a5SAli Bahramiuse vars qw($ErrFH $ErrTtl $InfoFH $InfoTtl $OutCnt1 $OutCnt2); 6275ce41a5SAli Bahrami 6375ce41a5SAli Bahrami# An exception file is used to specify regular expressions to match 6475ce41a5SAli Bahrami# objects. These directives specify special attributes of the object. 6575ce41a5SAli Bahrami# The regular expressions are read from the file and compiled into the 6675ce41a5SAli Bahrami# regular expression variables. 6775ce41a5SAli Bahrami# 6875ce41a5SAli Bahrami# The name of each regular expression variable is of the form 6975ce41a5SAli Bahrami# 7075ce41a5SAli Bahrami# $EXRE_xxx 7175ce41a5SAli Bahrami# 7275ce41a5SAli Bahrami# where xxx is the name of the exception in lower case. For example, 7375ce41a5SAli Bahrami# the regular expression variable for EXEC_STACK is $EXRE_exec_stack. 7475ce41a5SAli Bahrami# 7575ce41a5SAli Bahrami# onbld_elfmod::LoadExceptionsToEXRE() depends on this naming convention 7675ce41a5SAli Bahrami# to initialize the regular expression variables, and to detect invalid 7775ce41a5SAli Bahrami# exception names. 7875ce41a5SAli Bahrami# 7975ce41a5SAli Bahrami# If a given exception is not used in the exception file, its regular 8075ce41a5SAli Bahrami# expression variable will be undefined. Users of these variables must 8175ce41a5SAli Bahrami# test the variable with defined() prior to use: 8275ce41a5SAli Bahrami# 8375ce41a5SAli Bahrami# defined($EXRE_exec_stack) && ($foo =~ $EXRE_exec_stack) 8475ce41a5SAli Bahrami# 855253169eSAli Bahrami# or if the test is to make sure the item is not specified: 865253169eSAli Bahrami# 875253169eSAli Bahrami# !defined($EXRE_exec_stack) || ($foo !~ $EXRE_exec_stack) 885253169eSAli Bahrami# 8975ce41a5SAli Bahrami# ---- 9075ce41a5SAli Bahrami# 9175ce41a5SAli Bahrami# The exceptions are: 9275ce41a5SAli Bahrami# 935253169eSAli Bahrami# EXEC_DATA 945253169eSAli Bahrami# Objects that are not required to have non-executable writable 955253169eSAli Bahrami# data segments. 965253169eSAli Bahrami# 9775ce41a5SAli Bahrami# EXEC_STACK 9875ce41a5SAli Bahrami# Objects that are not required to have a non-executable stack 9975ce41a5SAli Bahrami# 1009e593677SRichard Lowe# FORBIDDEN_DEP 1019e593677SRichard Lowe# Objects allowed to link to 'forbidden' objects 1029e593677SRichard Lowe# 1039e593677SRichard Lowe# FORBIDDEN 1049e593677SRichard Lowe# Objects to which nobody not excepted with FORBIDDEN_DEP may link 1059e593677SRichard Lowe# 1060910f6b5SRichard Lowe# NOT_KMOD 1070910f6b5SRichard Lowe# Objects that we think should be linked with -ztype=kmod but are 1080910f6b5SRichard Lowe# allowed to not be. 1090910f6b5SRichard Lowe# 11075ce41a5SAli Bahrami# NOCRLEALT 11175ce41a5SAli Bahrami# Objects that should be skipped by AltObjectConfig() when building 11275ce41a5SAli Bahrami# the crle script that maps objects to the proto area. 11375ce41a5SAli Bahrami# 11475ce41a5SAli Bahrami# NODIRECT 11575ce41a5SAli Bahrami# Objects that are not required to use direct bindings 11675ce41a5SAli Bahrami# 11775ce41a5SAli Bahrami# NOSYMSORT 11875ce41a5SAli Bahrami# Objects we should not check for duplicate addresses in 11975ce41a5SAli Bahrami# the symbol sort sections. 12075ce41a5SAli Bahrami# 12175ce41a5SAli Bahrami# OLDDEP 12275ce41a5SAli Bahrami# Objects that are no longer needed because their functionalty 12375ce41a5SAli Bahrami# has migrated elsewhere. These are usually pure filters that 12475ce41a5SAli Bahrami# point at libc. 12575ce41a5SAli Bahrami# 12675ce41a5SAli Bahrami# SKIP 12775ce41a5SAli Bahrami# Files and directories that should be excluded from analysis. 12875ce41a5SAli Bahrami# 12975ce41a5SAli Bahrami# STAB 13075ce41a5SAli Bahrami# Objects that are allowed to contain stab debugging sections 13175ce41a5SAli Bahrami# 13275ce41a5SAli Bahrami# TEXTREL 13375ce41a5SAli Bahrami# Object for which relocations are allowed to the text segment 13475ce41a5SAli Bahrami# 13575ce41a5SAli Bahrami# UNDEF_REF 13675ce41a5SAli Bahrami# Objects that are allowed undefined references 13775ce41a5SAli Bahrami# 13875ce41a5SAli Bahrami# UNREF_OBJ 13975ce41a5SAli Bahrami# "unreferenced object=" ldd(1) diagnostics. 14075ce41a5SAli Bahrami# 14175ce41a5SAli Bahrami# UNUSED_DEPS 14275ce41a5SAli Bahrami# Objects that are allowed to have unused dependencies 14375ce41a5SAli Bahrami# 14475ce41a5SAli Bahrami# UNUSED_OBJ 14575ce41a5SAli Bahrami# Objects that are allowed to be unused dependencies 14675ce41a5SAli Bahrami# 14775ce41a5SAli Bahrami# UNUSED_RPATH 14875ce41a5SAli Bahrami# Objects with unused runpaths 14975ce41a5SAli Bahrami# 15075ce41a5SAli Bahrami 1515253169eSAli Bahramiuse vars qw($EXRE_exec_data $EXRE_exec_stack $EXRE_nocrlealt); 1529e593677SRichard Loweuse vars qw($EXRE_nodirect $EXRE_nosymsort $EXRE_forbidden_dep $EXRE_forbidden); 15375ce41a5SAli Bahramiuse vars qw($EXRE_olddep $EXRE_skip $EXRE_stab $EXRE_textrel $EXRE_undef_ref); 15475ce41a5SAli Bahramiuse vars qw($EXRE_unref_obj $EXRE_unused_deps $EXRE_unused_obj); 1550910f6b5SRichard Loweuse vars qw($EXRE_unused_rpath $EXRE_no_comment $EXRE_not_kmod); 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gateuse strict; 1587c478bd9Sstevel@tonic-gateuse Getopt::Std; 15975ce41a5SAli Bahramiuse File::Basename; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate# Reliably compare two OS revisions. Arguments are <ver1> <op> <ver2>. 1637c478bd9Sstevel@tonic-gate# <op> is the string form of a normal numeric comparison operator. 1647c478bd9Sstevel@tonic-gatesub cmp_os_ver { 1657c478bd9Sstevel@tonic-gate my @ver1 = split(/\./, $_[0]); 1667c478bd9Sstevel@tonic-gate my $op = $_[1]; 1677c478bd9Sstevel@tonic-gate my @ver2 = split(/\./, $_[2]); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate push @ver2, ("0") x $#ver1 - $#ver2; 1707c478bd9Sstevel@tonic-gate push @ver1, ("0") x $#ver2 - $#ver1; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate my $diff = 0; 1737c478bd9Sstevel@tonic-gate while (@ver1 || @ver2) { 1747c478bd9Sstevel@tonic-gate if (($diff = shift(@ver1) - shift(@ver2)) != 0) { 1757c478bd9Sstevel@tonic-gate last; 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate return (eval "$diff $op 0" ? 1 : 0); 1797c478bd9Sstevel@tonic-gate} 1807c478bd9Sstevel@tonic-gate 18175ce41a5SAli Bahrami## ProcFile(FullPath, RelPath, File, Class, Type, Verdef) 18275ce41a5SAli Bahrami# 1837c478bd9Sstevel@tonic-gate# Determine whether this a ELF dynamic object and if so investigate its runtime 1847c478bd9Sstevel@tonic-gate# attributes. 18575ce41a5SAli Bahrami# 1867c478bd9Sstevel@tonic-gatesub ProcFile { 18775ce41a5SAli Bahrami my($FullPath, $RelPath, $Class, $Type, $Verdef) = @_; 18875ce41a5SAli Bahrami my(@Elf, @Ldd, $Dyn, $Sym, $Stack); 18967e3a03eSrie my($Sun, $Relsz, $Pltsz, $Tex, $Stab, $Strip, $Lddopt, $SymSort); 19075ce41a5SAli Bahrami my($Val, $Header, $IsX86, $RWX, $UnDep); 1910910f6b5SRichard Lowe my($HasDirectBinding, $HasKMOD); 1927c478bd9Sstevel@tonic-gate 19375ce41a5SAli Bahrami # Ignore symbolic links 19475ce41a5SAli Bahrami return if -l $FullPath; 19575ce41a5SAli Bahrami 19675ce41a5SAli Bahrami # Is this an object or directory hierarchy we don't care about? 19775ce41a5SAli Bahrami return if (defined($EXRE_skip) && ($RelPath =~ $EXRE_skip)); 19875ce41a5SAli Bahrami 19975ce41a5SAli Bahrami # Bail if we can't stat the file. Otherwise, note if it is SUID/SGID. 20075ce41a5SAli Bahrami return if !stat($FullPath); 20175ce41a5SAli Bahrami my $Secure = (-u _ || -g _) ? 1 : 0; 20275ce41a5SAli Bahrami 20375ce41a5SAli Bahrami # Reset output message counts for new input file 20475ce41a5SAli Bahrami $$ErrTtl = $$InfoTtl = 0; 20575ce41a5SAli Bahrami 2067c478bd9Sstevel@tonic-gate @Ldd = 0; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate # Determine whether we have access to inspect the file. 2097c478bd9Sstevel@tonic-gate if (!(-r $FullPath)) { 21075ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 21175ce41a5SAli Bahrami "unable to inspect file: permission denied"); 2127c478bd9Sstevel@tonic-gate return; 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate # Determine whether we have a executable (static or dynamic) or a 2167c478bd9Sstevel@tonic-gate # shared object. 21775ce41a5SAli Bahrami @Elf = split(/\n/, `elfdump -epdcy $FullPath 2>&1`); 2187c478bd9Sstevel@tonic-gate 2190910f6b5SRichard Lowe $Dyn = $Stack = $IsX86 = $RWX = $HasKMOD = 0; 2200910f6b5SRichard Lowe 2217c478bd9Sstevel@tonic-gate $Header = 'None'; 2227c478bd9Sstevel@tonic-gate foreach my $Line (@Elf) { 2237c478bd9Sstevel@tonic-gate # If we have an invalid file type (which we can tell from the 2247c478bd9Sstevel@tonic-gate # first line), or we're processing an archive, bail. 2257c478bd9Sstevel@tonic-gate if ($Header eq 'None') { 2267c478bd9Sstevel@tonic-gate if (($Line =~ /invalid file/) || 2275253169eSAli Bahrami ($Line =~ /\Q$FullPath\E(.*):/)) { 2287c478bd9Sstevel@tonic-gate return; 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate if ($Line =~ /^ELF Header/) { 2337c478bd9Sstevel@tonic-gate $Header = 'Ehdr'; 23475ce41a5SAli Bahrami next; 23575ce41a5SAli Bahrami } 2367c478bd9Sstevel@tonic-gate 23775ce41a5SAli Bahrami if ($Line =~ /^Program Header/) { 2387c478bd9Sstevel@tonic-gate $Header = 'Phdr'; 2397c478bd9Sstevel@tonic-gate $RWX = 0; 24075ce41a5SAli Bahrami next; 24175ce41a5SAli Bahrami } 2427c478bd9Sstevel@tonic-gate 24375ce41a5SAli Bahrami if ($Line =~ /^Dynamic Section/) { 2447c478bd9Sstevel@tonic-gate # A dynamic section indicates we're a dynamic object 2450910f6b5SRichard Lowe $Header = 'Dyn'; 2467c478bd9Sstevel@tonic-gate $Dyn = 1; 24775ce41a5SAli Bahrami next; 24875ce41a5SAli Bahrami } 2497c478bd9Sstevel@tonic-gate 25075ce41a5SAli Bahrami if (($Header eq 'Ehdr') && ($Line =~ /e_machine:/)) { 2517c478bd9Sstevel@tonic-gate # If it's a X86 object, we need to enforce RW- data. 25275ce41a5SAli Bahrami $IsX86 = 1 if $Line =~ /(EM_AMD64|EM_386)/; 25375ce41a5SAli Bahrami next; 2547c478bd9Sstevel@tonic-gate } 25575ce41a5SAli Bahrami 25675ce41a5SAli Bahrami if (($Header eq 'Phdr') && 2575253169eSAli Bahrami ($Line =~ /\[ PF_X\s+PF_W\s+PF_R \]/)) { 2587c478bd9Sstevel@tonic-gate # RWX segment seen. 2597c478bd9Sstevel@tonic-gate $RWX = 1; 26075ce41a5SAli Bahrami next; 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 26375ce41a5SAli Bahrami if (($Header eq 'Phdr') && 26475ce41a5SAli Bahrami ($Line =~ /\[ PT_LOAD \]/ && $RWX && $IsX86)) { 26575ce41a5SAli Bahrami # Seen an RWX PT_LOAD segment. 2665253169eSAli Bahrami if (!defined($EXRE_exec_data) || 2675253169eSAli Bahrami ($RelPath !~ $EXRE_exec_data)) { 26875ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 26975ce41a5SAli Bahrami "application requires non-executable " . 27075ce41a5SAli Bahrami "data\t<no -Mmapfile_noexdata?>"); 27175ce41a5SAli Bahrami } 27275ce41a5SAli Bahrami next; 27375ce41a5SAli Bahrami } 27475ce41a5SAli Bahrami 27575ce41a5SAli Bahrami if (($Header eq 'Phdr') && ($Line =~ /\[ PT_SUNWSTACK \]/)) { 2767c478bd9Sstevel@tonic-gate # This object defines a non-executable stack. 2777c478bd9Sstevel@tonic-gate $Stack = 1; 27875ce41a5SAli Bahrami next; 2797c478bd9Sstevel@tonic-gate } 2800910f6b5SRichard Lowe 2810910f6b5SRichard Lowe if (($Header eq 'Dyn') && ($Line =~ /SUNW_KMOD/)) { 2820910f6b5SRichard Lowe $HasKMOD = 1; 2830910f6b5SRichard Lowe next; 2840910f6b5SRichard Lowe } 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2870910f6b5SRichard Lowe # Determine whether this ELF object has a conforming mcs(1) comment 2880910f6b5SRichard Lowe # section. If the correct $(POST_PROCESS) macros are used, only a 3 2890910f6b5SRichard Lowe # or 4 line .comment section should exist containing one or two 2900910f6b5SRichard Lowe # "@(#)illumos" identifying comments (one comment for a non-debug 2910910f6b5SRichard Lowe # build, and two for a debug build). The results of the following 2920910f6b5SRichard Lowe # split should be three or four lines, the last empty line being 2930910f6b5SRichard Lowe # discarded by the split. 2946112cec5SJoshua M. Clulow if ($opt{m} && 2956112cec5SJoshua M. Clulow (!defined($EXRE_no_comment) || ($RelPath !~ $EXRE_no_comment))) { 2967c478bd9Sstevel@tonic-gate my(@Mcs, $Con, $Dev); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate @Mcs = split(/\n/, `mcs -p $FullPath 2>&1`); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate $Con = $Dev = $Val = 0; 3017c478bd9Sstevel@tonic-gate foreach my $Line (@Mcs) { 3027c478bd9Sstevel@tonic-gate $Val++; 3037c478bd9Sstevel@tonic-gate 3046112cec5SJoshua M. Clulow if (($Val == 3) && ($Line !~ /^@\(#\)illumos/)) { 3057c478bd9Sstevel@tonic-gate $Con = 1; 3067c478bd9Sstevel@tonic-gate last; 3077c478bd9Sstevel@tonic-gate } 3086112cec5SJoshua M. Clulow if (($Val == 4) && ($Line =~ /^@\(#\)illumos/)) { 3097c478bd9Sstevel@tonic-gate $Dev = 1; 3107c478bd9Sstevel@tonic-gate next; 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate if (($Dev == 0) && ($Val == 4)) { 3137c478bd9Sstevel@tonic-gate $Con = 1; 3147c478bd9Sstevel@tonic-gate last; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate if (($Dev == 1) && ($Val == 5)) { 3177c478bd9Sstevel@tonic-gate $Con = 1; 3187c478bd9Sstevel@tonic-gate last; 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate if ($opt{m} && ($Con == 1)) { 32275ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 32375ce41a5SAli Bahrami "non-conforming mcs(1) comment\t<no \$(POST_PROCESS)?>"); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate # Applications should contain a non-executable stack definition. 32875ce41a5SAli Bahrami if (($Type eq 'EXEC') && ($Stack == 0) && 32975ce41a5SAli Bahrami (!defined($EXRE_exec_stack) || ($RelPath !~ $EXRE_exec_stack))) { 33075ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 33175ce41a5SAli Bahrami "non-executable stack required\t<no -Mmapfile_noexstk?>"); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3340910f6b5SRichard Lowe # Use ldd on dynamic objects unless it's a 64-bit object and we lack 3350910f6b5SRichard Lowe # the hardware. 3360910f6b5SRichard Lowe if (($Type ne 'REL') && (($Class == 32) || $Ena64)) { 337976d55c9Sab196087 my $LDDFullPath = $FullPath; 338976d55c9Sab196087 3397c478bd9Sstevel@tonic-gate if ($Secure) { 3407c478bd9Sstevel@tonic-gate # The execution of a secure application over an nfs file 3417c478bd9Sstevel@tonic-gate # system mounted nosuid will result in warning messages 3427c478bd9Sstevel@tonic-gate # being sent to /var/adm/messages. As this type of 3437c478bd9Sstevel@tonic-gate # environment can occur with root builds, move the file 3447c478bd9Sstevel@tonic-gate # being investigated to a safe place first. In addition 3457c478bd9Sstevel@tonic-gate # remove its secure permission so that it can be 3467c478bd9Sstevel@tonic-gate # influenced by any alternative dependency mappings. 3477c478bd9Sstevel@tonic-gate 34875ce41a5SAli Bahrami my $File = $RelPath; 34975ce41a5SAli Bahrami $File =~ s!^.*/!!; # basename 35075ce41a5SAli Bahrami 3517c478bd9Sstevel@tonic-gate my($TmpPath) = "$Tmpdir/$File"; 3527c478bd9Sstevel@tonic-gate 353976d55c9Sab196087 system('cp', $LDDFullPath, $TmpPath); 3547c478bd9Sstevel@tonic-gate chmod 0777, $TmpPath; 355976d55c9Sab196087 $LDDFullPath = $TmpPath; 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate # Use ldd(1) to determine the objects relocatability and use. 3597c478bd9Sstevel@tonic-gate # By default look for all unreferenced dependencies. However, 3607c478bd9Sstevel@tonic-gate # some objects have legitimate dependencies that they do not 3617c478bd9Sstevel@tonic-gate # reference. 36275ce41a5SAli Bahrami if ($LddNoU) { 3637c478bd9Sstevel@tonic-gate $Lddopt = "-ru"; 3647c478bd9Sstevel@tonic-gate } else { 3657c478bd9Sstevel@tonic-gate $Lddopt = "-rU"; 3667c478bd9Sstevel@tonic-gate } 367976d55c9Sab196087 @Ldd = split(/\n/, `ldd $Lddopt $Env $LDDFullPath 2>&1`); 3687c478bd9Sstevel@tonic-gate if ($Secure) { 369976d55c9Sab196087 unlink $LDDFullPath; 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate $Val = 0; 3747c478bd9Sstevel@tonic-gate $Sym = 5; 37567e3a03eSrie $UnDep = 1; 3767c478bd9Sstevel@tonic-gate 37767e3a03eSrie foreach my $Line (@Ldd) { 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate if ($Val == 0) { 3807c478bd9Sstevel@tonic-gate $Val = 1; 3817c478bd9Sstevel@tonic-gate # Make sure ldd(1) worked. One possible failure is that 3827c478bd9Sstevel@tonic-gate # this is an old ldd(1) prior to -e addition (4390308). 3837c478bd9Sstevel@tonic-gate if ($Line =~ /usage:/) { 3847c478bd9Sstevel@tonic-gate $Line =~ s/$/\t<old ldd(1)?>/; 38575ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, 38675ce41a5SAli Bahrami $RelPath, $Line); 3877c478bd9Sstevel@tonic-gate last; 3887c478bd9Sstevel@tonic-gate } elsif ($Line =~ /execution failed/) { 38975ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, 39075ce41a5SAli Bahrami $RelPath, $Line); 3917c478bd9Sstevel@tonic-gate last; 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate # It's possible this binary can't be executed, ie. we've 3957c478bd9Sstevel@tonic-gate # found a sparc binary while running on an intel system, 3967c478bd9Sstevel@tonic-gate # or a sparcv9 binary on a sparcv7/8 system. 3977c478bd9Sstevel@tonic-gate if ($Line =~ /wrong class/) { 39875ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 39975ce41a5SAli Bahrami "has wrong class or data encoding"); 4007c478bd9Sstevel@tonic-gate next; 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate # Historically, ldd(1) likes executable objects to have 40475ce41a5SAli Bahrami # their execute bit set. 4050910f6b5SRichard Lowe if (($Type eq 'EXEC' || $Type eq 'DYN' || 4060910f6b5SRichard Lowe $HasKMOD == 1) && (!(-x $FullPath))) { 40775ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 40875ce41a5SAli Bahrami "is not executable"); 4097c478bd9Sstevel@tonic-gate next; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate # Look for "file" or "versions" that aren't found. Note that 4147c478bd9Sstevel@tonic-gate # these lines will occur before we find any symbol referencing 4157c478bd9Sstevel@tonic-gate # errors. 4160910f6b5SRichard Lowe if (($Type ne 'REL') && ($Sym == 5) && ($Line =~ /not found\)/)) { 4177c478bd9Sstevel@tonic-gate if ($Line =~ /file not found\)/) { 4187c478bd9Sstevel@tonic-gate $Line =~ s/$/\t<no -zdefs?>/; 4197c478bd9Sstevel@tonic-gate } 42075ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line); 4217c478bd9Sstevel@tonic-gate next; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate # Look for relocations whose symbols can't be found. Note, we 4247c478bd9Sstevel@tonic-gate # only print out the first 5 relocations for any file as this 4257c478bd9Sstevel@tonic-gate # output can be excessive. 4260910f6b5SRichard Lowe if (($Type ne 'REL') && $Sym && ($Line =~ /symbol not found/)) { 4277c478bd9Sstevel@tonic-gate # Determine if this file is allowed undefined 4287c478bd9Sstevel@tonic-gate # references. 42975ce41a5SAli Bahrami if (($Sym == 5) && defined($EXRE_undef_ref) && 43075ce41a5SAli Bahrami ($RelPath =~ $EXRE_undef_ref)) { 4317c478bd9Sstevel@tonic-gate $Sym = 0; 43267e3a03eSrie next; 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate if ($Sym-- == 1) { 43575ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 43675ce41a5SAli Bahrami "continued ...") if !$opt{o}; 4377c478bd9Sstevel@tonic-gate next; 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate # Just print the symbol name. 4407c478bd9Sstevel@tonic-gate $Line =~ s/$/\t<no -zdefs?>/; 44175ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line); 4427c478bd9Sstevel@tonic-gate next; 4437c478bd9Sstevel@tonic-gate } 44467e3a03eSrie # Look for any unused search paths. 44567e3a03eSrie if ($Line =~ /unused search path=/) { 44675ce41a5SAli Bahrami next if defined($EXRE_unused_rpath) && 44775ce41a5SAli Bahrami ($Line =~ $EXRE_unused_rpath); 44875ce41a5SAli Bahrami 44967e3a03eSrie if ($Secure) { 45067e3a03eSrie $Line =~ s!$Tmpdir/!!; 45167e3a03eSrie } 45267e3a03eSrie $Line =~ s/^[ \t]*(.*)/\t$1\t<remove search path?>/; 45375ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line); 45467e3a03eSrie next; 45567e3a03eSrie } 4569e593677SRichard Lowe 45767e3a03eSrie # Look for unreferenced dependencies. Note, if any unreferenced 45867e3a03eSrie # objects are ignored, then set $UnDep so as to suppress any 45967e3a03eSrie # associated unused-object messages. 46067e3a03eSrie if ($Line =~ /unreferenced object=/) { 46175ce41a5SAli Bahrami if (defined($EXRE_unref_obj) && 46275ce41a5SAli Bahrami ($Line =~ $EXRE_unref_obj)) { 46367e3a03eSrie $UnDep = 0; 46467e3a03eSrie next; 46567e3a03eSrie } 46667e3a03eSrie if ($Secure) { 46767e3a03eSrie $Line =~ s!$Tmpdir/!!; 46867e3a03eSrie } 46975ce41a5SAli Bahrami $Line =~ s/^[ \t]*(.*)/$1\t<remove lib or -zignore?>/; 47075ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line); 47167e3a03eSrie next; 47267e3a03eSrie } 4737c478bd9Sstevel@tonic-gate # Look for any unused dependencies. 474*56acfad3SMarcel Telka if ($UnDep && ($Line =~ /unused .+=/)) { 47575ce41a5SAli Bahrami # Skip if object is allowed to have unused dependencies 47675ce41a5SAli Bahrami next if defined($EXRE_unused_deps) && 47775ce41a5SAli Bahrami ($RelPath =~ $EXRE_unused_deps); 47875ce41a5SAli Bahrami 47975ce41a5SAli Bahrami # Skip if dependency is always allowed to be unused 48075ce41a5SAli Bahrami next if defined($EXRE_unused_obj) && 48175ce41a5SAli Bahrami ($Line =~ $EXRE_unused_obj); 48275ce41a5SAli Bahrami 48375ce41a5SAli Bahrami $Line =~ s!$Tmpdir/!! if $Secure; 48475ce41a5SAli Bahrami $Line =~ s/^[ \t]*(.*)/$1\t<remove lib or -zignore?>/; 48575ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line); 4867c478bd9Sstevel@tonic-gate next; 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate # Reuse the elfdump(1) data to investigate additional dynamic linking 4917c478bd9Sstevel@tonic-gate # information. 4927c478bd9Sstevel@tonic-gate 493dfb96a4fSab196087 $Sun = $Relsz = $Pltsz = $Dyn = $Stab = $SymSort = 0; 4947c478bd9Sstevel@tonic-gate $Tex = $Strip = 1; 495f6acbf7cSrie $HasDirectBinding = 0; 4960910f6b5SRichard Lowe $HasKMOD = 0; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate $Header = 'None'; 4997c478bd9Sstevel@tonic-gateELF: foreach my $Line (@Elf) { 5007c478bd9Sstevel@tonic-gate # We're only interested in the section headers and the dynamic 5017c478bd9Sstevel@tonic-gate # section. 5027c478bd9Sstevel@tonic-gate if ($Line =~ /^Section Header/) { 5037c478bd9Sstevel@tonic-gate $Header = 'Shdr'; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate if (($Sun == 0) && ($Line =~ /\.SUNW_reloc/)) { 5067c478bd9Sstevel@tonic-gate # This object has a combined relocation section. 5077c478bd9Sstevel@tonic-gate $Sun = 1; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate } elsif (($Stab == 0) && ($Line =~ /\.stab/)) { 5107c478bd9Sstevel@tonic-gate # This object contain .stabs sections 5117c478bd9Sstevel@tonic-gate $Stab = 1; 512dfb96a4fSab196087 } elsif (($SymSort == 0) && 513dfb96a4fSab196087 ($Line =~ /\.SUNW_dyn(sym)|(tls)sort/)) { 514dfb96a4fSab196087 # This object contains a symbol sort section 515dfb96a4fSab196087 $SymSort = 1; 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate if (($Strip == 1) && ($Line =~ /\.symtab/)) { 5197c478bd9Sstevel@tonic-gate # This object contains a complete symbol table. 5207c478bd9Sstevel@tonic-gate $Strip = 0; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate next; 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate } elsif ($Line =~ /^Dynamic Section/) { 5257c478bd9Sstevel@tonic-gate $Header = 'Dyn'; 5267c478bd9Sstevel@tonic-gate next; 527f6acbf7cSrie } elsif ($Line =~ /^Syminfo Section/) { 528f6acbf7cSrie $Header = 'Syminfo'; 529f6acbf7cSrie next; 530f6acbf7cSrie } elsif (($Header ne 'Dyn') && ($Header ne 'Syminfo')) { 531f6acbf7cSrie next; 532f6acbf7cSrie } 533f6acbf7cSrie 534f6acbf7cSrie # Look into the Syminfo section. 535f6acbf7cSrie # Does this object have at least one Directly Bound symbol? 536f6acbf7cSrie if (($Header eq 'Syminfo')) { 537f6acbf7cSrie my(@Symword); 538f6acbf7cSrie 539f6acbf7cSrie if ($HasDirectBinding == 1) { 540f6acbf7cSrie next; 541f6acbf7cSrie } 542f6acbf7cSrie 543f6acbf7cSrie @Symword = split(' ', $Line); 544f6acbf7cSrie 545f6acbf7cSrie if (!defined($Symword[1])) { 546f6acbf7cSrie next; 547f6acbf7cSrie } 548f6acbf7cSrie if ($Symword[1] =~ /B/) { 549f6acbf7cSrie $HasDirectBinding = 1; 550f6acbf7cSrie } 5517c478bd9Sstevel@tonic-gate next; 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate # Does this object contain text relocations. 5550910f6b5SRichard Lowe if ($Tex && ($Type ne 'REL') && ($Line =~ /TEXTREL/)) { 5567c478bd9Sstevel@tonic-gate # Determine if this file is allowed text relocations. 55775ce41a5SAli Bahrami if (defined($EXRE_textrel) && 55875ce41a5SAli Bahrami ($RelPath =~ $EXRE_textrel)) { 5597c478bd9Sstevel@tonic-gate $Tex = 0; 5607c478bd9Sstevel@tonic-gate next ELF; 5617c478bd9Sstevel@tonic-gate } 56275ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 563532883abSRichard Lowe "TEXTREL .dynamic tag\t\t\t<no -fpic?>"); 5647c478bd9Sstevel@tonic-gate $Tex = 0; 5657c478bd9Sstevel@tonic-gate next; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate # Does this file have any relocation sections (there are a few 5697c478bd9Sstevel@tonic-gate # psr libraries with no relocations at all, thus a .SUNW_reloc 5707c478bd9Sstevel@tonic-gate # section won't exist either). 5717c478bd9Sstevel@tonic-gate if (($Relsz == 0) && ($Line =~ / RELA?SZ/)) { 5727c478bd9Sstevel@tonic-gate $Relsz = hex((split(' ', $Line))[2]); 5737c478bd9Sstevel@tonic-gate next; 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate # Does this file have any plt relocations. If the plt size is 5777c478bd9Sstevel@tonic-gate # equivalent to the total relocation size then we don't have 5787c478bd9Sstevel@tonic-gate # any relocations suitable for combining into a .SUNW_reloc 5797c478bd9Sstevel@tonic-gate # section. 5807c478bd9Sstevel@tonic-gate if (($Pltsz == 0) && ($Line =~ / PLTRELSZ/)) { 5817c478bd9Sstevel@tonic-gate $Pltsz = hex((split(' ', $Line))[2]); 5827c478bd9Sstevel@tonic-gate next; 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate # Does this object have any dependencies. 58667e3a03eSrie if ($Line =~ /NEEDED/) { 5877c478bd9Sstevel@tonic-gate my($Need) = (split(' ', $Line))[3]; 5887c478bd9Sstevel@tonic-gate 58975ce41a5SAli Bahrami if (defined($EXRE_olddep) && ($Need =~ $EXRE_olddep)) { 59067e3a03eSrie # Catch any old (unnecessary) dependencies. 59175ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 5929e593677SRichard Lowe "NEEDED=$Need\t<dependency no " . 5939e593677SRichard Lowe "longer necessary>"); 5949e593677SRichard Lowe } elsif ((defined($EXRE_forbidden) && 5959e593677SRichard Lowe ($Need =~ $EXRE_forbidden)) && 5969e593677SRichard Lowe (!defined($EXRE_forbidden_dep) || 5979e593677SRichard Lowe ($FullPath !~ $EXRE_forbidden_dep))) { 5989e593677SRichard Lowe onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 5999e593677SRichard Lowe "NEEDED=$Need\t<forbidden dependency, " . 6009e593677SRichard Lowe "missing -nodefaultlibs?>"); 60167e3a03eSrie } elsif ($opt{i}) { 60267e3a03eSrie # Under the -i (information) option print out 60367e3a03eSrie # any useful dynamic entries. 60475ce41a5SAli Bahrami onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath, 60575ce41a5SAli Bahrami "NEEDED=$Need"); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate next; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 610f6acbf7cSrie # Is this object built with -B direct flag on? 611f6acbf7cSrie if ($Line =~ / DIRECT /) { 612f6acbf7cSrie $HasDirectBinding = 1; 613f6acbf7cSrie } 614f6acbf7cSrie 6150910f6b5SRichard Lowe if (($Header eq 'Dyn') && ($Line =~ /SUNW_KMOD/)) { 6160910f6b5SRichard Lowe $HasKMOD = 1; 6170910f6b5SRichard Lowe } 6180910f6b5SRichard Lowe 6197c478bd9Sstevel@tonic-gate # Does this object specify a runpath. 6207c478bd9Sstevel@tonic-gate if ($opt{i} && ($Line =~ /RPATH/)) { 6217c478bd9Sstevel@tonic-gate my($Rpath) = (split(' ', $Line))[3]; 62275ce41a5SAli Bahrami onbld_elfmod::OutMsg($InfoFH, $InfoTtl, 62375ce41a5SAli Bahrami $RelPath, "RPATH=$Rpath"); 6247c478bd9Sstevel@tonic-gate next; 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate # A shared object, that contains non-plt relocations, should have a 6297c478bd9Sstevel@tonic-gate # combined relocation section indicating it was built with -z combreloc. 63075ce41a5SAli Bahrami if (($Type eq 'DYN') && $Relsz && ($Relsz != $Pltsz) && ($Sun == 0)) { 63175ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 6325253169eSAli Bahrami ".SUNW_reloc section missing\t\t<no -zcombreloc?>"); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6350910f6b5SRichard Lowe # A probable kernel module should be tagged 6360910f6b5SRichard Lowe if (($Type eq 'REL') && ($RelPath =~ qr{(^|/)kernel/}) && 6370910f6b5SRichard Lowe ($HasKMOD == 0)) { 6380910f6b5SRichard Lowe if (!defined($EXRE_not_kmod) || ($RelPath !~ $EXRE_not_kmod)) { 6390910f6b5SRichard Lowe onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 6400910f6b5SRichard Lowe "kernel object should be linked -ztype=kmod"); 6410910f6b5SRichard Lowe } 6420910f6b5SRichard Lowe } 6430910f6b5SRichard Lowe 6447c478bd9Sstevel@tonic-gate # No objects released to a customer should have any .stabs sections 6457c478bd9Sstevel@tonic-gate # remaining, they should be stripped. 6467c478bd9Sstevel@tonic-gate if ($opt{s} && $Stab) { 64775ce41a5SAli Bahrami goto DONESTAB if defined($EXRE_stab) && ($RelPath =~ $EXRE_stab); 64875ce41a5SAli Bahrami 64975ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 65075ce41a5SAli Bahrami "debugging sections should be deleted\t<no strip -x?>"); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 653f6acbf7cSrie # Identify an object that is not built with either -B direct or 654f6acbf7cSrie # -z direct. 65575ce41a5SAli Bahrami goto DONESTAB 65675ce41a5SAli Bahrami if (defined($EXRE_nodirect) && ($RelPath =~ $EXRE_nodirect)); 65775ce41a5SAli Bahrami 658f6acbf7cSrie if ($Relsz && ($HasDirectBinding == 0)) { 65975ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 66075ce41a5SAli Bahrami "object has no direct bindings\t<no -B direct or -z direct?>"); 661f6acbf7cSrie } 662f6acbf7cSrie 6637c478bd9Sstevel@tonic-gateDONESTAB: 6647c478bd9Sstevel@tonic-gate 6658ad60789Srie # All objects should have a full symbol table to provide complete 6667c478bd9Sstevel@tonic-gate # debugging stack traces. 66775ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 66875ce41a5SAli Bahrami "symbol table should not be stripped\t<remove -s?>") if $Strip; 669dfb96a4fSab196087 670dfb96a4fSab196087 # If there are symbol sort sections in this object, report on 671dfb96a4fSab196087 # any that have duplicate addresses. 67275ce41a5SAli Bahrami ProcSymSort($FullPath, $RelPath) if $SymSort; 673bfed486aSAli Bahrami 674bfed486aSAli Bahrami # If -v was specified, and the object has a version definition 675bfed486aSAli Bahrami # section, generate output showing each public symbol and the 676bfed486aSAli Bahrami # version it belongs to. 67775ce41a5SAli Bahrami ProcVerdef($FullPath, $RelPath) 67875ce41a5SAli Bahrami if ($Verdef eq 'VERDEF') && $opt{v}; 679dfb96a4fSab196087} 680dfb96a4fSab196087 681dfb96a4fSab196087 68275ce41a5SAli Bahrami## ProcSymSortOutMsg(RelPath, secname, addr, names...) 683dfb96a4fSab196087# 68475ce41a5SAli Bahrami# Call onbld_elfmod::OutMsg for a duplicate address error in a symbol sort 685dfb96a4fSab196087# section 686dfb96a4fSab196087# 687dfb96a4fSab196087sub ProcSymSortOutMsg { 68875ce41a5SAli Bahrami my($RelPath, $secname, $addr, @names) = @_; 689dfb96a4fSab196087 69075ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 691dfb96a4fSab196087 "$secname: duplicate $addr: ". join(', ', @names)); 692dfb96a4fSab196087} 693dfb96a4fSab196087 694dfb96a4fSab196087 695dfb96a4fSab196087## ProcSymSort(FullPath, RelPath) 696dfb96a4fSab196087# 697dfb96a4fSab196087# Examine the symbol sort sections for the given object and report 698dfb96a4fSab196087# on any duplicate addresses found. Ideally, mapfile directives 699dfb96a4fSab196087# should be used when building objects that have multiple symbols 700dfb96a4fSab196087# with the same address so that only one of them appears in the sort 701dfb96a4fSab196087# section. This saves space, reduces user confusion, and ensures that 702dfb96a4fSab196087# libproc and debuggers always display public names instead of symbols 703dfb96a4fSab196087# that are merely implementation details. 704dfb96a4fSab196087# 705dfb96a4fSab196087sub ProcSymSort { 706dfb96a4fSab196087 70775ce41a5SAli Bahrami my($FullPath, $RelPath) = @_; 708dfb96a4fSab196087 709dfb96a4fSab196087 # If this object is exempt from checking, return quietly 71075ce41a5SAli Bahrami return if defined($EXRE_nosymsort) && ($FullPath =~ $EXRE_nosymsort); 711dfb96a4fSab196087 712dfb96a4fSab196087 713dfb96a4fSab196087 open(SORT, "elfdump -S $FullPath|") || 714dfb96a4fSab196087 die "$Prog: Unable to execute elfdump (symbol sort sections)\n"; 715dfb96a4fSab196087 716dfb96a4fSab196087 my $line; 717dfb96a4fSab196087 my $last_addr; 718dfb96a4fSab196087 my @dups = (); 719dfb96a4fSab196087 my $secname; 720dfb96a4fSab196087 while ($line = <SORT>) { 721dfb96a4fSab196087 chomp $line; 722dfb96a4fSab196087 723dfb96a4fSab196087 next if ($line eq ''); 724dfb96a4fSab196087 725dfb96a4fSab196087 # If this is a header line, pick up the section name 726dfb96a4fSab196087 if ($line =~ /^Symbol Sort Section:\s+([^\s]+)\s+/) { 727dfb96a4fSab196087 $secname = $1; 728dfb96a4fSab196087 729dfb96a4fSab196087 # Every new section is followed by a column header line 730dfb96a4fSab196087 $line = <SORT>; # Toss header line 731dfb96a4fSab196087 732dfb96a4fSab196087 # Flush anything left from previous section 73375ce41a5SAli Bahrami ProcSymSortOutMsg($RelPath, $secname, $last_addr, @dups) 73475ce41a5SAli Bahrami if (scalar(@dups) > 1); 735dfb96a4fSab196087 736dfb96a4fSab196087 # Reset variables for new sort section 737dfb96a4fSab196087 $last_addr = ''; 738dfb96a4fSab196087 @dups = (); 739dfb96a4fSab196087 740dfb96a4fSab196087 next; 741dfb96a4fSab196087 } 742dfb96a4fSab196087 743dfb96a4fSab196087 # Process symbol line 744dfb96a4fSab196087 my @fields = split /\s+/, $line; 745dfb96a4fSab196087 my $new_addr = $fields[2]; 746169e20d9SAli Bahrami my $new_type = $fields[8]; 747dfb96a4fSab196087 my $new_name = $fields[9]; 748607c61fdSab196087 749169e20d9SAli Bahrami if ($new_type eq 'UNDEF') { 75075ce41a5SAli Bahrami onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, 751169e20d9SAli Bahrami "$secname: unexpected UNDEF symbol " . 752169e20d9SAli Bahrami "(link-editor error): $new_name"); 753169e20d9SAli Bahrami next; 754169e20d9SAli Bahrami } 755169e20d9SAli Bahrami 756a854c1c1Sab196087 if ($new_addr eq $last_addr) { 757dfb96a4fSab196087 push @dups, $new_name; 758dfb96a4fSab196087 } else { 75975ce41a5SAli Bahrami ProcSymSortOutMsg($RelPath, $secname, 760dfb96a4fSab196087 $last_addr, @dups) if (scalar(@dups) > 1); 761dfb96a4fSab196087 @dups = ( $new_name ); 762dfb96a4fSab196087 $last_addr = $new_addr; 763dfb96a4fSab196087 } 764dfb96a4fSab196087 } 765dfb96a4fSab196087 76675ce41a5SAli Bahrami ProcSymSortOutMsg($RelPath, $secname, $last_addr, @dups) 767dfb96a4fSab196087 if (scalar(@dups) > 1); 768dfb96a4fSab196087 769dfb96a4fSab196087 close SORT; 7707c478bd9Sstevel@tonic-gate} 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate 773bfed486aSAli Bahrami## ProcVerdef(FullPath, RelPath) 774bfed486aSAli Bahrami# 775bfed486aSAli Bahrami# Examine the version definition section for the given object and report 776bfed486aSAli Bahrami# each public symbol along with the version it belongs to. 777bfed486aSAli Bahrami# 778bfed486aSAli Bahramisub ProcVerdef { 779bfed486aSAli Bahrami 78075ce41a5SAli Bahrami my($FullPath, $RelPath) = @_; 781bfed486aSAli Bahrami my $line; 782bfed486aSAli Bahrami my $cur_ver = ''; 783bfed486aSAli Bahrami my $tab = $opt{o} ? '' : "\t"; 784bfed486aSAli Bahrami 785bfed486aSAli Bahrami # pvs -dov provides information about the versioning hierarchy 786bfed486aSAli Bahrami # in the file. Lines are of the format: 787bfed486aSAli Bahrami # path - version[XXX]; 788bfed486aSAli Bahrami # where [XXX] indicates optional information, such as flags 789bfed486aSAli Bahrami # or inherited versions. 790bfed486aSAli Bahrami # 791bfed486aSAli Bahrami # Private versions are allowed to change freely, so ignore them. 792bfed486aSAli Bahrami open(PVS, "pvs -dov $FullPath|") || 793bfed486aSAli Bahrami die "$Prog: Unable to execute pvs (version definition section)\n"; 794bfed486aSAli Bahrami 795bfed486aSAli Bahrami while ($line = <PVS>) { 796bfed486aSAli Bahrami chomp $line; 797bfed486aSAli Bahrami 798bfed486aSAli Bahrami if ($line =~ /^[^\s]+\s+-\s+([^;]+)/) { 799bfed486aSAli Bahrami my $ver = $1; 800bfed486aSAli Bahrami 801bfed486aSAli Bahrami next if $ver =~ /private/i; 80275ce41a5SAli Bahrami onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath, 80375ce41a5SAli Bahrami "${tab}VERDEF=$ver"); 804bfed486aSAli Bahrami } 805bfed486aSAli Bahrami } 806bfed486aSAli Bahrami close PVS; 807bfed486aSAli Bahrami 808bfed486aSAli Bahrami # pvs -dos lists the symbols assigned to each version definition. 809bfed486aSAli Bahrami # Lines are of the format: 810bfed486aSAli Bahrami # path - version: symbol; 811bfed486aSAli Bahrami # path - version: symbol (size); 812bfed486aSAli Bahrami # where the (size) is added to data items, but not for functions. 813bfed486aSAli Bahrami # We strip off the size, if present. 814bfed486aSAli Bahrami 815bfed486aSAli Bahrami open(PVS, "pvs -dos $FullPath|") || 816bfed486aSAli Bahrami die "$Prog: Unable to execute pvs (version definition section)\n"; 817bfed486aSAli Bahrami while ($line = <PVS>) { 818bfed486aSAli Bahrami chomp $line; 819bfed486aSAli Bahrami if ($line =~ /^[^\s]+\s+-\s+([^:]+):\s*([^\s;]+)/) { 820bfed486aSAli Bahrami my $ver = $1; 821bfed486aSAli Bahrami my $sym = $2; 822bfed486aSAli Bahrami 823bfed486aSAli Bahrami next if $ver =~ /private/i; 824bfed486aSAli Bahrami 825bfed486aSAli Bahrami if ($opt{o}) { 82675ce41a5SAli Bahrami onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath, 827bfed486aSAli Bahrami "VERSION=$ver, SYMBOL=$sym"); 828bfed486aSAli Bahrami } else { 829bfed486aSAli Bahrami if ($cur_ver ne $ver) { 83075ce41a5SAli Bahrami onbld_elfmod::OutMsg($InfoFH, $InfoTtl, 83175ce41a5SAli Bahrami $RelPath, "VERSION=$ver"); 832bfed486aSAli Bahrami $cur_ver = $ver; 833bfed486aSAli Bahrami } 83475ce41a5SAli Bahrami onbld_elfmod::OutMsg($InfoFH, $InfoTtl, 83575ce41a5SAli Bahrami $RelPath, "SYMBOL=$sym"); 836bfed486aSAli Bahrami } 837bfed486aSAli Bahrami } 838bfed486aSAli Bahrami } 839bfed486aSAli Bahrami 840bfed486aSAli Bahrami close PVS; 841bfed486aSAli Bahrami} 842bfed486aSAli Bahrami 843bfed486aSAli Bahrami 84475ce41a5SAli Bahrami## OpenFindElf(file, FileHandleRef, LineNumRef) 84575ce41a5SAli Bahrami# 84675ce41a5SAli Bahrami# Open file in 'find_elf -r' format, and return the value of 84775ce41a5SAli Bahrami# the opening PREFIX line. 84875ce41a5SAli Bahrami# 84975ce41a5SAli Bahrami# entry: 85075ce41a5SAli Bahrami# file - file, or find_elf child process, to open 85175ce41a5SAli Bahrami# FileHandleRef - Reference to file handle to open 85275ce41a5SAli Bahrami# LineNumRef - Reference to integer to increment as lines are input 85375ce41a5SAli Bahrami# 85475ce41a5SAli Bahrami# exit: 85575ce41a5SAli Bahrami# This routine issues a fatal error and does not return on error. 85675ce41a5SAli Bahrami# Otherwise, the value of PREFIX is returned. 85775ce41a5SAli Bahrami# 85875ce41a5SAli Bahramisub OpenFindElf { 85975ce41a5SAli Bahrami my ($file, $fh, $LineNum) = @_; 86075ce41a5SAli Bahrami my $line; 86175ce41a5SAli Bahrami my $prefix; 8627c478bd9Sstevel@tonic-gate 86375ce41a5SAli Bahrami open($fh, $file) || die "$Prog: Unable to open: $file"; 86475ce41a5SAli Bahrami $$LineNum = 0; 86575ce41a5SAli Bahrami 86675ce41a5SAli Bahrami # This script requires relative paths as created by 'find_elf -r'. 86775ce41a5SAli Bahrami # When this is done, the first non-comment line will always 86875ce41a5SAli Bahrami # be PREFIX. Obtain that line, or issue a fatal error. 86975ce41a5SAli Bahrami while ($line = onbld_elfmod::GetLine($fh, $LineNum)) { 87075ce41a5SAli Bahrami if ($line =~ /^PREFIX\s+(.*)$/i) { 87175ce41a5SAli Bahrami $prefix = $1; 87275ce41a5SAli Bahrami last; 8737c478bd9Sstevel@tonic-gate } 8747c478bd9Sstevel@tonic-gate 87575ce41a5SAli Bahrami die "$Prog: No PREFIX line seen on line $$LineNum: $file"; 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate 87875ce41a5SAli Bahrami $prefix; 8797c478bd9Sstevel@tonic-gate} 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate 88275ce41a5SAli Bahrami## ProcFindElf(file) 88375ce41a5SAli Bahrami# 88475ce41a5SAli Bahrami# Open the specified file, which must be produced by "find_elf -r", 88575ce41a5SAli Bahrami# and process the files it describes. 88675ce41a5SAli Bahrami# 88775ce41a5SAli Bahramisub ProcFindElf { 88875ce41a5SAli Bahrami my $file = $_[0]; 88975ce41a5SAli Bahrami my $line; 89075ce41a5SAli Bahrami my $LineNum; 89175ce41a5SAli Bahrami 89275ce41a5SAli Bahrami my $prefix = OpenFindElf($file, \*FIND_ELF, \$LineNum); 89375ce41a5SAli Bahrami 89475ce41a5SAli Bahrami while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) { 89575ce41a5SAli Bahrami next if !($line =~ /^OBJECT\s/i); 89675ce41a5SAli Bahrami 89775ce41a5SAli Bahrami my ($item, $class, $type, $verdef, $obj) = 89875ce41a5SAli Bahrami split(/\s+/, $line, 5); 89975ce41a5SAli Bahrami 90075ce41a5SAli Bahrami ProcFile("$prefix/$obj", $obj, $class, $type, $verdef); 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 90375ce41a5SAli Bahrami close FIND_ELF; 9047c478bd9Sstevel@tonic-gate} 9057c478bd9Sstevel@tonic-gate 90675ce41a5SAli Bahrami 90775ce41a5SAli Bahrami## AltObjectConfig(file) 90875ce41a5SAli Bahrami# 90975ce41a5SAli Bahrami# Recurse through a directory hierarchy looking for appropriate dependencies 91075ce41a5SAli Bahrami# to map from their standard system locations to the proto area via a crle 91175ce41a5SAli Bahrami# config file. 91275ce41a5SAli Bahrami# 91375ce41a5SAli Bahrami# entry: 91475ce41a5SAli Bahrami# file - File of ELF objects, in 'find_elf -r' format, to examine. 91575ce41a5SAli Bahrami# 91675ce41a5SAli Bahrami# exit: 91775ce41a5SAli Bahrami# Scripts are generated for the 32 and 64-bit cases to run crle 91875ce41a5SAli Bahrami# and create runtime configuration files that will establish 91975ce41a5SAli Bahrami# alternative dependency mappings for the objects identified. 92075ce41a5SAli Bahrami# 92175ce41a5SAli Bahrami# $Env - Set to environment variable definitions that will cause 92275ce41a5SAli Bahrami# the config files generated by this routine to be used 92375ce41a5SAli Bahrami# by ldd. 92475ce41a5SAli Bahrami# $Conf32, $Conf64 - Undefined, or set to the config files generated 92575ce41a5SAli Bahrami# by this routine. If defined, the caller is responsible for 92675ce41a5SAli Bahrami# unlinking the files before exiting. 92775ce41a5SAli Bahrami# 92875ce41a5SAli Bahramisub AltObjectConfig { 92975ce41a5SAli Bahrami my $file = $_[0]; 93075ce41a5SAli Bahrami my ($Crle32, $Crle64); 93175ce41a5SAli Bahrami my $line; 93275ce41a5SAli Bahrami my $LineNum; 93375ce41a5SAli Bahrami my $obj_path; 93475ce41a5SAli Bahrami my $obj_active = 0; 93575ce41a5SAli Bahrami my $obj_class; 93675ce41a5SAli Bahrami 93775ce41a5SAli Bahrami my $prefix = OpenFindElf($file, \*FIND_ELF); 93875ce41a5SAli Bahrami 93975ce41a5SAli BahramiLINE: 94075ce41a5SAli Bahrami while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) { 94175ce41a5SAli Bahrami ITEM: { 94275ce41a5SAli Bahrami 94375ce41a5SAli Bahrami if ($line =~ /^OBJECT\s/i) { 94475ce41a5SAli Bahrami my ($item, $class, $type, $verdef, $obj) = 94575ce41a5SAli Bahrami split(/\s+/, $line, 5); 94675ce41a5SAli Bahrami 94775ce41a5SAli Bahrami if ($type eq 'DYN') { 94875ce41a5SAli Bahrami $obj_active = 1; 94975ce41a5SAli Bahrami $obj_path = $obj; 95075ce41a5SAli Bahrami $obj_class = $class; 95175ce41a5SAli Bahrami } else { 95275ce41a5SAli Bahrami # Only want sharable objects 95375ce41a5SAli Bahrami $obj_active = 0; 9547c478bd9Sstevel@tonic-gate } 95575ce41a5SAli Bahrami last ITEM; 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 95875ce41a5SAli Bahrami # We need to follow links to sharable objects so 95975ce41a5SAli Bahrami # that any dependencies are expressed in all their 96075ce41a5SAli Bahrami # available forms. We depend on ALIAS lines directly 96175ce41a5SAli Bahrami # following the object they alias, so if we have 96275ce41a5SAli Bahrami # a current object, this alias belongs to it. 96375ce41a5SAli Bahrami if ($obj_active && ($line =~ /^ALIAS\s/i)) { 96475ce41a5SAli Bahrami my ($item, $real_obj, $obj) = 96575ce41a5SAli Bahrami split(/\s+/, $line, 3); 96675ce41a5SAli Bahrami $obj_path = $obj; 96775ce41a5SAli Bahrami last ITEM; 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 97075ce41a5SAli Bahrami # Skip unrecognized item 97175ce41a5SAli Bahrami next LINE; 97275ce41a5SAli Bahrami } 9737c478bd9Sstevel@tonic-gate 97475ce41a5SAli Bahrami next if !$obj_active; 9757c478bd9Sstevel@tonic-gate 97675ce41a5SAli Bahrami my $full = "$prefix/$obj_path"; 97775ce41a5SAli Bahrami 97875ce41a5SAli Bahrami next if defined($EXRE_nocrlealt) && 97975ce41a5SAli Bahrami ($obj_path =~ $EXRE_nocrlealt); 98075ce41a5SAli Bahrami 98175ce41a5SAli Bahrami my $Dir = $full; 98275ce41a5SAli Bahrami $Dir =~ s/^(.*)\/.*$/$1/; 98375ce41a5SAli Bahrami 98475ce41a5SAli Bahrami # Create a crle(1) script for the dependency we've found. 98575ce41a5SAli Bahrami # We build separate scripts for the 32 and 64-bit cases. 98675ce41a5SAli Bahrami # We create and initialize each script when we encounter 98775ce41a5SAli Bahrami # the first object that needs it. 98875ce41a5SAli Bahrami if ($obj_class == 32) { 9897c478bd9Sstevel@tonic-gate if (!$Crle32) { 9907c478bd9Sstevel@tonic-gate $Crle32 = "$Tmpdir/$Prog.crle32.$$"; 9917c478bd9Sstevel@tonic-gate open(CRLE32, "> $Crle32") || 9927c478bd9Sstevel@tonic-gate die "$Prog: open failed: $Crle32: $!"; 9937c478bd9Sstevel@tonic-gate print CRLE32 "#!/bin/sh\ncrle \\\n"; 9947c478bd9Sstevel@tonic-gate } 99575ce41a5SAli Bahrami print CRLE32 "\t-o $Dir -a /$obj_path \\\n"; 99675ce41a5SAli Bahrami } elsif ($Ena64) { 99775ce41a5SAli Bahrami if (!$Crle64) { 99875ce41a5SAli Bahrami $Crle64 = "$Tmpdir/$Prog.crle64.$$"; 99975ce41a5SAli Bahrami open(CRLE64, "> $Crle64") || 100075ce41a5SAli Bahrami die "$Prog: open failed: $Crle64: $!"; 100175ce41a5SAli Bahrami print CRLE64 "#!/bin/sh\ncrle -64\\\n"; 100275ce41a5SAli Bahrami } 100375ce41a5SAli Bahrami print CRLE64 "\t-o $Dir -a /$obj_path \\\n"; 100475ce41a5SAli Bahrami } 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate 100775ce41a5SAli Bahrami close FIND_ELF; 10087c478bd9Sstevel@tonic-gate 100975ce41a5SAli Bahrami 101075ce41a5SAli Bahrami # Now that the config scripts are complete, use them to generate 101175ce41a5SAli Bahrami # runtime linker config files. 10127c478bd9Sstevel@tonic-gate if ($Crle64) { 10137c478bd9Sstevel@tonic-gate $Conf64 = "$Tmpdir/$Prog.conf64.$$"; 10147c478bd9Sstevel@tonic-gate print CRLE64 "\t-c $Conf64\n"; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate chmod 0755, $Crle64; 10177c478bd9Sstevel@tonic-gate close CRLE64; 10187c478bd9Sstevel@tonic-gate 101975ce41a5SAli Bahrami undef $Conf64 if system($Crle64); 102075ce41a5SAli Bahrami 102175ce41a5SAli Bahrami # Done with the script 102275ce41a5SAli Bahrami unlink $Crle64; 10237c478bd9Sstevel@tonic-gate } 10247c478bd9Sstevel@tonic-gate if ($Crle32) { 10257c478bd9Sstevel@tonic-gate $Conf32 = "$Tmpdir/$Prog.conf32.$$"; 10267c478bd9Sstevel@tonic-gate print CRLE32 "\t-c $Conf32\n"; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate chmod 0755, $Crle32; 10297c478bd9Sstevel@tonic-gate close CRLE32; 10307c478bd9Sstevel@tonic-gate 103175ce41a5SAli Bahrami undef $Conf32 if system($Crle32); 103275ce41a5SAli Bahrami 103375ce41a5SAli Bahrami # Done with the script 103475ce41a5SAli Bahrami unlink $Crle32; 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 103775ce41a5SAli Bahrami # Set $Env so that we will use the config files generated above 103875ce41a5SAli Bahrami # when we run ldd. 10397c478bd9Sstevel@tonic-gate if ($Crle64 && $Conf64 && $Crle32 && $Conf32) { 10407c478bd9Sstevel@tonic-gate $Env = "-e LD_FLAGS=config_64=$Conf64,config_32=$Conf32"; 10417c478bd9Sstevel@tonic-gate } elsif ($Crle64 && $Conf64) { 10427c478bd9Sstevel@tonic-gate $Env = "-e LD_FLAGS=config_64=$Conf64"; 10437c478bd9Sstevel@tonic-gate } elsif ($Crle32 && $Conf32) { 10447c478bd9Sstevel@tonic-gate $Env = "-e LD_FLAGS=config_32=$Conf32"; 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate} 10477c478bd9Sstevel@tonic-gate 104875ce41a5SAli Bahrami# ----------------------------------------------------------------------------- 10497c478bd9Sstevel@tonic-gate 105075ce41a5SAli Bahrami# This script relies on ldd returning output reflecting only the binary 105175ce41a5SAli Bahrami# contents. But if LD_PRELOAD* environment variables are present, libraries 105275ce41a5SAli Bahrami# named by them will also appear in the output, disrupting our analysis. 105375ce41a5SAli Bahrami# So, before we get too far, scrub the environment. 10547c478bd9Sstevel@tonic-gate 105575ce41a5SAli Bahramidelete($ENV{LD_PRELOAD}); 105675ce41a5SAli Bahramidelete($ENV{LD_PRELOAD_32}); 105775ce41a5SAli Bahramidelete($ENV{LD_PRELOAD_64}); 10587c478bd9Sstevel@tonic-gate 105975ce41a5SAli Bahrami# Establish a program name for any error diagnostics. 106075ce41a5SAli Bahramichomp($Prog = `basename $0`); 10617c478bd9Sstevel@tonic-gate 106275ce41a5SAli Bahrami# The onbld_elfmod package is maintained in the same directory as this 106375ce41a5SAli Bahrami# script, and is installed in ../lib/perl. Use the local one if present, 106475ce41a5SAli Bahrami# and the installed one otherwise. 106575ce41a5SAli Bahramimy $moddir = dirname($0); 106675ce41a5SAli Bahrami$moddir = "$moddir/../lib/perl" if ! -f "$moddir/onbld_elfmod.pm"; 106775ce41a5SAli Bahramirequire "$moddir/onbld_elfmod.pm"; 106875ce41a5SAli Bahrami 106975ce41a5SAli Bahrami# Determine what machinery is available. 107075ce41a5SAli Bahramimy $Mach = `uname -p`; 107175ce41a5SAli Bahramimy$Isalist = `isalist`; 107275ce41a5SAli Bahramiif ($Mach =~ /sparc/) { 107375ce41a5SAli Bahrami if ($Isalist =~ /sparcv9/) { 107475ce41a5SAli Bahrami $Ena64 = "ok"; 107575ce41a5SAli Bahrami } 107675ce41a5SAli Bahrami} elsif ($Mach =~ /i386/) { 107775ce41a5SAli Bahrami if ($Isalist =~ /amd64/) { 107875ce41a5SAli Bahrami $Ena64 = "ok"; 10794840e086Srie } 10804840e086Srie} 10814840e086Srie 108275ce41a5SAli Bahrami# $Env is used with all calls to ldd. It is set by AltObjectConfig to 108375ce41a5SAli Bahrami# cause an alternate object mapping runtime config file to be used. 108475ce41a5SAli Bahrami$Env = ''; 10857c478bd9Sstevel@tonic-gate 108675ce41a5SAli Bahrami# Check that we have arguments. 108775ce41a5SAli Bahramiif ((getopts('D:d:E:e:f:I:imosvw:', \%opt) == 0) || 108875ce41a5SAli Bahrami (!$opt{f} && ($#ARGV == -1))) { 108975ce41a5SAli Bahrami print "usage: $Prog [-imosv] [-D depfile | -d depdir] [-E errfile]\n"; 109075ce41a5SAli Bahrami print "\t\t[-e exfile] [-f listfile] [-I infofile] [-w outdir]\n"; 109175ce41a5SAli Bahrami print "\t\t[file | dir]...\n"; 109275ce41a5SAli Bahrami print "\n"; 109375ce41a5SAli Bahrami print "\t[-D depfile]\testablish dependencies from 'find_elf -r' file list\n"; 109475ce41a5SAli Bahrami print "\t[-d depdir]\testablish dependencies from under directory\n"; 109575ce41a5SAli Bahrami print "\t[-E errfile]\tdirect error output to file\n"; 109675ce41a5SAli Bahrami print "\t[-e exfile]\texceptions file\n"; 109775ce41a5SAli Bahrami print "\t[-f listfile]\tuse file list produced by find_elf -r\n"; 109875ce41a5SAli Bahrami print "\t[-I infofile]\tdirect informational output (-i, -v) to file\n"; 109975ce41a5SAli Bahrami print "\t[-i]\t\tproduce dynamic table entry information\n"; 110075ce41a5SAli Bahrami print "\t[-m]\t\tprocess mcs(1) comments\n"; 110175ce41a5SAli Bahrami print "\t[-o]\t\tproduce one-liner output (prefixed with pathname)\n"; 110275ce41a5SAli Bahrami print "\t[-s]\t\tprocess .stab and .symtab entries\n"; 110375ce41a5SAli Bahrami print "\t[-v]\t\tprocess version definition entries\n"; 110475ce41a5SAli Bahrami print "\t[-w outdir]\tinterpret all files relative to given directory\n"; 110575ce41a5SAli Bahrami exit 1; 110675ce41a5SAli Bahrami} 110775ce41a5SAli Bahrami 110875ce41a5SAli Bahramidie "$Prog: -D and -d options are mutually exclusive\n" if ($opt{D} && $opt{d}); 110975ce41a5SAli Bahrami 111075ce41a5SAli Bahrami$Tmpdir = "/tmp" if (!($Tmpdir = $ENV{TMPDIR}) || (! -d $Tmpdir)); 111175ce41a5SAli Bahrami 111275ce41a5SAli Bahrami# If -w, change working directory to given location 111375ce41a5SAli Bahrami!$opt{w} || chdir($opt{w}) || die "$Prog: can't cd to $opt{w}"; 111475ce41a5SAli Bahrami 111575ce41a5SAli Bahrami# Locate and process the exceptions file 111675ce41a5SAli Bahramionbld_elfmod::LoadExceptionsToEXRE('check_rtime'); 111775ce41a5SAli Bahrami 111875ce41a5SAli Bahrami# Is there a proto area available, either via the -d option, or because 111975ce41a5SAli Bahrami# we are part of an activated workspace? 112075ce41a5SAli Bahramimy $Proto; 112175ce41a5SAli Bahramiif ($opt{d}) { 112275ce41a5SAli Bahrami # User specified dependency directory - make sure it exists. 112375ce41a5SAli Bahrami -d $opt{d} || die "$Prog: $opt{d} is not a directory\n"; 112475ce41a5SAli Bahrami $Proto = $opt{d}; 112575ce41a5SAli Bahrami} elsif ($ENV{CODEMGR_WS}) { 112675ce41a5SAli Bahrami my $Root; 112775ce41a5SAli Bahrami 112875ce41a5SAli Bahrami # Without a user specified dependency directory see if we're 112975ce41a5SAli Bahrami # part of a codemanager workspace and if a proto area exists. 113075ce41a5SAli Bahrami $Proto = $Root if ($Root = $ENV{ROOT}) && (-d $Root); 113175ce41a5SAli Bahrami} 113275ce41a5SAli Bahrami 113375ce41a5SAli Bahrami# If we are basing this analysis off the sharable objects found in 113475ce41a5SAli Bahrami# a proto area, then gather dependencies and construct an alternative 113575ce41a5SAli Bahrami# dependency mapping via a crle(1) configuration file. 113675ce41a5SAli Bahrami# 113775ce41a5SAli Bahrami# To support alternative dependency mapping we'll need ldd(1)'s 113875ce41a5SAli Bahrami# -e option. This is relatively new (s81_30), so make sure 113975ce41a5SAli Bahrami# ldd(1) is capable before gathering any dependency information. 114075ce41a5SAli Bahramiif ($opt{D} || $Proto) { 114175ce41a5SAli Bahrami if (system('ldd -e /usr/lib/lddstub 2> /dev/null')) { 114275ce41a5SAli Bahrami print "ldd: does not support -e, unable to "; 114375ce41a5SAli Bahrami print "create alternative dependency mappingings.\n"; 114475ce41a5SAli Bahrami print "ldd: option added under 4390308 (s81_30).\n\n"; 11457c478bd9Sstevel@tonic-gate } else { 114675ce41a5SAli Bahrami # If -D was specified, it supplies a list of files in 114775ce41a5SAli Bahrami # 'find_elf -r' format, and can use it directly. Otherwise, 114875ce41a5SAli Bahrami # we will run find_elf as a child process to find the 114975ce41a5SAli Bahrami # sharable objects found under $Proto. 115075ce41a5SAli Bahrami AltObjectConfig($opt{D} ? $opt{D} : "find_elf -frs $Proto|"); 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate} 11537c478bd9Sstevel@tonic-gate 115475ce41a5SAli Bahrami# To support unreferenced dependency detection we'll need ldd(1)'s -U 115575ce41a5SAli Bahrami# option. This is relatively new (4638070), and if not available we 115675ce41a5SAli Bahrami# can still fall back to -u. Even with this option, don't use -U with 115775ce41a5SAli Bahrami# releases prior to 5.10 as the cleanup for -U use only got integrated 115875ce41a5SAli Bahrami# into 5.10 under 4642023. Note, that nightly doesn't typically set a 115975ce41a5SAli Bahrami# RELEASE from the standard <env> files. Users who wish to disable use 116075ce41a5SAli Bahrami# of ldd(1)'s -U should set (or uncomment) RELEASE in their <env> file 116175ce41a5SAli Bahrami# if using nightly, or otherwise establish it in their environment. 116275ce41a5SAli Bahramiif (system('ldd -U /usr/lib/lddstub 2> /dev/null')) { 116375ce41a5SAli Bahrami $LddNoU = 1; 116475ce41a5SAli Bahrami} else { 116575ce41a5SAli Bahrami my($Release); 116675ce41a5SAli Bahrami 116775ce41a5SAli Bahrami if (($Release = $ENV{RELEASE}) && (cmp_os_ver($Release, "<", "5.10"))) { 116875ce41a5SAli Bahrami $LddNoU = 1; 116975ce41a5SAli Bahrami } else { 117075ce41a5SAli Bahrami $LddNoU = 0; 117175ce41a5SAli Bahrami } 11727c478bd9Sstevel@tonic-gate} 11737c478bd9Sstevel@tonic-gate 117475ce41a5SAli Bahrami# Set up variables used to handle output files: 117575ce41a5SAli Bahrami# 117675ce41a5SAli Bahrami# Error messages go to stdout unless -E is specified. $ErrFH is a 117775ce41a5SAli Bahrami# file handle reference that points at the file handle where error messages 117875ce41a5SAli Bahrami# are sent, and $ErrTtl is a reference that points at an integer used 117975ce41a5SAli Bahrami# to count how many lines have been sent there. 118075ce41a5SAli Bahrami# 118175ce41a5SAli Bahrami# Informational messages go to stdout unless -I is specified. $InfoFH is a 118275ce41a5SAli Bahrami# file handle reference that points at the file handle where info messages 118375ce41a5SAli Bahrami# are sent, and $InfoTtl is a reference that points at an integer used 118475ce41a5SAli Bahrami# to count how many lines have been sent there. 118575ce41a5SAli Bahrami# 118675ce41a5SAli Bahramiif ($opt{E}) { 118775ce41a5SAli Bahrami open(ERROR, ">$opt{E}") || die "$Prog: open failed: $opt{E}"; 118875ce41a5SAli Bahrami $ErrFH = \*ERROR; 118975ce41a5SAli Bahrami} else { 119075ce41a5SAli Bahrami $ErrFH = \*STDOUT; 11917c478bd9Sstevel@tonic-gate} 119275ce41a5SAli Bahrami 119375ce41a5SAli Bahramiif ($opt{I}) { 119475ce41a5SAli Bahrami open(INFO, ">$opt{I}") || die "$Prog: open failed: $opt{I}"; 119575ce41a5SAli Bahrami $InfoFH = \*INFO; 119675ce41a5SAli Bahrami} else { 119775ce41a5SAli Bahrami $InfoFH = \*STDOUT; 11987c478bd9Sstevel@tonic-gate} 119975ce41a5SAli Bahramimy ($err_dev, $err_ino) = stat($ErrFH); 120075ce41a5SAli Bahramimy ($info_dev, $info_ino) = stat($InfoFH); 120175ce41a5SAli Bahrami$ErrTtl = \$OutCnt1; 120275ce41a5SAli Bahrami$InfoTtl = (($err_dev == $info_dev) && ($err_ino == $info_ino)) ? 120375ce41a5SAli Bahrami \$OutCnt1 : \$OutCnt2; 120475ce41a5SAli Bahrami 120575ce41a5SAli Bahrami 120675ce41a5SAli Bahrami# If we were given a list of objects in 'find_elf -r' format, then 120775ce41a5SAli Bahrami# process it. 120875ce41a5SAli BahramiProcFindElf($opt{f}) if $opt{f}; 120975ce41a5SAli Bahrami 121075ce41a5SAli Bahrami# Process each argument 121175ce41a5SAli Bahramiforeach my $Arg (@ARGV) { 121275ce41a5SAli Bahrami # Run find_elf to find the files given by $Arg and process them 121375ce41a5SAli Bahrami ProcFindElf("find_elf -fr $Arg|"); 12147c478bd9Sstevel@tonic-gate} 121575ce41a5SAli Bahrami 121675ce41a5SAli Bahrami# Cleanup output files 121775ce41a5SAli Bahramiunlink $Conf64 if $Conf64; 121875ce41a5SAli Bahramiunlink $Conf32 if $Conf32; 121975ce41a5SAli Bahramiclose ERROR if $opt{E}; 122075ce41a5SAli Bahramiclose INFO if $opt{I}; 122175ce41a5SAli Bahrami 122275ce41a5SAli Bahramiexit 0; 1223