1 #!/bin/ksh
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License, Version 1.0 only
   7 # (the "License").  You may not use this file except in compliance
   8 # with the License.
   9 #
  10 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  11 # or http://www.opensolaris.org/os/licensing.
  12 # See the License for the specific language governing permissions
  13 # and limitations under the License.
  14 #
  15 # When distributing Covered Code, include this CDDL HEADER in each
  16 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  17 # If applicable, add the following below this CDDL HEADER, with the
  18 # fields enclosed by brackets "[]" replaced with your own identifying
  19 # information: Portions Copyright [yyyy] [name of copyright owner]
  20 #
  21 # CDDL HEADER END
  22 #
  23 #
  24 # Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  25 # Use is subject to license terms.
  26 # 
  27 #ident  "%Z%%M% %I%     %E% SMI"
  28 #
  29 # elfcmp - compare significant sections in two ELF files
  30 #
  31 # usage: elfcmp [-v] [-S] [-s section ...] <f1> <f2>
  32 #
  33 
  34 VERBOSE=0
  35 SECTIONLIST=""
  36 SIGNING_CHECK=0
  37 ERRORS=0
  38 
  39 usage() {
  40         echo 'Usage: elfcmp [-v] [-S] [-s section ...] <f1> <f2>' 1>&2
  41         exit 1
  42 }
  43 
  44 while [[ $# > 0 ]]
  45 do
  46         case "$1" in
  47         -v)
  48                 VERBOSE=1
  49                 ;;
  50         -s)
  51                 SECTIONLIST="$2"
  52                 shift
  53                 ;;
  54         -S)
  55                 SIGNING_CHECK=1
  56                 ;;
  57         -*)
  58                 usage
  59                 ;;
  60         *)
  61                 break
  62                 ;;
  63         esac
  64         shift
  65 done
  66 
  67 if [[ $# != 2 ]]
  68 then
  69         usage
  70 fi
  71 
  72 TMP1=/tmp/elfcmp.1.$$
  73 TMP2=/tmp/elfcmp.2.$$
  74 trap "rm -f $TMP1 $TMP2" EXIT HUP INT QUIT PIPE TERM
  75 
  76 list_sections() {
  77         dump -h "$1" | grep '\[[0-9]' | awk '{print $7}'
  78 }
  79 
  80 list_alloc_sections() {
  81         dump -hv "$1" | grep '\[[0-9]' | awk '$3 ~ /A/ {print $4, $5, $6, $7}'
  82 }
  83 
  84 signing_filter() {
  85         /usr/xpg4/bin/grep -v -e \\$SHSTRTAB -e \\.SUNW_signature
  86 }
  87         
  88 # get section lists for both files into temp files
  89 
  90 if [[ "$SECTIONLIST" = "" ]]
  91 then
  92         if [[ $SIGNING_CHECK = 1 ]]
  93         then
  94                 SHSTRNDX=`dump -f "$1" | awk '{if (NR==11) print $5}'`
  95                 SHSTRTAB=`dump -h "$1" | grep "^\\[$SHSTRNDX\\]" | \
  96                         awk '{print $7}'`
  97                 FILTER=signing_filter
  98         else
  99                 FILTER=cat
 100         fi
 101 
 102         list_sections "$1" | $FILTER | sort >$TMP1
 103         list_sections "$2" | $FILTER | sort >$TMP2
 104 else
 105         echo "$SECTIONLIST" >$TMP1
 106         echo "$SECTIONLIST" >$TMP2
 107 fi
 108 
 109 # determine and print which ones aren't in both of the input files
 110 
 111 NOT_IN_1=$(comm -13 $TMP1 $TMP2)
 112 if [[ ! -z "$NOT_IN_1" ]]
 113 then
 114         echo "Section(s) $NOT_IN_1 not in $1"
 115         (( ERRORS += 1 ))
 116 fi
 117 NOT_IN_2=$(comm -23 $TMP1 $TMP2)
 118 if [[ ! -z "$NOT_IN_2" ]]
 119 then
 120         echo "Section(s) $NOT_IN_2 not in $2"
 121         (( ERRORS += 1 ))
 122 fi
 123 
 124 # for all the sections which *are* common, do the following
 125 
 126 for s in $(comm -12 $TMP1 $TMP2)
 127 do
 128         dump -s -n $s "$1" | sed '/:/d' >$TMP1
 129         dump -s -n $s "$2" | sed '/:/d' >$TMP2
 130         if cmp -s $TMP1 $TMP2
 131         then
 132                 if [[ $VERBOSE = 1 ]]
 133                 then
 134                         echo "Section $s is the same"
 135                 fi
 136         else
 137                 echo "Section $s differs"
 138                 if [[ $VERBOSE = 1 ]]
 139                 then
 140                         dump -sv -n $s "$1" | sed '/:/d' >$TMP1
 141                         dump -sv -n $s "$2" | sed '/:/d' >$TMP2
 142                         diff -c $TMP1 $TMP2
 143                 fi
 144                 (( ERRORS += 1 ))
 145         fi
 146 done
 147 
 148 # verify that allocated objects have not moved
 149 # only applies to signed objects with a program header
 150 
 151 if [[ $SIGNING_CHECK = 1 ]]
 152 then
 153         HDR=$(dump -op $1 | wc -l)
 154         if [[ $HDR -gt 2 ]]
 155         then
 156                 list_alloc_sections "$1" | sort >$TMP1
 157                 list_alloc_sections "$2" | sort >$TMP2
 158                 if cmp -s $TMP1 $TMP2
 159                 then
 160                         if [[ $VERBOSE = 1 ]]
 161                         then
 162                                 echo "Allocated sections are the same"
 163                         fi
 164                 else
 165                         echo "Allocated section(s) changed"
 166                         if [[ $VERBOSE = 1 ]]
 167                         then
 168                                 diff -c $TMP1 $TMP2
 169                         fi
 170                         (( ERRORS += 1 ))
 171                 fi
 172         fi
 173 fi
 174 
 175 exit $ERRORS