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 # elfcmp - compare significant sections in two ELF files
  28 #
  29 # usage: elfcmp [-v] [-S] [-s section ...] <f1> <f2>
  30 #
  31 
  32 VERBOSE=0
  33 SECTIONLIST=""
  34 SIGNING_CHECK=0
  35 ERRORS=0
  36 
  37 usage() {
  38         echo 'Usage: elfcmp [-v] [-S] [-s section ...] <f1> <f2>' 1>&2
  39         exit 1
  40 }
  41 
  42 while [[ $# > 0 ]]
  43 do
  44         case "$1" in
  45         -v)
  46                 VERBOSE=1
  47                 ;;
  48         -s)
  49                 SECTIONLIST="$2"
  50                 shift
  51                 ;;
  52         -S)
  53                 SIGNING_CHECK=1
  54                 ;;
  55         -*)
  56                 usage
  57                 ;;
  58         *)
  59                 break
  60                 ;;
  61         esac
  62         shift
  63 done
  64 
  65 if [[ $# != 2 ]]
  66 then
  67         usage
  68 fi
  69 
  70 TMP1=/tmp/elfcmp.1.$$
  71 TMP2=/tmp/elfcmp.2.$$
  72 trap "rm -f $TMP1 $TMP2" EXIT HUP INT QUIT PIPE TERM
  73 
  74 list_sections() {
  75         dump -h "$1" | grep '\[[0-9]' | awk '{print $7}'
  76 }
  77 
  78 list_alloc_sections() {
  79         dump -hv "$1" | grep '\[[0-9]' | awk '$3 ~ /A/ {print $4, $5, $6, $7}'
  80 }
  81 
  82 signing_filter() {
  83         /usr/bin/grep -v -e \\$SHSTRTAB -e \\.SUNW_signature
  84 }
  85         
  86 # get section lists for both files into temp files
  87 
  88 if [[ "$SECTIONLIST" = "" ]]
  89 then
  90         if [[ $SIGNING_CHECK = 1 ]]
  91         then
  92                 SHSTRNDX=`dump -f "$1" | awk '{if (NR==11) print $5}'`
  93                 SHSTRTAB=`dump -h "$1" | grep "^\\[$SHSTRNDX\\]" | \
  94                         awk '{print $7}'`
  95                 FILTER=signing_filter
  96         else
  97                 FILTER=cat
  98         fi
  99 
 100         list_sections "$1" | $FILTER | sort >$TMP1
 101         list_sections "$2" | $FILTER | sort >$TMP2
 102 else
 103         echo "$SECTIONLIST" >$TMP1
 104         echo "$SECTIONLIST" >$TMP2
 105 fi
 106 
 107 # determine and print which ones aren't in both of the input files
 108 
 109 NOT_IN_1=$(comm -13 $TMP1 $TMP2)
 110 if [[ ! -z "$NOT_IN_1" ]]
 111 then
 112         echo "Section(s) $NOT_IN_1 not in $1"
 113         (( ERRORS += 1 ))
 114 fi
 115 NOT_IN_2=$(comm -23 $TMP1 $TMP2)
 116 if [[ ! -z "$NOT_IN_2" ]]
 117 then
 118         echo "Section(s) $NOT_IN_2 not in $2"
 119         (( ERRORS += 1 ))
 120 fi
 121 
 122 # for all the sections which *are* common, do the following
 123 
 124 for s in $(comm -12 $TMP1 $TMP2)
 125 do
 126         dump -s -n $s "$1" | sed '/:/d' >$TMP1
 127         dump -s -n $s "$2" | sed '/:/d' >$TMP2
 128         if cmp -s $TMP1 $TMP2
 129         then
 130                 if [[ $VERBOSE = 1 ]]
 131                 then
 132                         echo "Section $s is the same"
 133                 fi
 134         else
 135                 echo "Section $s differs"
 136                 if [[ $VERBOSE = 1 ]]
 137                 then
 138                         dump -sv -n $s "$1" | sed '/:/d' >$TMP1
 139                         dump -sv -n $s "$2" | sed '/:/d' >$TMP2
 140                         diff -c $TMP1 $TMP2
 141                 fi
 142                 (( ERRORS += 1 ))
 143         fi
 144 done
 145 
 146 # verify that allocated objects have not moved
 147 # only applies to signed objects with a program header
 148 
 149 if [[ $SIGNING_CHECK = 1 ]]
 150 then
 151         HDR=$(dump -op $1 | wc -l)
 152         if [[ $HDR -gt 2 ]]
 153         then
 154                 list_alloc_sections "$1" | sort >$TMP1
 155                 list_alloc_sections "$2" | sort >$TMP2
 156                 if cmp -s $TMP1 $TMP2
 157                 then
 158                         if [[ $VERBOSE = 1 ]]
 159                         then
 160                                 echo "Allocated sections are the same"
 161                         fi
 162                 else
 163                         echo "Allocated section(s) changed"
 164                         if [[ $VERBOSE = 1 ]]
 165                         then
 166                                 diff -c $TMP1 $TMP2
 167                         fi
 168                         (( ERRORS += 1 ))
 169                 fi
 170         fi
 171 fi
 172 
 173 exit $ERRORS