summaryrefslogtreecommitdiff
path: root/arch/powerpc/tools
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/tools')
-rwxr-xr-xarch/powerpc/tools/unrel_branch_check.sh34
1 files changed, 29 insertions, 5 deletions
diff --git a/arch/powerpc/tools/unrel_branch_check.sh b/arch/powerpc/tools/unrel_branch_check.sh
index 0369eb2e7e4b..8301efee1e6c 100755
--- a/arch/powerpc/tools/unrel_branch_check.sh
+++ b/arch/powerpc/tools/unrel_branch_check.sh
@@ -18,12 +18,16 @@ if [ "$end_intr" = "0x" ]; then
exit 0
fi
-$objdump -R -D --no-show-raw-insn --start-address="$kstart" --stop-address="$end_intr" "$vmlinux" |
+# we know that there is a correct branch to
+# __start_initialization_multiplatform, so find its address
+# so we can exclude it.
+sim=0x$($nm -p "$vmlinux" |
+ sed -E -n '/\s+[[:alpha:]]\s+__start_initialization_multiplatform\s*$/{s///p;q}')
+
+$objdump -D --no-show-raw-insn --start-address="$kstart" --stop-address="$end_intr" "$vmlinux" |
sed -E -n '
# match lines that start with a kernel address
/^c[0-9a-f]*:\s*b/ {
- # drop a target that we do not care about
- /\<__start_initialization_multiplatform>/d
# drop branches via ctr or lr
/\<b.?.?(ct|l)r/d
# cope with some differences between Clang and GNU objdumps
@@ -33,14 +37,34 @@ sed -E -n '
s/\s0x/ /
s/://
# format for the loop below
- s/^(\S+)\s+(\S+)\s+(\S+)\s*(\S*).*$/\1:\2:0x\3:\4/
+ s/^(\S+)\s+(\S+)\s+(\S+)\s*(\S*).*$/\1:\2:\3:\4/
# strip out condition registers
- s/:0xcr[0-7],/:0x/
+ s/:cr[0-7],/:/
p
}' | {
all_good=true
while IFS=: read -r from branch to sym; do
+ case "$to" in
+ c*) to="0x$to"
+ ;;
+ .+*)
+ to=${to#.+}
+ if [ "$branch" = 'b' ]; then
+ if (( to >= 0x2000000 )); then
+ to=$(( to - 0x4000000 ))
+ fi
+ elif (( to >= 0x8000 )); then
+ to=$(( to - 0x10000 ))
+ fi
+ printf -v to '0x%x' $(( "0x$from" + to ))
+ ;;
+ *) printf 'Unkown branch format\n'
+ ;;
+ esac
+ if [ "$to" = "$sim" ]; then
+ continue
+ fi
if (( to > end_intr )); then
if $all_good; then
printf '%s\n' 'WARNING: Unrelocated relative branches'