diff options
Diffstat (limited to 'scripts/faddr2line')
| -rwxr-xr-x | scripts/faddr2line | 45 | 
1 files changed, 34 insertions, 11 deletions
diff --git a/scripts/faddr2line b/scripts/faddr2line index 0e6268d59883..94ed98dd899f 100755 --- a/scripts/faddr2line +++ b/scripts/faddr2line @@ -95,17 +95,25 @@ __faddr2line() {  	local print_warnings=$4  	local sym_name=${func_addr%+*} -	local offset=${func_addr#*+} -	offset=${offset%/*} +	local func_offset=${func_addr#*+} +	func_offset=${func_offset%/*}  	local user_size= +	local file_type +	local is_vmlinux=0  	[[ $func_addr =~ "/" ]] && user_size=${func_addr#*/} -	if [[ -z $sym_name ]] || [[ -z $offset ]] || [[ $sym_name = $func_addr ]]; then +	if [[ -z $sym_name ]] || [[ -z $func_offset ]] || [[ $sym_name = $func_addr ]]; then  		warn "bad func+offset $func_addr"  		DONE=1  		return  	fi +	# vmlinux uses absolute addresses in the section table rather than +	# section offsets. +	local file_type=$(${READELF} --file-header $objfile | +		${AWK} '$1 == "Type:" { print $2; exit }') +	[[ $file_type = "EXEC" ]] && is_vmlinux=1 +  	# Go through each of the object's symbols which match the func name.  	# In rare cases there might be duplicates, in which case we print all  	# matches. @@ -114,9 +122,11 @@ __faddr2line() {  		local sym_addr=0x${fields[1]}  		local sym_elf_size=${fields[2]}  		local sym_sec=${fields[6]} +		local sec_size +		local sec_name  		# Get the section size: -		local sec_size=$(${READELF} --section-headers --wide $objfile | +		sec_size=$(${READELF} --section-headers --wide $objfile |  			sed 's/\[ /\[/' |  			${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }') @@ -126,6 +136,17 @@ __faddr2line() {  			return  		fi +		# Get the section name: +		sec_name=$(${READELF} --section-headers --wide $objfile | +			sed 's/\[ /\[/' | +			${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print $2; exit }') + +		if [[ -z $sec_name ]]; then +			warn "bad section name: section: $sym_sec" +			DONE=1 +			return +		fi +  		# Calculate the symbol size.  		#  		# Unfortunately we can't use the ELF size, because kallsyms @@ -174,10 +195,10 @@ __faddr2line() {  		sym_size=0x$(printf %x $sym_size) -		# Calculate the section address from user-supplied offset: -		local addr=$(($sym_addr + $offset)) +		# Calculate the address from user-supplied offset: +		local addr=$(($sym_addr + $func_offset))  		if [[ -z $addr ]] || [[ $addr = 0 ]]; then -			warn "bad address: $sym_addr + $offset" +			warn "bad address: $sym_addr + $func_offset"  			DONE=1  			return  		fi @@ -191,9 +212,9 @@ __faddr2line() {  		fi  		# Make sure the provided offset is within the symbol's range: -		if [[ $offset -gt $sym_size ]]; then +		if [[ $func_offset -gt $sym_size ]]; then  			[[ $print_warnings = 1 ]] && -				echo "skipping $sym_name address at $addr due to size mismatch ($offset > $sym_size)" +				echo "skipping $sym_name address at $addr due to size mismatch ($func_offset > $sym_size)"  			continue  		fi @@ -202,11 +223,13 @@ __faddr2line() {  		[[ $FIRST = 0 ]] && echo  		FIRST=0 -		echo "$sym_name+$offset/$sym_size:" +		echo "$sym_name+$func_offset/$sym_size:"  		# Pass section address to addr2line and strip absolute paths  		# from the output: -		local output=$(${ADDR2LINE} -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;") +		local args="--functions --pretty-print --inlines --exe=$objfile" +		[[ $is_vmlinux = 0 ]] && args="$args --section=$sec_name" +		local output=$(${ADDR2LINE} $args $addr | sed "s; $dir_prefix\(\./\)*; ;")  		[[ -z $output ]] && continue  		# Default output (non --list):  |