Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: unrel_branch_check.sh: enable the use of llvm-objdump v9, 10 or 11

Currently, using llvm-objtool, this script just silently succeeds without
actually do the intended checking. So this updates it to work properly.

Firstly, llvm-objdump does not add target symbol names to the end
of branches in its asm output, so we have to drop the branch to
__start_initialization_multiplatform using its address.

Secondly, v9 and 10 specify branch targets as .+<offset>, so we convert
those to actual addresses.

Thirdly, v10 and 11 error out on a vmlinux if given the -R option
complaining that it is "not a dynamic object". The -R does not make
any difference to the asm output, so remove it.

Lastly, v11 produces asm that is very similar to Gnu objtool (at least
as far as branches are concerned), so no further changes are necessary
to make it work.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200812081036.7969-3-sfr@canb.auug.org.au

authored by

Stephen Rothwell and committed by
Michael Ellerman
6b1992bc b71dca98

+29 -5
+29 -5
arch/powerpc/tools/unrel_branch_check.sh
··· 18 18 exit 0 19 19 fi 20 20 21 - $objdump -R -D --no-show-raw-insn --start-address="$kstart" --stop-address="$end_intr" "$vmlinux" | 21 + # we know that there is a correct branch to 22 + # __start_initialization_multiplatform, so find its address 23 + # so we can exclude it. 24 + sim=0x$($nm -p "$vmlinux" | 25 + sed -E -n '/\s+[[:alpha:]]\s+__start_initialization_multiplatform\s*$/{s///p;q}') 26 + 27 + $objdump -D --no-show-raw-insn --start-address="$kstart" --stop-address="$end_intr" "$vmlinux" | 22 28 sed -E -n ' 23 29 # match lines that start with a kernel address 24 30 /^c[0-9a-f]*:\s*b/ { 25 - # drop a target that we do not care about 26 - /\<__start_initialization_multiplatform>/d 27 31 # drop branches via ctr or lr 28 32 /\<b.?.?(ct|l)r/d 29 33 # cope with some differences between Clang and GNU objdumps ··· 37 33 s/\s0x/ / 38 34 s/:// 39 35 # format for the loop below 40 - s/^(\S+)\s+(\S+)\s+(\S+)\s*(\S*).*$/\1:\2:0x\3:\4/ 36 + s/^(\S+)\s+(\S+)\s+(\S+)\s*(\S*).*$/\1:\2:\3:\4/ 41 37 # strip out condition registers 42 - s/:0xcr[0-7],/:0x/ 38 + s/:cr[0-7],/:/ 43 39 p 44 40 }' | { 45 41 46 42 all_good=true 47 43 while IFS=: read -r from branch to sym; do 44 + case "$to" in 45 + c*) to="0x$to" 46 + ;; 47 + .+*) 48 + to=${to#.+} 49 + if [ "$branch" = 'b' ]; then 50 + if (( to >= 0x2000000 )); then 51 + to=$(( to - 0x4000000 )) 52 + fi 53 + elif (( to >= 0x8000 )); then 54 + to=$(( to - 0x10000 )) 55 + fi 56 + printf -v to '0x%x' $(( "0x$from" + to )) 57 + ;; 58 + *) printf 'Unkown branch format\n' 59 + ;; 60 + esac 61 + if [ "$to" = "$sim" ]; then 62 + continue 63 + fi 48 64 if (( to > end_intr )); then 49 65 if $all_good; then 50 66 printf '%s\n' 'WARNING: Unrelocated relative branches'