#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos720 src/bos/usr/ccs/bin/rtl_enable/POWER/rtl_enable.sh 1.10 # # Licensed Materials - Property of IBM # # Restricted Materials of IBM # # COPYRIGHT International Business Machines Corp. 1996,2007 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # @(#)93 1.10 src/bos/usr/ccs/bin/rtl_enable/POWER/rtl_enable.sh, cmdld, bos720 3/29/07 04:11:32 # # COMPONENT_NAME: cmdld # # FUNCTIONS: none # # ORIGINS: 27 # # # Shell script to relink executables or shared objects with runtime linking # enabled. # command_name=$0 LD=${LD:-/bin/ld} TMPDIR=${TMPDIR:-/tmp} WRKDIR= AR=/usr/bin/ar AWK=/usr/bin/awk BASENAME=/usr/bin/basename CHMOD=/usr/bin/chmod CP=/usr/bin/cp DIRNAME=/usr/bin/dirname DUMP=/usr/sbin/dump FILE=/usr/bin/file GREP=/usr/bin/grep HEAD=/usr/bin/head MKDIR=/usr/bin/mkdir MV=/usr/bin/mv OD=/usr/bin/od PRINTF=/usr/bin/printf RM=/usr/bin/rm TOUCH=/usr/bin/touch NLSSET=2 rc=0 OBJ_FLAG= lflag= oflag= sflag= Rflag= curdir=$(/bin/pwd) alias showmsg='/usr/bin/dspmsg -s $NLSSET ld.cat' # Usage: usage() { showmsg 1 \ 'Usage: %s [-X{32|64|32_64}] [-R|-o ofile] [-ls] ifile \ \t[ ld-opts ... ] [ -F objs-libs ... ]\n' \ $command_name exit 1 } check_write() { if $TOUCH $1 2>/dev/null then return 1 else showmsg 10 '%s: Cannot write to file %s\n' $command_name $1 return 0 fi } # Process options while getopts ':lo:sRX:' opt do case $opt in l) lflag=1 ;; o) oflag=1 ofile="$OPTARG" if [ "$Rflag" -eq 1 ] then usage $command_name fi ;; s) sflag=1; lflag=1; # -s implies -l ;; R) Rflag=1 if [ "$oflag" -eq 1 ] then usage $command_name fi ;; X) if [ "$OBJ_FLAG" = "32" -o "$OBJ_FLAG" = "32_64" -a "$OPTARG" = "64" ] then OBJ_FLAG=32_64 elif [ "$OBJ_FLAG" = "64" -o "$OBJ_FLAG" = "32_64" \ -a "$OPTARG" = "32" ] then OBJ_FLAG=32_64 else OBJ_FLAG=$OPTARG fi ;; ':') showmsg 2 '%s: Missing parameter for option %s\n' \ $command_name $1 $OPTARG usage $command_name ;; '?') showmsg 3 '%s: Unknown option %s\n' $command_name '-'$OPTARG usage $command_name ;; esac done shift $(($OPTIND - 1)) if [ $# = 0 ] then showmsg 4 '%s: Missing input file\n' $command_name usage $command_name fi #Verify the specified OBJECT mode if [ "$OBJ_FLAG" != "" -a "$OBJ_FLAG" != "32" \ -a "$OBJ_FLAG" != "64" -a "$OBJ_FLAG" != "32_64" ] then showmsg 13 "%s: The specified object mode is not valid.\n\ \tSpecify -X32, -X64, or -X32_64.\n" $command_name exit 1 fi #If no -X given, look for OBJECT_MODE from environment if [ "$OBJ_FLAG" = "" ] then OBJ_FLAG=$OBJECT_MODE if [ "$OBJ_FLAG" != "" -a "$OBJ_FLAG" != "32" \ -a "$OBJ_FLAG" != "64" -a "$OBJ_FLAG" != "32_64" ] then showmsg 14 "%s: The OBJECT_MODE environment variable has an \ invalid setting.\n\tOBJECT_MODE must be 32, 64, or 32_64.\n" $command_name exit 1 else if [ "$OBJ_FLAG" = "" ] then OBJ_FLAG=32 #default to 32-bit fi fi fi PLAIN_IFILE=$1 shift if ! $HEAD -c 1 $PLAIN_IFILE > /dev/null 2>/dev/null then showmsg 5 '%s: Cannot open or find file: %s\n' \ $command_name $PLAIN_IFILE exit 1 fi # Collect other arguments. User-specified ld options are taken from # command line up to -F flag. Arguments after -F flag are additional # object files and libraries. user_ldopts= other_args= Fflag= while [ $# -gt 0 ] do if [ $1 = -F ] then Fflag=1 shift other_args="$*" break else user_ldopts="$user_ldopts $1" fi shift done ifile_dir=$(cd $($DIRNAME $PLAIN_IFILE) > /dev/null; /bin/pwd) Ifile=$($BASENAME $PLAIN_IFILE) ibase=${Ifile%.*} # Strip off suffix, if any IFILE=$ifile_dir/$Ifile # Use current directory if we'll be saving files there, either because # -l (or -s) is used or because -R and -o are not used. if [ ! -z "$lflag" -o -z "$Rflag" -a -z "$oflag" ]; then : else WRKDIR=$TMPDIR/rtl$$ trap "cd $curdir; $RM -rf $WRKDIR" 0 1 2 13 15 $MKDIR $WRKDIR fi if [ ! -z "$oflag" ] then if [ -z "$WRKDIR" ] then OFILE=$ofile # Write directly to output file. else if ! cd $($DIRNAME $ofile) > /dev/null 2> /dev/null then # if we can't cd there, we can't write there. showmsg 2 '%s: Cannot write to file %s\n' \ $command_name $ofile exit 1 fi # Get full pathname of output file OFILE=$(/bin/pwd)/$($BASENAME $ofile) cd - > /dev/null fi elif [ ! -z "$Rflag" ] then OFILE=$IFILE else OFILE=$curdir/$Ifile.new # Output file goes in current # directory, even if input file is # not in the current directory. fi if [ ! -z "$WRKDIR" ]; then cd $WRKDIR; fi # Get file name for writing shell script. Make sure we can write to the file. if [ -z "$sflag" ] then SFILE=/dev/null else SFILE=$curdir/$ibase.sh check_write $SFILE print '#!/bin/ksh' > $SFILE print "LD='$LD'" >> $SFILE $CHMOD +x $SFILE fi awkcmd=' BEGIN {previmpid = -1;} $1 == "0" {printf("-blibpath:%s", $NF); in_libpath = 1; next; } /^\[/ {in_libpath = 0; f = tolower(substr($4, length($4))); impid_cmd = "printf %d " $7 impid_cmd | getline impid close(impid_cmd) if (match(f, "[89abcdef]")) { if (previmpid != impid) { previmpid = impid; printf "#!" > IMPFILE; if (path[impid] == "/") printf "%s", path[impid] > IMPFILE; else if (path[impid]) printf "%s/", path[impid] > IMPFILE; printf "%s", base[impid] > IMPFILE; if (member[impid]) printf "(%s)", member[impid] > IMPFILE; print "" > IMPFILE; } if ($5 == "0x07") print $NF, $2 > IMPFILE; else print $NF > IMPFILE; } if (match(f, "[2367abef]")) print $NF > EXPFILE; if (match(f, "[4567cdef]")) {print " -e"$NF; eseen = 1;} if ((match(f, "[01]"))&&( ! match($NF, "__rtinit"))) print $NF " list" > EXPFILE } in_libpath {if (NF == 2) base[$1] = $2; else if (NF == 4) { path[$1] = substr($2, 1); base[$1] = $3; member[$1] = $4; } else if (substr($2,1,1) == "/") { path[$1] = substr($2, 1); base[$1] = $3; } else { base[$1] = $2; member[$1] = $3; } } END {if (eseen != 1) print " -bnoentry"}' # Function process_rtinit. Retrieves __rtinit structure information # from file to allow files linked with -binitfini to be relinked # Arguements: None # # Returns: string of -binitfini commands function process_rtinit { rtinitawk='/^\[0\].*__rtinit$/{print (substr($2, 3));}' datasectawk=' BEGIN {while (! match($4, ".data")) getline;} {print (substr($1,3)); print (substr ($4, 3));}' #get address of __rtinit structure rtinit_addr=$(LANG=C $DUMP -HTp -X"$OBJ_FLAG" $ifile | $AWK "$rtinitawk") #continue only if __rtinit is used if [[ -n $rtinit_addr ]]; then #get the phy_addr and RAWptr of .data section datasect=$(LANG=C $DUMP -hp -X"$OBJ_FLAG" $ifile | $AWK "$datasectawk") set $datasect typeset -i16 phys_addr RAW_ptr phys_addr=16#$1 RAW_ptr=16#$2 #adjust rtinit_addr let rtinit_addr=16#$rtinit_addr-$phys_addr+$RAW_ptr #retrieve init/fini descriptors info offsets=$(LANG=C $OD -An -tx -j"$rtinit_addr" -N20 $ifile) set $offsets typeset -i init_offset fini_offset descriptor_size if [[ $OBJ_FLAG = "32" ]]; then init_offset=16#$2+$rtinit_addr fini_offset=16#$3+$rtinit_addr descriptor_size=16#$4 else #64-bit mode init_offset=16#$3+$rtinit_addr fini_offset=16#$4+$rtinit_addr descriptor_size=16#$5 fi typeset -i index noinits nofinis let index=0 let noinits=0 let nofinis=0 #retrieve init func names if [[ $init_offset > $rtinit_addr ]]; then name_offset=$(LANG=C $OD -An -tx -j"$init_offset" -N12 $ifile) set $name_offset typeset -i funcname if [[ $OBJ_FLAG = "32" ]]; then funcname=16#$2+$rtinit_addr else #64-bit funcname=16#$3+$rtinit_addr fi while [[ $funcname -ne $rtinit_addr ]]; do cmdarr[$index]=$(LANG=C $OD -An -S1 -j"$funcname" $ifile | $HEAD -1) noinits=$noinits+1 index=$index+1 init_offset=$init_offset+$descriptor_size name_offset=$(LANG=C $OD -An -tx -j"$init_offset" -N12 $ifile) set $name_offset if [[ $OBJ_FLAG = "32" ]]; then funcname=16#$2+$rtinit_addr else #64-bit funcname=16#$3+$rtinit_addr fi done fi #retrieve fini func names if [[ $fini_offset > $rtinit_addr ]]; then name_offset=$(LANG=C $OD -An -tx -j"$fini_offset" -N12 $ifile) set $name_offset if [[ $OBJ_FLAG = "32" ]]; then funcname=16#$2+$rtinit_addr else #64-bit funcname=16#$3+$rtinit_addr fi while [[ $funcname -ne $rtinit_addr ]]; do cmdarr[$index]=$(LANG=C $OD -An -S1 -j"$funcname" $ifile | $HEAD -1) nofinis=$nofinis+1 index=$index+1 fini_offset=$fini_offset+$descriptor_size name_offset=$(LANG=C $OD -An -tx -j"$fini_offset" -N12 $ifile) set $name_offset if [[ $OBJECT_FLAG = "32" ]]; then funcname=16#$2+$rtinit_addr else #64-bit funcname=16#$3+$rtinit_addr fi done fi #make command typeset -i ctr priority let ctr=0 let priority=100 while [[ $ctr < $noinits ]]; do $PRINTF "%s%s%s%d%s" "-binitfini:" ${cmdarr[$ctr]} "::" $priority " " ctr=$ctr+1 priority=$priority-10 done nofinis=$noinits+$nofinis while [[ $ctr < $nofinis ]]; do priority=$priority+10 $PRINTF "%s%s%s%d%s" "-binitfini::" ${cmdarr[$ctr]} ":" $priority " " ctr=$ctr+1 done fi } # Function process_file. Relink an object file. # Arguments: $1: Input file # $2: Basename for import and export files # $3: Output file name # $4: Command to print to script file for good archive member # # Returns: 0 Success # 1 Input file is not an XCOFF executable # 2 Some other error occurred # 3 The link command failed. function process_file { ifile=$1 imp=$2.imp exp=$2.exp ofile=$3 # Check for an XCOFF executable. Return 1 for non-executables. ftype=$(LANG=C $DUMP -X32_64 -ov $ifile 2>/dev/null | $GREP '^Flags' ) if [[ ! $ftype = *EXEC* ]]; then return 1; fi if [[ $ftype = *LOADONLY* ]]; then isLoadOnly=1; else isLoadOnly=0; fi #It's an executable, but is it valid in our object mode? mtype=$(LANG=C $DUMP -X32_64 -ov $ifile 2>/dev/null | $GREP '^Magic' ) [[ $mtype = *32* ]] && mtype=32 || mtype=64 if [ "$OBJ_FLAG" = "32_64" ]; then OBJ_FLAG=$mtype elif [ "$OBJ_FLAG" != "$mtype" ]; then return 4 # not valid in this object mode fi # Is it a regular executable or a shared object file? if [[ $ftype = *SHROBJ* ]] then ldflags='-bM:SRE' imode=-bdynamic else ldflags= imode= fi # See if we can create import/export files. if check_write $imp; then return 2; fi if check_write $exp then $RM -f $imp return 2 fi # Build the IMPORTS and EXPORTS lists and find the entry point # if any. In addition, assign a value to LIBPATH_EP # containing the libpath information and the entrypoint name (or # -bnoentry if none). # # This information is extracted from the XCOFF loader section. LIBPATH_EP=$(LANG=C $DUMP -X$OBJ_FLAG -HTp $ifile \ | $AWK "$awkcmd" IMPFILE=$imp EXPFILE=$exp) if [ $? -ne 0 ] then showmsg 7 '%s: Error processing input object: %s\n' \ $command_name "$1" return 2 fi #retrieve any initfini commands initfini=$(process_rtinit) if [ "$sflag" -eq 1 ] then if [ ! -z "$4" ] then print -- "$4" >> $SFILE fi print -- '$'LD \ $other_args \ -b$OBJ_FLAG \ -brtl -bnortllib -bnosymbolic -bnoautoexp \ -bstatic $1 $imode -o $ofile.'$$' \ -bI:$imp -bE:$exp \ $ldflags $initfini \ $LIBPATH_EP \ -bdynamic $user_ldopts >> $SFILE if [ $isLoadOnly -eq 1 ] then print -- strip -e $ofile.'$$' >> $SFILE fi ldrc=0 else if check_write $ofile.$$ then $RM -rf $imp $exp return 2 fi $LD $other_args \ -b$OBJ_FLAG \ -brtl -bnortllib -bnosymbolic -bnoautoexp \ -bstatic $1 $imode -o $ofile.$$ \ -bI:$imp -bE:$exp \ $ldflags $initfini \ $LIBPATH_EP \ -bdynamic $user_ldopts ldrc=$? if [ $ldrc -ne 0 ]; then ldrc=3; fi if [ $isLoadOnly -eq 1 ]; then strip -e $ofile.$$; fi # Clean up import and export file. if [ -z "$lflag" ]; then $RM -f $imp $exp; fi fi return $ldrc } # Function process_archive. Extract each member from the archive and pass # it to process_file for processing. Replace member in new archive # if it was enabled. # function process_archive { integer bad=0 integer good=0 for f in $($AR -X$OBJ_FLAG -t $IFILE) do $AR -X$OBJ_FLAG -x $IFILE $f $CHMOD +w $f fbase=${f%.*} # Strip off suffix, if any process_file $f $fbase $f "$AR -X$OBJ_FLAG -x $IFILE $f" ldrc=$? case $ldrc in 0) ((good += 1)) if [ -z "$sflag" ] then $MV -f $f.$$ $f $AR -X$OBJ_FLAG -ro $OFILE.$$ $f else print -- $MV -f $f.'$$' $f >> $SFILE print -- $AR -X$OBJ_FLAG -ro $OFILE.'$$' $f >> $SFILE fi print -- $RM -f $f >> $SFILE ;; 2) ((bad += 1)) ;; 3) ((bad += 1)) showmsg 8 \ '%s: Link command failed for archive member: %s\n' \ $command_name $f ;; esac $RM -f $f $f.$$ done if [ $good -eq 0 -o $bad -gt 0 ] then if [ $bad -eq 0 ] then showmsg 11 "%s: Warning: Archive file %s\n\ \tNo archive members are executables or shared objects.\n" \ $command_name $PLAIN_IFILE fi rc=1 fi } # Check if the specified file is an archive. ftype=$(LANG=C $FILE $(/bin/ls -l $IFILE|$AWK '{print $NF}') | $AWK '{print $2}') if [[ "$ftype" = archive ]] then if [ -z "$sflag" ] then $CP $IFILE $OFILE.$$ $CHMOD +w $OFILE.$$ # Make sure we can write to the file. else print -- $CP $IFILE $OFILE.'$$' >> $SFILE print -- $CHMOD +w $OFILE.'$$' >> $SFILE fi if [ "$OBJ_FLAG" != "32_64" ]; then process_archive else OBJ_FLAG=32 process_archive OBJ_FLAG=64 process_archive fi else process_file $IFILE $ibase $OFILE ldrc=$? case $ldrc in 1) showmsg 6 \ '%s: Input file is not an executable or shared object: %s\n' \ $command_name "$PLAIN_IFILE" rc=1 ;; 2) rc=1 # Error already printed ;; 3) showmsg 9 '%s: Link command failed for file: %s\n' \ $command_name $PLAIN_IFILE rc=1 ;; 4) showmsg 15 \ '%s: Input file is not valid in the current object file mode: %s\n' \ $command_name "$PLAIN_IFILE" rc=1 ;; esac fi if [ $rc -eq 0 ] then if [ -z "$sflag" ] then $MV -f $OFILE.$$ $OFILE else print -- $MV -f $OFILE.'$$' $OFILE >> $SFILE fi else # Failure $RM -f $OFILE.$$ if [ ! -z "$sflag" ]; then $RM -f $SFILE; fi if [ ! -z "$Rflag" ] then showmsg 12 '%s: Input file %s was not modified.\n' \ $command_name $PLAIN_IFILE fi fi exit $rc