diff options
-rwxr-xr-x | arch/powerpc/tools/unrel_branch_check.sh | 34 |
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' |