1#!/bin/sh
2#   Usage: unwcheck.sh <executable_file_name>
3#   Pre-requisite: readelf [from Gnu binutils package]
4#   Purpose: Check the following invariant
5#       For each code range in the input binary:
6#          Sum[ lengths of unwind regions] = Number of slots in code range.
7#   Author : Harish Patil
8#   First version: January 2002
9#   Modified : 2/13/2002
10#   Modified : 3/15/2002: duplicate detection
11readelf -u $1 | gawk '\
12 function todec(hexstr){
13    dec = 0;
14    l = length(hexstr);
15    for (i = 1; i <= l; i++)
16    {
17        c = substr(hexstr, i, 1);
18        if (c == "A")
19            dec = dec*16 + 10;
20        else if (c == "B")
21            dec = dec*16 + 11;
22        else if (c == "C")
23            dec = dec*16 + 12;
24        else if (c == "D")
25            dec = dec*16 + 13;
26        else if (c == "E")
27            dec = dec*16 + 14;
28        else if (c == "F")
29            dec = dec*16 + 15;
30        else
31            dec = dec*16 + c;
32    }
33    return dec;
34 }
35 BEGIN { first = 1; sum_rlen = 0; no_slots = 0; errors=0; no_code_ranges=0; }
36 {
37   if (NF==5 && $3=="info")
38   {
39      no_code_ranges += 1;
40      if (first == 0)
41      {
42         if (sum_rlen != no_slots)
43         {
44            print full_code_range;
45            print "       ", "lo = ", lo, " hi =", hi;
46            print "       ", "sum_rlen = ", sum_rlen, "no_slots = " no_slots;
47            print "       ","   ", "*******ERROR ***********";
48            print "       ","   ", "sum_rlen:", sum_rlen, " != no_slots:" no_slots;
49            errors += 1;
50         }
51         sum_rlen = 0;
52      }
53      full_code_range =  $0;
54      code_range =  $2;
55      gsub("..$", "", code_range);
56      gsub("^.", "", code_range);
57      split(code_range, addr, "-");
58      lo = toupper(addr[1]);
59
60      code_range_lo[no_code_ranges] = addr[1];
61      occurs[addr[1]] += 1;
62      full_range[addr[1]] = $0;
63
64      gsub("0X.[0]*", "", lo);
65      hi = toupper(addr[2]);
66      gsub("0X.[0]*", "", hi);
67      no_slots = (todec(hi) - todec(lo))/ 16*3
68      first = 0;
69   }
70   if (index($0,"rlen") > 0 )
71   {
72    rlen_str =  substr($0, index($0,"rlen"));
73    rlen = rlen_str;
74    gsub("rlen=", "", rlen);
75    gsub(")", "", rlen);
76    sum_rlen = sum_rlen +  rlen;
77   }
78  }
79  END {
80      if (first == 0)
81      {
82         if (sum_rlen != no_slots)
83         {
84            print "code_range=", code_range;
85            print "       ", "lo = ", lo, " hi =", hi;
86            print "       ", "sum_rlen = ", sum_rlen, "no_slots = " no_slots;
87            print "       ","   ", "*******ERROR ***********";
88            print "       ","   ", "sum_rlen:", sum_rlen, " != no_slots:" no_slots;
89            errors += 1;
90         }
91      }
92    no_duplicates = 0;
93    for (i=1; i<=no_code_ranges; i++)
94    {
95        cr = code_range_lo[i];
96        if (reported_cr[cr]==1) continue;
97        if ( occurs[cr] > 1)
98        {
99            reported_cr[cr] = 1;
100            print "Code range low ", code_range_lo[i], ":", full_range[cr], " occurs: ", occurs[cr], " times.";
101            print " ";
102            no_duplicates++;
103        }
104    }
105    print "======================================"
106    print "Total errors:", errors, "/", no_code_ranges, " duplicates:", no_duplicates;
107    print "======================================"
108  }
109  '
110