xref: /OK3568_Linux_fs/kernel/arch/powerpc/tools/unrel_branch_check.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0+
3*4882a593Smuzhiyun# Copyright © 2016,2020 IBM Corporation
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun# This script checks the unrelocated code of a vmlinux for "suspicious"
6*4882a593Smuzhiyun# branches to relocated code (head_64.S code).
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun# Have Kbuild supply the path to objdump and nm so we handle cross compilation.
9*4882a593Smuzhiyunobjdump="$1"
10*4882a593Smuzhiyunnm="$2"
11*4882a593Smuzhiyunvmlinux="$3"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyunkstart=0xc000000000000000
14*4882a593Smuzhiyun
15*4882a593Smuzhiyunend_intr=0x$($nm -p "$vmlinux" |
16*4882a593Smuzhiyun	sed -E -n '/\s+[[:alpha:]]\s+__end_interrupts\s*$/{s///p;q}')
17*4882a593Smuzhiyunif [ "$end_intr" = "0x" ]; then
18*4882a593Smuzhiyun	exit 0
19*4882a593Smuzhiyunfi
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun# we know that there is a correct branch to
22*4882a593Smuzhiyun# __start_initialization_multiplatform, so find its address
23*4882a593Smuzhiyun# so we can exclude it.
24*4882a593Smuzhiyunsim=0x$($nm -p "$vmlinux" |
25*4882a593Smuzhiyun	sed -E -n '/\s+[[:alpha:]]\s+__start_initialization_multiplatform\s*$/{s///p;q}')
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun$objdump -D --no-show-raw-insn --start-address="$kstart" --stop-address="$end_intr" "$vmlinux" |
28*4882a593Smuzhiyunsed -E -n '
29*4882a593Smuzhiyun# match lines that start with a kernel address
30*4882a593Smuzhiyun/^c[0-9a-f]*:\s*b/ {
31*4882a593Smuzhiyun	# drop branches via ctr or lr
32*4882a593Smuzhiyun	/\<b.?.?(ct|l)r/d
33*4882a593Smuzhiyun	# cope with some differences between Clang and GNU objdumps
34*4882a593Smuzhiyun	s/\<bt.?\s*[[:digit:]]+,/beq/
35*4882a593Smuzhiyun	s/\<bf.?\s*[[:digit:]]+,/bne/
36*4882a593Smuzhiyun	# tidy up
37*4882a593Smuzhiyun	s/\s0x/ /
38*4882a593Smuzhiyun	s/://
39*4882a593Smuzhiyun	# format for the loop below
40*4882a593Smuzhiyun	s/^(\S+)\s+(\S+)\s+(\S+)\s*(\S*).*$/\1:\2:\3:\4/
41*4882a593Smuzhiyun	# strip out condition registers
42*4882a593Smuzhiyun	s/:cr[0-7],/:/
43*4882a593Smuzhiyun	p
44*4882a593Smuzhiyun}' | {
45*4882a593Smuzhiyun
46*4882a593Smuzhiyunall_good=true
47*4882a593Smuzhiyunwhile IFS=: read -r from branch to sym; do
48*4882a593Smuzhiyun	case "$to" in
49*4882a593Smuzhiyun	c*)	to="0x$to"
50*4882a593Smuzhiyun		;;
51*4882a593Smuzhiyun	.+*)
52*4882a593Smuzhiyun		to=${to#.+}
53*4882a593Smuzhiyun		if [ "$branch" = 'b' ]; then
54*4882a593Smuzhiyun			if (( to >= 0x2000000 )); then
55*4882a593Smuzhiyun				to=$(( to - 0x4000000 ))
56*4882a593Smuzhiyun			fi
57*4882a593Smuzhiyun		elif (( to >= 0x8000 )); then
58*4882a593Smuzhiyun			to=$(( to - 0x10000 ))
59*4882a593Smuzhiyun		fi
60*4882a593Smuzhiyun		printf -v to '0x%x' $(( "0x$from" + to ))
61*4882a593Smuzhiyun		;;
62*4882a593Smuzhiyun	*)	printf 'Unkown branch format\n'
63*4882a593Smuzhiyun		;;
64*4882a593Smuzhiyun	esac
65*4882a593Smuzhiyun	if [ "$to" = "$sim" ]; then
66*4882a593Smuzhiyun		continue
67*4882a593Smuzhiyun	fi
68*4882a593Smuzhiyun	if (( to > end_intr )); then
69*4882a593Smuzhiyun		if $all_good; then
70*4882a593Smuzhiyun			printf '%s\n' 'WARNING: Unrelocated relative branches'
71*4882a593Smuzhiyun			all_good=false
72*4882a593Smuzhiyun		fi
73*4882a593Smuzhiyun		printf '%s %s-> %s %s\n' "$from" "$branch" "$to" "$sym"
74*4882a593Smuzhiyun	fi
75*4882a593Smuzhiyundone
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun$all_good
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun}
80