source: tags/arb-7.0.2/UNIT_TESTER/dupsymwarn.pl

Last change on this file was 18426, checked in by westram, 4 years ago
  • Property svn:executable set to *
File size: 4.7 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6my $seenDups = 0;
7
8my %gloc = (); # [global] key=symbol, value=location (or empty string)
9my %lloc = (); # [local]  key=symbol, value=location (or empty string)
10my %rloc = (); # [local]  key=symbol, value=location of reference
11
12sub acceptDupSym($);
13sub acceptDupSym($) {
14  # return true for all symbols that shall be accepted if duplicated
15  my ($sym) = @_;
16  if ($sym =~ /^(ARB_main|aw_never_called_main)\(/o) {
17    return 1; # special ARB function
18  }
19  if ($sym =~ /^aisc_main/o) {
20    return 1; # special ARB variable
21  }
22  if ($sym =~ /^(_init|__bss_start|_edata|_fini|_end)$/o) {
23    return 1; # shared lib entry/exit points
24  }
25  if ($sym =~ /^__odr_asan\./o) { # ignore ASAN prefixes
26    return acceptDupSym($');
27  }
28  return 0;
29}
30
31sub isGlobalSymFlag($) {
32  # return true for all flags that shall be checked for duplicates
33  my ($f) = @_;
34  if (($f ge 'A' and $f le 'D') or ($f eq 'G') or ($f ge 'R' and $f le 'T')) {
35    return 1;
36  }
37  return 0;
38}
39
40sub isReferenceSymFlag($) {
41  my ($f) = @_;
42  if ($f eq 'U') {
43    return 1;
44  }
45  return 0;
46}
47
48sub addSym($$) {
49  my ($sym,$sloc) = @_;
50  my $haveLoc = $lloc{$sym};
51  if (not defined $haveLoc) {
52    $lloc{$sym} = $sloc; # first definition
53  }
54  elsif ($haveLoc eq '') { # first definition was empty
55    $lloc{$sym} = $sloc; # overwrite empty definition
56  }
57  elsif ($haveLoc ne $sloc) { # differing locations reported for one symbol (inside one unit)
58    if ($sloc ne '') { # ignore if second is empty (Note: does the same as overwrite above)
59      print "$haveLoc: Warning: first definition of $sym\n";
60      print "$sloc: Error: duplicated definition of $sym (in same unit). Bug?\n";
61    }
62  }
63}
64sub addRef($$) {
65  my ($sym,$sloc) = @_;
66  my $haveRef = $rloc{$sym};
67  if (not defined $haveRef) {
68    die if $sloc eq ''; # not allowed here
69    $rloc{$sym} = $sloc; # first reference
70  }
71  # ignore following references
72}
73
74my $reg_sym = qr/^[0-9a-f]*\s+([A-Z])\s(.*)$/i;
75my $reg_loc = qr/^(.*)\s([^\s]+:[0-9]+)$/i;
76
77sub scanSymdef($) {
78  my ($line) = @_;
79  if ($line ne '') {
80    if ($line =~ $reg_sym) {
81      my ($flag,$rest) = ($1,$2);
82      if (isGlobalSymFlag($flag)) {
83        if ($rest =~ $reg_loc) {
84          my ($proto,$sloc) = ($1,$2);
85          addSym($proto,$sloc);
86        }
87        else { # assume whole rest is prototype
88          addSym($rest,'');
89        }
90      }
91      elsif (isReferenceSymFlag($flag)) {
92        if ($rest =~ $reg_loc) {
93          my ($proto,$sloc) = ($1,$2);
94          addRef($proto,$sloc);
95        }
96        # ignore refs w/o location (they are not useful)
97      }
98    }
99    else {
100      if ($line =~ /^[^\s]+:$/o) { # accept start of single objects
101        ;
102      }
103      else {
104        die "cannot parse line '$line'\n";
105      }
106    }
107  }
108}
109
110sub nonEmpty($$) {
111  my ($locMaybeEmpty,$fakeLoc) = @_;
112  return $locMaybeEmpty eq '' ? $fakeLoc : $locMaybeEmpty;
113}
114
115sub addFileSymbols($) {
116  # called after symfile has been completely scanned
117
118  my ($symfile) = @_;
119  my $fallback_loc = $ENV{ARBHOME}.'/UNIT_TESTER/'.$symfile.':1';
120
121  foreach my $sym (keys %lloc) {
122    my $loc = $lloc{$sym};
123    if ($loc eq '') { # if location missing..
124      my $seenRef = $rloc{$sym};
125      if (defined $seenRef) {
126        $loc = $seenRef; # .. use location of reference
127      }
128    }
129
130    my $haveGlobal = $gloc{$sym};
131    if (defined $haveGlobal) {
132      if (not acceptDupSym($sym)) {
133        print nonEmpty($haveGlobal,$fallback_loc).": Warning: previous occurrence of $sym\n";
134        print nonEmpty($loc,$fallback_loc).": Warning: duplicated occurrence of $sym\n";
135        $seenDups++;
136
137        if ($loc ne '') {
138          $gloc{$sym} = $loc;
139        }
140      }
141    }
142    else {
143      $gloc{$sym} = $loc;
144    }
145  }
146
147  # reset local symbol tracking:
148  %lloc = ();
149  %rloc = ();
150}
151
152sub scanSymfile($) {
153  my ($symfile) = @_;
154  open(IN,'<'.$symfile) || die "failed to open '$symfile' (Reason: $!)";
155
156  my $lineno = 0;
157  eval {
158    my $line;
159    while (defined($line=<IN>)) {
160      chomp($line);
161      $lineno++;
162      scanSymdef($line);
163    }
164  };
165  if ($@) {
166    die "$symfile:$lineno: $@";
167  }
168  close(IN);
169}
170
171# --------------------------------------------------------------------------------
172
173sub main() {
174  my $args = scalar(@ARGV);
175  if ($args<1) {
176    die "Usage: dupsymwarn.pl nm-output [nm-output]+\n".
177      "Collects and warns about duplicated global symbols\n";
178  }
179
180  foreach my $symfile (@ARGV) {
181    scanSymfile($symfile);
182    addFileSymbols($symfile);
183  }
184
185  if ($seenDups>0) {
186    print "Encountered $seenDups duplicated global symbols in arb-codebase\n";
187    print "Notes:\n";
188    print " * this is checked in TESTED modules and libraries only (i.e. it may miss some dups)\n";
189    print " * this is unwanted => please fix it!\n";
190  }
191}
192main();
Note: See TracBrowser for help on using the repository browser.