123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- #!/bin/bash
- # objdiff - a small script for validating that a commit or series of commits
- # didn't change object code.
- #
- # Copyright 2014, Jason Cooper <jason@lakedaemon.net>
- #
- # Licensed under the terms of the GNU GPL version 2
- # usage example:
- #
- # $ git checkout COMMIT_A
- # $ <your fancy build command here>
- # $ ./scripts/objdiff record path/to/*.o
- #
- # $ git checkout COMMIT_B
- # $ <your fancy build command here>
- # $ ./scripts/objdiff record path/to/*.o
- #
- # $ ./scripts/objdiff diff COMMIT_A COMMIT_B
- # $
- # And to clean up (everything is in .tmp_objdiff/*)
- # $ ./scripts/objdiff clean all
- #
- # Note: 'make mrproper' will also remove .tmp_objdiff
- SRCTREE=$(cd $(git rev-parse --show-toplevel 2>/dev/null); pwd)
- if [ -z "$SRCTREE" ]; then
- echo >&2 "ERROR: Not a git repository."
- exit 1
- fi
- TMPD=$SRCTREE/.tmp_objdiff
- usage() {
- echo >&2 "Usage: $0 <command> <args>"
- echo >&2 " record <list of object files or directories>"
- echo >&2 " diff <commitA> <commitB>"
- echo >&2 " clean all | <commit>"
- exit 1
- }
- get_output_dir() {
- dir=${1%/*}
- if [ "$dir" = "$1" ]; then
- dir=.
- fi
- dir=$(cd $dir; pwd)
- echo $TMPD/$CMT${dir#$SRCTREE}
- }
- do_objdump() {
- dir=$(get_output_dir $1)
- base=${1##*/}
- stripped=$dir/${base%.o}.stripped
- dis=$dir/${base%.o}.dis
- [ ! -d "$dir" ] && mkdir -p $dir
- # remove addresses for a cleaner diff
- # http://dummdida.tumblr.com/post/60924060451/binary-diff-between-libc-from-scientificlinux-and
- $STRIP -g $1 -R __bug_table -R .note -R .comment -o $stripped
- $OBJDUMP -D $stripped | sed -e "s/^[[:space:]]\+[0-9a-f]\+//" -e "s:^$stripped:$1:" > $dis
- }
- dorecord() {
- [ $# -eq 0 ] && usage
- FILES="$*"
- CMT="`git rev-parse --short HEAD`"
- STRIP="${CROSS_COMPILE}strip"
- OBJDUMP="${CROSS_COMPILE}objdump"
- for d in $FILES; do
- if [ -d "$d" ]; then
- for f in $(find $d -name '*.o')
- do
- do_objdump $f
- done
- else
- do_objdump $d
- fi
- done
- }
- dodiff() {
- [ $# -ne 2 ] && [ $# -ne 0 ] && usage
- if [ $# -eq 0 ]; then
- SRC="`git rev-parse --short HEAD^`"
- DST="`git rev-parse --short HEAD`"
- else
- SRC="`git rev-parse --short $1`"
- DST="`git rev-parse --short $2`"
- fi
- DIFF="`which colordiff`"
- if [ ${#DIFF} -eq 0 ] || [ ! -x "$DIFF" ]; then
- DIFF="`which diff`"
- fi
- SRCD="$TMPD/$SRC"
- DSTD="$TMPD/$DST"
- if [ ! -d "$SRCD" ]; then
- echo >&2 "ERROR: $SRCD doesn't exist"
- exit 1
- fi
- if [ ! -d "$DSTD" ]; then
- echo >&2 "ERROR: $DSTD doesn't exist"
- exit 1
- fi
- $DIFF -Nurd $SRCD $DSTD
- }
- doclean() {
- [ $# -eq 0 ] && usage
- [ $# -gt 1 ] && usage
- if [ "x$1" = "xall" ]; then
- rm -rf $TMPD/*
- else
- CMT="`git rev-parse --short $1`"
- if [ -d "$TMPD/$CMT" ]; then
- rm -rf $TMPD/$CMT
- else
- echo >&2 "$CMT not found"
- fi
- fi
- }
- [ $# -eq 0 ] && usage
- case "$1" in
- record)
- shift
- dorecord $*
- ;;
- diff)
- shift
- dodiff $*
- ;;
- clean)
- shift
- doclean $*
- ;;
- *)
- echo >&2 "Unrecognized command '$1'"
- exit 1
- ;;
- esac
|