1*4882a593Smuzhiyun#!/bin/bash 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun# objdiff - a small script for validating that a commit or series of commits 5*4882a593Smuzhiyun# didn't change object code. 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# Copyright 2014, Jason Cooper <jason@lakedaemon.net> 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun# usage example: 11*4882a593Smuzhiyun# 12*4882a593Smuzhiyun# $ git checkout COMMIT_A 13*4882a593Smuzhiyun# $ <your fancy build command here> 14*4882a593Smuzhiyun# $ ./scripts/objdiff record path/to/*.o 15*4882a593Smuzhiyun# 16*4882a593Smuzhiyun# $ git checkout COMMIT_B 17*4882a593Smuzhiyun# $ <your fancy build command here> 18*4882a593Smuzhiyun# $ ./scripts/objdiff record path/to/*.o 19*4882a593Smuzhiyun# 20*4882a593Smuzhiyun# $ ./scripts/objdiff diff COMMIT_A COMMIT_B 21*4882a593Smuzhiyun# $ 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun# And to clean up (everything is in .tmp_objdiff/*) 24*4882a593Smuzhiyun# $ ./scripts/objdiff clean all 25*4882a593Smuzhiyun# 26*4882a593Smuzhiyun# Note: 'make mrproper' will also remove .tmp_objdiff 27*4882a593Smuzhiyun 28*4882a593SmuzhiyunSRCTREE=$(cd $(git rev-parse --show-toplevel 2>/dev/null); pwd) 29*4882a593Smuzhiyun 30*4882a593Smuzhiyunif [ -z "$SRCTREE" ]; then 31*4882a593Smuzhiyun echo >&2 "ERROR: Not a git repository." 32*4882a593Smuzhiyun exit 1 33*4882a593Smuzhiyunfi 34*4882a593Smuzhiyun 35*4882a593SmuzhiyunTMPD=$SRCTREE/.tmp_objdiff 36*4882a593Smuzhiyun 37*4882a593Smuzhiyunusage() { 38*4882a593Smuzhiyun echo >&2 "Usage: $0 <command> <args>" 39*4882a593Smuzhiyun echo >&2 " record <list of object files or directories>" 40*4882a593Smuzhiyun echo >&2 " diff <commitA> <commitB>" 41*4882a593Smuzhiyun echo >&2 " clean all | <commit>" 42*4882a593Smuzhiyun exit 1 43*4882a593Smuzhiyun} 44*4882a593Smuzhiyun 45*4882a593Smuzhiyunget_output_dir() { 46*4882a593Smuzhiyun dir=${1%/*} 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun if [ "$dir" = "$1" ]; then 49*4882a593Smuzhiyun dir=. 50*4882a593Smuzhiyun fi 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun dir=$(cd $dir; pwd) 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun echo $TMPD/$CMT${dir#$SRCTREE} 55*4882a593Smuzhiyun} 56*4882a593Smuzhiyun 57*4882a593Smuzhiyundo_objdump() { 58*4882a593Smuzhiyun dir=$(get_output_dir $1) 59*4882a593Smuzhiyun base=${1##*/} 60*4882a593Smuzhiyun stripped=$dir/${base%.o}.stripped 61*4882a593Smuzhiyun dis=$dir/${base%.o}.dis 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun [ ! -d "$dir" ] && mkdir -p $dir 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun # remove addresses for a cleaner diff 66*4882a593Smuzhiyun # http://dummdida.tumblr.com/post/60924060451/binary-diff-between-libc-from-scientificlinux-and 67*4882a593Smuzhiyun $STRIP -g $1 -R __bug_table -R .note -R .comment -o $stripped 68*4882a593Smuzhiyun $OBJDUMP -D $stripped | sed -e "s/^[[:space:]]\+[0-9a-f]\+//" -e "s:^$stripped:$1:" > $dis 69*4882a593Smuzhiyun} 70*4882a593Smuzhiyun 71*4882a593Smuzhiyundorecord() { 72*4882a593Smuzhiyun [ $# -eq 0 ] && usage 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun FILES="$*" 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun CMT="`git rev-parse --short HEAD`" 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun STRIP="${CROSS_COMPILE}strip" 79*4882a593Smuzhiyun OBJDUMP="${CROSS_COMPILE}objdump" 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun for d in $FILES; do 82*4882a593Smuzhiyun if [ -d "$d" ]; then 83*4882a593Smuzhiyun for f in $(find $d -name '*.o') 84*4882a593Smuzhiyun do 85*4882a593Smuzhiyun do_objdump $f 86*4882a593Smuzhiyun done 87*4882a593Smuzhiyun else 88*4882a593Smuzhiyun do_objdump $d 89*4882a593Smuzhiyun fi 90*4882a593Smuzhiyun done 91*4882a593Smuzhiyun} 92*4882a593Smuzhiyun 93*4882a593Smuzhiyundodiff() { 94*4882a593Smuzhiyun [ $# -ne 2 ] && [ $# -ne 0 ] && usage 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun if [ $# -eq 0 ]; then 97*4882a593Smuzhiyun SRC="`git rev-parse --short HEAD^`" 98*4882a593Smuzhiyun DST="`git rev-parse --short HEAD`" 99*4882a593Smuzhiyun else 100*4882a593Smuzhiyun SRC="`git rev-parse --short $1`" 101*4882a593Smuzhiyun DST="`git rev-parse --short $2`" 102*4882a593Smuzhiyun fi 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun DIFF="`which colordiff`" 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun if [ ${#DIFF} -eq 0 ] || [ ! -x "$DIFF" ]; then 107*4882a593Smuzhiyun DIFF="`which diff`" 108*4882a593Smuzhiyun fi 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun SRCD="$TMPD/$SRC" 111*4882a593Smuzhiyun DSTD="$TMPD/$DST" 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun if [ ! -d "$SRCD" ]; then 114*4882a593Smuzhiyun echo >&2 "ERROR: $SRCD doesn't exist" 115*4882a593Smuzhiyun exit 1 116*4882a593Smuzhiyun fi 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun if [ ! -d "$DSTD" ]; then 119*4882a593Smuzhiyun echo >&2 "ERROR: $DSTD doesn't exist" 120*4882a593Smuzhiyun exit 1 121*4882a593Smuzhiyun fi 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun $DIFF -Nurd $SRCD $DSTD 124*4882a593Smuzhiyun} 125*4882a593Smuzhiyun 126*4882a593Smuzhiyundoclean() { 127*4882a593Smuzhiyun [ $# -eq 0 ] && usage 128*4882a593Smuzhiyun [ $# -gt 1 ] && usage 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun if [ "x$1" = "xall" ]; then 131*4882a593Smuzhiyun rm -rf $TMPD/* 132*4882a593Smuzhiyun else 133*4882a593Smuzhiyun CMT="`git rev-parse --short $1`" 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun if [ -d "$TMPD/$CMT" ]; then 136*4882a593Smuzhiyun rm -rf $TMPD/$CMT 137*4882a593Smuzhiyun else 138*4882a593Smuzhiyun echo >&2 "$CMT not found" 139*4882a593Smuzhiyun fi 140*4882a593Smuzhiyun fi 141*4882a593Smuzhiyun} 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun[ $# -eq 0 ] && usage 144*4882a593Smuzhiyun 145*4882a593Smuzhiyuncase "$1" in 146*4882a593Smuzhiyun record) 147*4882a593Smuzhiyun shift 148*4882a593Smuzhiyun dorecord $* 149*4882a593Smuzhiyun ;; 150*4882a593Smuzhiyun diff) 151*4882a593Smuzhiyun shift 152*4882a593Smuzhiyun dodiff $* 153*4882a593Smuzhiyun ;; 154*4882a593Smuzhiyun clean) 155*4882a593Smuzhiyun shift 156*4882a593Smuzhiyun doclean $* 157*4882a593Smuzhiyun ;; 158*4882a593Smuzhiyun *) 159*4882a593Smuzhiyun echo >&2 "Unrecognized command '$1'" 160*4882a593Smuzhiyun exit 1 161*4882a593Smuzhiyun ;; 162*4882a593Smuzhiyunesac 163