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