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