xref: /freebsd/tools/build/check-links.sh (revision d0b2dbfa)
16276797fSBaptiste Daroussin#!/bin/sh
26276797fSBaptiste Daroussin
33844bbe2SBryan Drewerylibkey() {
43844bbe2SBryan Drewery	libkey="lib_symbols_$1"
55f6c4518SBryan Drewery	patterns=[.+,/-]
63844bbe2SBryan Drewery	replacement=_
73844bbe2SBryan Drewery	while :; do
83844bbe2SBryan Drewery		case " ${libkey} " in
93844bbe2SBryan Drewery			*${patterns}*)
103844bbe2SBryan Drewery				libkey="${libkey%%${patterns}*}${replacement}${libkey#*${patterns}}"
113844bbe2SBryan Drewery				;;
123844bbe2SBryan Drewery			*)
133844bbe2SBryan Drewery				break
143844bbe2SBryan Drewery				;;
153844bbe2SBryan Drewery		esac
163844bbe2SBryan Drewery	done
173844bbe2SBryan Drewery	return 0
183844bbe2SBryan Drewery}
193844bbe2SBryan Drewery
208afa72e5SBryan Dreweryusage() {
218afa72e5SBryan Drewery	cat <<-EOF
22fcd26781SBryan Drewery	usage: $0 [-Uv] [-L LD_LIBRARY_PATH] file
23fcd26781SBryan Drewery	       -L:       Specify an alternative LD_LIBRARY_PATH for the library resolution.
248afa72e5SBryan Drewery	       -U:       Skip looking for unresolved symbols.
258afa72e5SBryan Drewery	       -v:       Show which library each symbol is resolved to.
268afa72e5SBryan Drewery	EOF
278afa72e5SBryan Drewery	exit 0
288afa72e5SBryan Drewery}
298afa72e5SBryan Drewery
303554283aSBryan Dreweryret=0
313554283aSBryan DreweryCHECK_UNRESOLVED=1
32fc2ef3b2SBryan DreweryVERBOSE_RESOLVED=0
33fcd26781SBryan Drewerywhile getopts "L:Uv" flag; do
343554283aSBryan Drewery	case "${flag}" in
35fcd26781SBryan Drewery		L) LIB_PATH="${OPTARG}" ;;
363554283aSBryan Drewery		U) CHECK_UNRESOLVED=0 ;;
37fc2ef3b2SBryan Drewery		v) VERBOSE_RESOLVED=1 ;;
388afa72e5SBryan Drewery		*) usage ;;
393554283aSBryan Drewery	esac
403554283aSBryan Drewerydone
413554283aSBryan Dreweryshift $((OPTIND-1))
423554283aSBryan Drewery
43d1db5f8fSBryan Dreweryif ! [ -f "$1" ]; then
44d1db5f8fSBryan Drewery	echo "No such file or directory: $1" >&2
45d1db5f8fSBryan Drewery	exit 1
46d1db5f8fSBryan Dreweryfi
47d1db5f8fSBryan Drewery
483554283aSBryan Drewerymime=$(file -L --mime-type $1)
493554283aSBryan Dreweryisbin=0
503554283aSBryan Drewerycase $mime in
5188741a40SBaptiste Daroussin*application/x-executable|*application/x-pie-executable) isbin=1 ;;
523554283aSBryan Drewery*application/x-sharedlib);;
533554283aSBryan Drewery*) echo "Not an elf file" >&2 ; exit 1;;
543554283aSBryan Dreweryesac
553554283aSBryan Drewery
563554283aSBryan Drewery# Gather all symbols from the target
5764ee145bSBryan Dreweryunresolved_symbols=$(nm -u -D --format=posix "$1" | awk '$2 == "U" {print $1}' | tr '\n' ' ')
5864ee145bSBryan Drewery[ ${isbin} -eq 1 ] && bss_symbols=$(nm -D --format=posix "$1" | awk '$2 == "B" && $4 != "" {print $1}' | tr '\n' ' ')
59fcd26781SBryan Dreweryif [ -n "${LIB_PATH}" ]; then
60fcd26781SBryan Drewery	for libc in /lib/libc.so.*; do
61fcd26781SBryan Drewery		LDD_ENV="LD_PRELOAD=${libc}"
62fcd26781SBryan Drewery	done
63fcd26781SBryan Drewery	LDD_ENV="${LDD_ENV} LD_LIBRARY_PATH=${LIB_PATH}"
64fcd26781SBryan Dreweryfi
65fcd26781SBryan Drewery
66fcd26781SBryan Dreweryldd_libs=$(env ${LDD_ENV} ldd $(realpath $1) | awk '{print $1 ":" $3}')
673554283aSBryan Drewery
686276797fSBaptiste Daroussin# Check for useful libs
693844bbe2SBryan Drewerylist_libs=
703844bbe2SBryan Dreweryresolved_symbols=
71daa301d1SBryan Dreweryfor lib in $(readelf -d $1 | awk '$2 ~ /\(?NEEDED\)?/ { sub(/\[/,"",$NF); sub(/\]/,"",$NF); print $NF }'); do
726276797fSBaptiste Daroussin	echo -n "checking if $lib is needed: "
735f6c4518SBryan Drewery	if [ -n "${lib##/*}" ]; then
743844bbe2SBryan Drewery		for libpair in ${ldd_libs}; do
753844bbe2SBryan Drewery			case "${libpair}" in
763844bbe2SBryan Drewery				${lib}:*) libpath="${libpair#*:}" && break ;;
773844bbe2SBryan Drewery			esac
786276797fSBaptiste Daroussin		done
795f6c4518SBryan Drewery	else
805f6c4518SBryan Drewery		libpath="${lib}"
815f6c4518SBryan Drewery	fi
823844bbe2SBryan Drewery	list_libs="$list_libs $lib"
833844bbe2SBryan Drewery	foundone=
843554283aSBryan Drewery	lib_symbols="$(nm -D --defined-only --format=posix "${libpath}" | awk '$2 ~ /C|R|D|T|W|B|V/ {print $1}' | tr '\n' ' ')"
853844bbe2SBryan Drewery	if [ ${CHECK_UNRESOLVED} -eq 1 ]; then
863844bbe2SBryan Drewery		# Save the global symbols for this lib
873844bbe2SBryan Drewery		libkey "${lib}"
883844bbe2SBryan Drewery		setvar "${libkey}" "${lib_symbols}"
893844bbe2SBryan Drewery	fi
903844bbe2SBryan Drewery	for fct in ${lib_symbols}; do
9164ee145bSBryan Drewery		case " ${unresolved_symbols} ${bss_symbols} " in
923844bbe2SBryan Drewery			*\ ${fct}\ *) foundone="${fct}" && break ;;
933844bbe2SBryan Drewery		esac
943844bbe2SBryan Drewery	done
953844bbe2SBryan Drewery	if [ -n "${foundone}" ]; then
963844bbe2SBryan Drewery		echo "yes... ${foundone}"
976276797fSBaptiste Daroussin	else
986276797fSBaptiste Daroussin		echo "no"
993844bbe2SBryan Drewery		ret=1
1006276797fSBaptiste Daroussin	fi
1016276797fSBaptiste Daroussindone
1026276797fSBaptiste Daroussin
1033844bbe2SBryan Dreweryif [ ${CHECK_UNRESOLVED} -eq 1 ]; then
1043554283aSBryan Drewery	# Add in crt1 symbols
1053554283aSBryan Drewery	list_libs="${list_libs} crt1.o"
1063554283aSBryan Drewery	lib_symbols="$(nm --defined-only --format=posix "/usr/lib/crt1.o" | awk '$2 ~ /C|R|D|T|W|B|V/ {print $1}' | tr '\n' ' ')"
1073554283aSBryan Drewery	# Save the global symbols for this lib
1083554283aSBryan Drewery	libkey "crt1.o"
1093554283aSBryan Drewery	setvar "${libkey}" "${lib_symbols}"
1103554283aSBryan Drewery
111b0cb3920SBryan Drewery	# Now search libs for all symbols and report missing ones.
1123844bbe2SBryan Drewery	for sym in ${unresolved_symbols}; do
1136276797fSBaptiste Daroussin		found=0
1143844bbe2SBryan Drewery		for lib in ${list_libs}; do
1153844bbe2SBryan Drewery			libkey "${lib}"
1163844bbe2SBryan Drewery			eval "lib_symbols=\"\${${libkey}}\""
1173844bbe2SBryan Drewery			# lib_symbols now contains symbols for the lib.
1183844bbe2SBryan Drewery			case " ${lib_symbols} " in
119fc2ef3b2SBryan Drewery				*\ ${sym}\ *)
120fc2ef3b2SBryan Drewery					[ ${VERBOSE_RESOLVED} -eq 1 ] &&
121fc2ef3b2SBryan Drewery					    echo "Resolved symbol ${sym} from ${lib}"
122fc2ef3b2SBryan Drewery					found=1
123fc2ef3b2SBryan Drewery					break
124fc2ef3b2SBryan Drewery					;;
1253844bbe2SBryan Drewery			esac
1266276797fSBaptiste Daroussin		done
1276276797fSBaptiste Daroussin		if [ $found -eq 0 ]; then
1286276797fSBaptiste Daroussin			echo "Unresolved symbol $sym"
1293844bbe2SBryan Drewery			ret=1
1306276797fSBaptiste Daroussin		fi
1316276797fSBaptiste Daroussin	done
1323844bbe2SBryan Dreweryfi
1333844bbe2SBryan Drewery
1343844bbe2SBryan Dreweryexit ${ret}
135