summaryrefslogblamecommitdiffstats
path: root/helper/binutil.inc
blob: aa793e08a4312df2ca8901e29260cdb79e4ad202 (plain) (tree)
1
2
3
4
5
6
7
8
9




                                                            



                                                           
 






                                                             
 

                                                            
                                      
                                                  

                                           


                 
                                                                   

                                                        










                                                                      
                            

                                                               

                                   
                     

                                                                                 
                     

                
                                             
                             
                                 

                     
                                                                   
                                          
                                                   
                                                              
                                                                                                                                     

                                                                                  

                                                            
                                                                              

                                          
                                                                     
                    
                                                           
                                                       
                                        

                                
                                
            
 

 













                                                                 
              


                                                          
                                    
                                                                                                       
                               
                                                       
                                                            
                                                                                                  

                                                                                             




                                                     


                                                                     
                                                                         
                                                   

                                                    
            
                                                                                                                                  
                                                                                                                                 



                                                            



                                                           


                                                           
 

                  








                                                                              
                                              



                                        



                                     

                           
                                           











                                                                 


                                   
                                                   


                                           
                                               
                                       
                                        
                                  

                                                                                   












                                                                         
            
                           
 








                                                            
                   





                                                                                                                                     
#!/bin/bash
# 
# Common functions to copy binaries and their dependancies.
#
############################################################
#	This will parse the output of ldd on given binaries
#	and echo the location of these libs to STDOUT
#	The output of this function has to be used in some
#	way, it only echos!	
#
# About local search:
#	It is required that we can search for the dynamic
#	libraries in a specific directory, namely the one
#	where we (potentially) built the binary. If a 
#	corresponding library is found, it should take 
#	precedence over ones found on the system.
#	This can be done by using the '-l' switch, see below.
#
############################################################
# We use a blacklist mechanism to exclude common libraries.
# This improves runtime quite a bit...
BLACKLIST="ld-linux linux-gate linux-vdso libc.so"

# Initialise flag and path for local search
LOCALSEARCH=0
LOCALSEARCHDIR=""

# replace ' ' by '|' in the blacklist, so grep can use it directly.
CURRENT_BLACKLIST=$(echo ${BLACKLIST} | sed 's/ /\\|/g')

############################################################
#
# Usage: 
#	get_dynamic_dependencies [-l <searchdir>] <binary_list>
# 	  * the list must be seperated by spaces
#	  * the search for lib needed by a binary can be done locally,
#	    using the -l <searchdir> option
#
# Ouput: 
#	 Will simply echo list of required libraries

