From 79192ca8ebd9a25c583aa46024a250fef1e7766f Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Mon, 7 Apr 2014 18:30:29 +0000 Subject: scripts: objdiff: detect object code changes between two commits objdiff is useful when doing large code cleanups. For example, when removing checkpatch warnings and errors from new drivers in the staging tree. objdiff can be used in conjunction with a git rebase to confirm that each commit made no changes to the resulting object code. It has the same return values as diff(1). This was written specifically to support adding the skein and threefish cryto drivers to the staging tree. I needed a programmatic way to confirm that commits changing >90% of the lines didn't inadvertently change the code. Temporary files (objdump output) are stored in /path/to/linux/.tmp_objdiff 'make mrproper' will remove this directory. Signed-off-by: Jason Cooper Signed-off-by: Michal Marek --- scripts/objdiff | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100755 scripts/objdiff (limited to 'scripts/objdiff') diff --git a/scripts/objdiff b/scripts/objdiff new file mode 100755 index 000000000000..b3e4f10bfc3e --- /dev/null +++ b/scripts/objdiff @@ -0,0 +1,141 @@ +#!/bin/bash + +# objdiff - a small script for validating that a commit or series of commits +# didn't change object code. +# +# Copyright 2014, Jason Cooper +# +# Licensed under the terms of the GNU GPL version 2 + +# usage example: +# +# $ git checkout COMMIT_A +# $ +# $ ./scripts/objdiff record path/to/*.o +# +# $ git checkout COMMIT_B +# $ +# $ ./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 + +GIT_DIR="`git rev-parse --git-dir`" + +if [ -d "$GIT_DIR" ]; then + TMPD="${GIT_DIR%git}tmp_objdiff" + + [ -d "$TMPD" ] || mkdir "$TMPD" +else + echo "ERROR: git directory not found." + exit 1 +fi + +usage() { + echo "Usage: $0 " + echo " record " + echo " diff " + echo " clean all | " + exit 1 +} + +dorecord() { + [ $# -eq 0 ] && usage + + FILES="$*" + + CMT="`git rev-parse --short HEAD`" + + OBJDUMP="${CROSS_COMPILE}objdump" + OBJDIFFD="$TMPD/$CMT" + + [ ! -d "$OBJDIFFD" ] && mkdir -p "$OBJDIFFD" + + for f in $FILES; do + dn="${f%/*}" + bn="${f##*/}" + + [ ! -d "$OBJDIFFD/$dn" ] && mkdir -p "$OBJDIFFD/$dn" + + # remove addresses for a more clear diff + # http://dummdida.tumblr.com/post/60924060451/binary-diff-between-libc-from-scientificlinux-and + $OBJDUMP -D "$f" | sed "s/^[[:space:]]\+[0-9a-f]\+//" \ + >"$OBJDIFFD/$dn/$bn" + 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 "ERROR: $SRCD doesn't exist" + exit 1 + fi + + if [ ! -d "$DSTD" ]; then + echo "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 "$CMT not found" + fi + fi +} + +[ $# -eq 0 ] && usage + +case "$1" in + record) + shift + dorecord $* + ;; + diff) + shift + dodiff $* + ;; + clean) + shift + doclean $* + ;; + *) + echo "Unrecognized command '$1'" + exit 1 + ;; +esac -- cgit From fd6e12423311697860f30d10398a0f9eb91977d2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 Jun 2014 11:16:34 +0900 Subject: scripts: objdiff: get the path to .tmp_objdiff more simply This commit is a minor refactoring. Temporary files for objdiff are stored in .tmp_objdiff directory which is located at the top directory. To get the path to this directory, SRCTREE=`git rev-parse --show-toplevel` TMPD=$SRCTREE/.tmp_objdiff seems easier to understand than GIT_DIR=`git rev-parse --git-dir` TMPD=${GIT_DIR%git}tmp_objdiff Besides, it is not always necessary to create .tmp_objdiff dicrectory. It should be created only for "record" command. Signed-off-by: Masahiro Yamada Acked-by: Jason Cooper Signed-off-by: Michal Marek --- scripts/objdiff | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'scripts/objdiff') diff --git a/scripts/objdiff b/scripts/objdiff index b3e4f10bfc3e..b8f7fc60563e 100755 --- a/scripts/objdiff +++ b/scripts/objdiff @@ -25,17 +25,15 @@ # # Note: 'make mrproper' will also remove .tmp_objdiff -GIT_DIR="`git rev-parse --git-dir`" +SRCTREE=$(git rev-parse --show-toplevel 2>/dev/null) -if [ -d "$GIT_DIR" ]; then - TMPD="${GIT_DIR%git}tmp_objdiff" - - [ -d "$TMPD" ] || mkdir "$TMPD" -else - echo "ERROR: git directory not found." +if [ -z "$SRCTREE" ]; then + echo "ERROR: Not a git repository." exit 1 fi +TMPD=$SRCTREE/.tmp_objdiff + usage() { echo "Usage: $0 " echo " record " -- cgit From 5ab370e91af70d5f1b1dbaec78798a2ff236a2d5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 Jun 2014 11:16:35 +0900 Subject: scripts: objdiff: direct error messages to stderr Signed-off-by: Masahiro Yamada Acked-by: Jason Cooper Signed-off-by: Michal Marek --- scripts/objdiff | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'scripts/objdiff') diff --git a/scripts/objdiff b/scripts/objdiff index b8f7fc60563e..cc6736553958 100755 --- a/scripts/objdiff +++ b/scripts/objdiff @@ -28,17 +28,17 @@ SRCTREE=$(git rev-parse --show-toplevel 2>/dev/null) if [ -z "$SRCTREE" ]; then - echo "ERROR: Not a git repository." + echo >&2 "ERROR: Not a git repository." exit 1 fi TMPD=$SRCTREE/.tmp_objdiff usage() { - echo "Usage: $0 " - echo " record " - echo " diff " - echo " clean all | " + echo >&2 "Usage: $0 " + echo >&2 " record " + echo >&2 " diff " + echo >&2 " clean all | " exit 1 } @@ -88,12 +88,12 @@ dodiff() { DSTD="$TMPD/$DST" if [ ! -d "$SRCD" ]; then - echo "ERROR: $SRCD doesn't exist" + echo >&2 "ERROR: $SRCD doesn't exist" exit 1 fi if [ ! -d "$DSTD" ]; then - echo "ERROR: $DSTD doesn't exist" + echo >&2 "ERROR: $DSTD doesn't exist" exit 1 fi @@ -112,7 +112,7 @@ doclean() { if [ -d "$TMPD/$CMT" ]; then rm -rf $TMPD/$CMT else - echo "$CMT not found" + echo >&2 "$CMT not found" fi fi } @@ -133,7 +133,7 @@ case "$1" in doclean $* ;; *) - echo "Unrecognized command '$1'" + echo >&2 "Unrecognized command '$1'" exit 1 ;; esac -- cgit From 1ecc8e489abfdaa6d8d1689f7ff62fdf1adda30c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 Jun 2014 11:16:36 +0900 Subject: scripts: objdiff: remove unnecessary code The directories for objdump is created by the code a few lines below: [ ! -d "$OBJDIFFD/$dn" ] && mkdir -p "$OBJDIFFD/$dn" Signed-off-by: Masahiro Yamada Acked-by: Jason Cooper Signed-off-by: Michal Marek --- scripts/objdiff | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts/objdiff') diff --git a/scripts/objdiff b/scripts/objdiff index cc6736553958..6e72f9645983 100755 --- a/scripts/objdiff +++ b/scripts/objdiff @@ -52,8 +52,6 @@ dorecord() { OBJDUMP="${CROSS_COMPILE}objdump" OBJDIFFD="$TMPD/$CMT" - [ ! -d "$OBJDIFFD" ] && mkdir -p "$OBJDIFFD" - for f in $FILES; do dn="${f%/*}" bn="${f##*/}" -- cgit From 18165efa8203a34d82f60a1831ea290e7304c654 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 Jun 2014 11:16:37 +0900 Subject: scripts: objdiff: improve path flexibility for record command Prior to this commit, scripts/objdiff expected to be run at the top directory and only the relative path of objects. This commit provides more flexibility in terms of object path: [1] scripts/objdiff can be run in any directory For example, $ scripts/objdiff record init/main.o and $ cd init; ../scripts/objdiff record main.o produce the same result. [2] Support absolute path for objects $ scripts/objdiff record /home/foo/bar/linux/init/main.o work as well. Signed-off-by: Masahiro Yamada Acked-by: Jason Cooper Signed-off-by: Michal Marek --- scripts/objdiff | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'scripts/objdiff') diff --git a/scripts/objdiff b/scripts/objdiff index 6e72f9645983..499eb4bc1e8d 100755 --- a/scripts/objdiff +++ b/scripts/objdiff @@ -25,7 +25,7 @@ # # Note: 'make mrproper' will also remove .tmp_objdiff -SRCTREE=$(git rev-parse --show-toplevel 2>/dev/null) +SRCTREE=$(cd $(git rev-parse --show-toplevel 2>/dev/null); pwd) if [ -z "$SRCTREE" ]; then echo >&2 "ERROR: Not a git repository." @@ -42,6 +42,18 @@ usage() { exit 1 } +get_output_dir() { + dir=${1%/*} + + if [ "$dir" = "$1" ]; then + dir=. + fi + + dir=$(cd $dir; pwd) + + echo $TMPD/$CMT${dir#$SRCTREE} +} + dorecord() { [ $# -eq 0 ] && usage @@ -50,18 +62,16 @@ dorecord() { CMT="`git rev-parse --short HEAD`" OBJDUMP="${CROSS_COMPILE}objdump" - OBJDIFFD="$TMPD/$CMT" for f in $FILES; do - dn="${f%/*}" + dir=$(get_output_dir $f) bn="${f##*/}" - [ ! -d "$OBJDIFFD/$dn" ] && mkdir -p "$OBJDIFFD/$dn" + [ ! -d "$dir" ] && mkdir -p $dir # remove addresses for a more clear diff # http://dummdida.tumblr.com/post/60924060451/binary-diff-between-libc-from-scientificlinux-and - $OBJDUMP -D "$f" | sed "s/^[[:space:]]\+[0-9a-f]\+//" \ - >"$OBJDIFFD/$dn/$bn" + $OBJDUMP -D $f | sed "s/^[[:space:]]\+[0-9a-f]\+//" > $dir/$bn done } -- cgit From 8b5d0f20d64f00ffd5685879f8eb3659379f5aaa Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 Jun 2014 11:16:38 +0900 Subject: scripts: objdiff: change the extension of disassembly from .o to .dis Prior to this commit, the command "scripts/objdiff record path/to/*.o" disassembled the given object into ".tmp_objdiff/path/to/*.o" file. The problem here is that recorded disassemblies are lost if we run "make clean" because it removes all the *.o files. Disassembled code should be dumped into *.dis instead of *.o files. Signed-off-by: Masahiro Yamada Acked-by: Jason Cooper Signed-off-by: Michal Marek --- scripts/objdiff | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'scripts/objdiff') diff --git a/scripts/objdiff b/scripts/objdiff index 499eb4bc1e8d..c997e44e4b54 100755 --- a/scripts/objdiff +++ b/scripts/objdiff @@ -65,13 +65,14 @@ dorecord() { for f in $FILES; do dir=$(get_output_dir $f) - bn="${f##*/}" + base=${f##*/} + dis=$dir/${base%.o}.dis [ ! -d "$dir" ] && mkdir -p $dir # remove addresses for a more clear diff # http://dummdida.tumblr.com/post/60924060451/binary-diff-between-libc-from-scientificlinux-and - $OBJDUMP -D $f | sed "s/^[[:space:]]\+[0-9a-f]\+//" > $dir/$bn + $OBJDUMP -D $f | sed "s/^[[:space:]]\+[0-9a-f]\+//" > $dis done } -- cgit From 8ac28bee76eec006aac5ba5c418878a607d53a9b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 Jun 2014 11:16:39 +0900 Subject: scripts: objdiff: fix a comment Signed-off-by: Masahiro Yamada Acked-by: Jason Cooper Signed-off-by: Michal Marek --- scripts/objdiff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/objdiff') diff --git a/scripts/objdiff b/scripts/objdiff index c997e44e4b54..0644898d5fab 100755 --- a/scripts/objdiff +++ b/scripts/objdiff @@ -70,7 +70,7 @@ dorecord() { [ ! -d "$dir" ] && mkdir -p $dir - # remove addresses for a more clear diff + # remove addresses for a cleaner diff # http://dummdida.tumblr.com/post/60924060451/binary-diff-between-libc-from-scientificlinux-and $OBJDUMP -D $f | sed "s/^[[:space:]]\+[0-9a-f]\+//" > $dis done -- cgit From 7fa0e6db3cedc9b70d68a4170f1352e2b1aa0f90 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 Jun 2014 11:16:40 +0900 Subject: scripts: objdiff: support directories for the augument of record command For example, $ scripts/objdiff record init drivers/usb disassembles all the objects under init and drivers/usb directories. This feature would be useful when we change various files under the specific directory. Signed-off-by: Masahiro Yamada Acked-by: Jason Cooper Signed-off-by: Michal Marek --- scripts/objdiff | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'scripts/objdiff') diff --git a/scripts/objdiff b/scripts/objdiff index 0644898d5fab..62e51dae2138 100755 --- a/scripts/objdiff +++ b/scripts/objdiff @@ -36,7 +36,7 @@ TMPD=$SRCTREE/.tmp_objdiff usage() { echo >&2 "Usage: $0 " - echo >&2 " record " + echo >&2 " record " echo >&2 " diff " echo >&2 " clean all | " exit 1 @@ -54,6 +54,18 @@ get_output_dir() { echo $TMPD/$CMT${dir#$SRCTREE} } +do_objdump() { + dir=$(get_output_dir $1) + base=${1##*/} + 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 + $OBJDUMP -D $1 | sed "s/^[[:space:]]\+[0-9a-f]\+//" > $dis +} + dorecord() { [ $# -eq 0 ] && usage @@ -63,16 +75,15 @@ dorecord() { OBJDUMP="${CROSS_COMPILE}objdump" - for f in $FILES; do - dir=$(get_output_dir $f) - base=${f##*/} - 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 - $OBJDUMP -D $f | sed "s/^[[:space:]]\+[0-9a-f]\+//" > $dis + 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 } -- cgit