get_dynamic_dependencies() {
	# check if local search is activated by the '-l' switch
	# if so the following argument is the path.
	if [ "x$1" == "x-l" ]; then
		LOCALSEARCH=1
		shift
		[ ! -d "$1" ] && perror "Directory '$1' does not exist, exiting."
		LOCALSEARCHDIR="$1"
		shift
	fi	

	# main loop over the list of binaries
	while [ $# != 0 ]; do
		local BINARY="$1"
		shift

		# now run ldd on it and save the output in $LDD_OUT
		local LDD_OUT="ldd_output"
		if ldd "$BINARY" > "$LDD_OUT"; then
			# Case 1: file is a dynamic executable
			for LIB in $(grep -v "${CURRENT_BLACKLIST}${REQUIRED_LDD_BLACKLIST}" "$LDD_OUT" | awk '{print $1 $2 $3}'); do
				# split the entry into an array, ex:
				# libm.so.6 => /lib/libm.so.6 would be split into:
				# LIBLINK[0]   LIBLINK[1]
				local LIBLINK=(${LIB//=>/ })
				# call helper function to find the correct lib
				lib_search
			done
			#TODO: check if "statically linked" is output
		else
			# Case 2: not a dynamic, do nothing
			pdebug "\t\t\t(Not a dynamic.)"
			rm -f "$LDD_OUT"
			continue
		fi	
		rm -f "$LDD_OUT"
	done

}

############################################################
#
# Usage:
#	lib_search
#
# Output:
#	List of the path including any possible symbolic links
#	of the found libraries.
#
# Note: This function takes no argument. It takes the library
#	to look for from the local array LIBLINK.
#	If the local was activated in get_dynamic_dependencies
#	this will search for the library in LOCALSEARCHDIR first.
#	If its not found, then it will look system-wide.
lib_search() {

	# if activated, start by searching the lib locally
	if [ "x$LOCALSEARCH" == "x1" ]; then
		cd "$LOCALSEARCHDIR"
        	local LOCAL_MATCHES=$(find . -name "${LIBLINK[0]}") # | awk -F '.' '{print $1}')".so\*)
		cd - >/dev/null
	        if [ "x${LOCAL_MATCHES}" != "x" ]; then
        		for LOCALLIB in ${LOCAL_MATCHES}; do
				get_link_chain "${LOCALSEARCHDIR}/${LOCALLIB}" "${LOCALSEARCHDIR}"
				get_dynamic_dependencies -l "${LOCALSEARCHDIR}" "${LOCALLIB}"
				CURRENT_BLACKLIST+="\|${LIBLINK[0]}"
	                done
			# found the libs, we are done
			return
	        fi
		# mark local search as done
	fi

	# search the lib on the system since it was not found earlier
	if [ ! -z ${LIBLINK[1]} ] && [ "x${LIBLINK[1]}" != "xnot" ]; then
		# get chain of symlink for that lib
                get_link_chain "${LIBLINK[1]}"
		CURRENT_BLACKLIST+="\|${LIBLINK[1]}"
        else
                pwarning "\t\tLib '${LIBLINK[0]}' from required dir '$ENTRY' neither found in build directory nor on this system."
                pwarning "\t\tIf this lib is not supplied by another module, this module will probably fail in your final system"
        fi
}
############################################################
#
# Usage:
#	get_link_chain <link> [prefix] 
#	  * <link> must be in absolute form-
#	  * [prefix] is the prefix to strip from the ouput.
#
# Output:
#	 Lists the symlink chain until a hardlink is found.
#
get_link_chain() {

	# sanity checks
	if [[ "$1" == /* ]]; then
		[ -e $1 ] || perror "get_link_chain: no such file: $1"
	else
		perror "get_link_chain() requires absolute paths, given: $1"
	fi
	if [ $# == 2 ] ; then
		[ ! -d $2 ] && perror "get_link_chain: $2 is not a directory."
		# got a prefix
		local PREFIX=$(readlink -f $2)
	else
		# mark prefix as not set
		local PREFIX="notset"
	fi

	# canonalize
	local LINK=$(canonicalize $1)

	local CHAIN="$LINK"

	# write the first link in the chain
	if [ "x$PREFIX" != "x" -a "x$PREFIX" != "xnotset" ]; then
		if [ "x${LINK#$PREFIX}" == "x${LINK}" ]; then
			# prefix was not in the link
			echo "$LINK"
		else
			# prefix was in the link
			echo ./"${LINK#$PREFIX}"
		fi 
	else
		# no prefix, copy like it is
		echo "$LINK"
	fi

	# now we check for symlinks
	local TRY=0
	while [ -L "$LINK" ] && [ $TRY -lt 10 ]; do
		let TRY=TRY+1

		# save the directory prefix
		CURRENTDIR=$(dirname "${LINK}")
		# first follow the link
		LINK=$(readlink "$LINK")
		CHAIN+=" -> $LINK"
		# $LINK can be absolute or relative, check cases
		[[ "$LINK" == /* ]] || LINK=$(canonicalize "$CURRENTDIR"/"${LINK}")
		# write the first link in the chain
	        if [ "x$PREFIX" != "x" -a "x$PREFIX" != "xnotset" ]; then
	                if [ "x${LINK#$PREFIX}" == "x${LINK}" ]; then
        	        	# prefix was not in the link
                	        echo "$LINK"
	                else
        	                # prefix was in the link
                	        echo ./"${LINK#$PREFIX}"
	                fi
        	else
                	# no prefix, copy like it is
	                echo "$LINK"
        	fi
	done
	pdebug "\t\t$CHAIN"
}
############################################################
#
# Usage:
#	list_basic_libs
#
# Output:
#	list the path of following basic system libraries:
#	- libc.so, ld-linux.so
#
list_basic_libs() {
        for i in $(ldd ${SHELL})
        do
                [ $(echo $i | grep '^/' | grep -c ld) -eq 1 -o  $(echo $i | grep '^/' | grep -c libc.so) -eq 1 ] && get_link_chain $i
        done
}