source: branches/gcc/UNIT_TESTER/dupsymwarn.pl

Last change on this file was 19810, checked in by westram, 3 weeks ago
  • Property svn:executable set to *
File size: 6.2 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6my $seenGlobalDups = 0;
7my $seenUnitDups   = undef;
8
9my $dumpAllSymbols = 0; # dump ALL found symbols (debugging only)
10
11my %gloc = (); # [global] key=symbol, value=location (or empty string)
12my %lloc = (); # [local]  key=symbol, value=location (or empty string)
13my %dloc = (); # key=symbol, value=location in .sym file where first defined
14
15sub acceptDupSym($);
16sub acceptDupSym($) {
17  # return true for all symbols that shall be accepted if duplicated
18  my ($sym) = @_;
19  # return 0 if $sym =~ /aw_never_called_main/o; # @@@ check whether AW_HEADER_MAIN is necessary
20  if ($sym =~ /^(ARB_main|aw_never_called_main)\(/o) {
21    return 1; # special ARB function
22  }
23  if ($sym eq 'aisc_main') {
24    return 1; # special ARB variable in generated code (exists once in PTSERVER and in NAMESERVER)
25  }
26  if ($sym =~ /^(_init|_fini)$/o) { # formerly also accepted __bss_start _edata and _end
27    return 1; # shared lib entry/exit points
28  }
29  if ($sym =~ /^__odr_asan\./o) { # ignore ASAN prefixes
30    return acceptDupSym($');
31  }
32  return 0;
33}
34
35sub addSym($$$$) {
36  my ($sym, $sloc, $symfile, $lineno) = @_;
37
38  my $haveLoc = $lloc{$sym};
39  my $haveDLoc = $dloc{$sym};
40  if (not defined $haveLoc) {
41    $lloc{$sym} = $sloc; # first definition
42  }
43  elsif ($haveLoc eq $sloc) { die "redefined symbol '$sym' with same location"; }
44  else {
45    die "had empty first definition (sym=$sym; sloc=$sloc)\n" if $haveLoc eq '';
46    die "empty redefinition (sym=$sym)\n" if $sloc eq '';
47
48    my $dloc = $symfile.':'.$lineno;
49    print "$haveLoc: Warning: first definition of $sym\n";
50    print "$dloc: Error: duplicated definition of $sym (in same unit). Bug?\n";
51    $seenUnitDups++;
52  }
53
54  if (not defined $haveDLoc) {
55    $dloc{$sym} = $symfile.':'.$lineno;
56  }
57}
58
59sub scanSymdef($$$) {
60  my ($line, $symfile, $lineno) = @_;
61  if ($line ne '') {
62    # format of symlist is documented at ./make_symlist.sh@SYMLIST_FORMAT
63
64    my @splitted = split /;/,$line;
65    my $splitted = scalar(@splitted);
66
67    die "expected to see 3 or 4 semicolon-separted parts (got: $splitted)" if $splitted<3 or $splitted>4;
68
69    my ($symScope, $symType, $protoOrName, $sloc)
70      = ( $splitted[0], $splitted[1], $splitted[2], $splitted[3] );
71    if (not defined $sloc) { $sloc = ''; }
72
73    if ($symScope eq 'def') {
74      addSym($protoOrName, $sloc, $symfile, $lineno);
75    }
76    elsif ($symScope eq 'ref') {
77      # ignore references
78    }
79    else {
80        die "cannot parse line '$line'\n";
81    }
82  }
83}
84
85sub nonEmpty($$) {
86  my ($locMaybeEmpty,$fakeLoc) = @_;
87  return $locMaybeEmpty eq '' ? $fakeLoc : $locMaybeEmpty;
88}
89
90sub dumpSymbolsOfThisUnit($) {
91  my ($fallback_loc) = @_;
92
93  my @sortedSyms = sort {
94    die if not defined $a;
95    die if not defined $b;
96
97    my $aloc = $lloc{$a};
98    my $bloc = $lloc{$b};
99
100    die if not defined $aloc;
101    die if not defined $bloc;
102
103    if (($aloc ne '') and ($bloc ne '')) {
104      my @aloc = split /:/o, $aloc;
105      my @bloc = split /:/o, $bloc;
106
107      if (scalar(@aloc)==3 and scalar(@bloc)==3) {
108        my $cmp = $aloc[0] cmp $bloc[0]; # compare filenames
109        if ($cmp == 0) {
110          if (($aloc[1] eq '') or ($bloc[1] eq '')) {
111            my $d1 = 'aloc[1]='.$aloc[1].' bloc[1]='.$bloc[1];
112            my $d2 = "a='$a' b='$b'";
113            my $d3 = "aloc='$aloc' bloc='$bloc'";
114            die "unexpected value parsed from locations: $d1 $d2 $d3\n ";
115          }
116          $cmp = $aloc[1] <=> $bloc[1]; # compare linenumbers
117          if ($cmp==0) {
118            $cmp = $a cmp $b;
119            die if $cmp eq 0;
120          }
121        }
122        $cmp;
123      }
124      else { die "broken locations detected\n"; }
125    }
126    else { $a cmp $b; }
127  } keys %lloc;
128
129  foreach my $sym (@sortedSyms) {
130    my $loc = $lloc{$sym};
131    print nonEmpty($loc, $fallback_loc).": Note: definition of symbol '$sym'\n";
132  }
133}
134
135my %warned = (); # key=symbol, value=1 if already warned about duplicate
136
137sub addFileSymbols($) {
138  # called after symfile has been completely scanned
139
140  my ($symfile) = @_;
141  my $fallback_loc = $symfile.':1';
142
143  foreach my $sym (keys %lloc) {
144    my $loc = $lloc{$sym}; # is empty for _init and _fini.
145    my $haveGlobal = $gloc{$sym};
146    if (defined $haveGlobal) {
147      if (not acceptDupSym($sym)) {
148        my $firstDefAt = $dloc{$sym};
149        my $duplicated = 'another';
150        if (not exists $warned{$sym}) {
151          print nonEmpty($haveGlobal,$firstDefAt).": Warning: first occurrence of $sym\n";
152          $warned{$sym} = 1;
153          $duplicated = 'duplicated';
154        }
155        print nonEmpty($loc,$fallback_loc).": Warning: $duplicated occurrence of $sym\n";
156        $seenGlobalDups++;
157
158        if ($loc ne '') {
159          $gloc{$sym} = $loc;
160        }
161      }
162    }
163    else {
164      $gloc{$sym} = $loc;
165    }
166  }
167
168  if ($dumpAllSymbols) {
169    dumpSymbolsOfThisUnit($fallback_loc);
170  }
171
172  # reset local symbol tracking:
173  %lloc = ();
174}
175
176sub scanSymfile($) {
177  my ($symfile) = @_;
178  open(IN,'<'.$symfile) || die "failed to open '$symfile' (Reason: $!)";
179
180  my $lineno = 0;
181  eval {
182    my $line;
183    while (defined($line=<IN>)) {
184      chomp($line);
185      $lineno++;
186      scanSymdef($line, $symfile, $lineno);
187    }
188  };
189  if ($@) {
190    die "$symfile:$lineno: $@";
191  }
192  close(IN);
193}
194
195# --------------------------------------------------------------------------------
196
197sub main() {
198  my $args = scalar(@ARGV);
199  if ($args<1) {
200    die "Usage: dupsymwarn.pl make_symlist-output [make_symlist-output]+\n".
201      "Collects and warns about duplicated global symbols\n";
202  }
203
204  foreach my $symfile (@ARGV) { # one symfile for each unit
205    $seenUnitDups = 0;
206
207    scanSymfile($symfile);
208    addFileSymbols($symfile);
209
210    if ($seenUnitDups>0) {
211      print "Please note: detected $seenUnitDups duplicate symbols in unit ($symfile)\n";
212      print "             This may occur e.g. after renaming a source file.\n";
213      print "             In that case try to clean that UNIT using 'make UNIT/UNIT.clean'\n";
214    }
215  }
216
217  if ($seenGlobalDups>0) {
218    my $diffDups = scalar(keys %warned);
219    print "Encountered $seenGlobalDups duplicated global symbols in arb-codebase ($diffDups different)\n";
220    print "Notes:\n";
221    print " * this is checked in TESTED modules/libraries only.\n";
222    print " * duplicated symbols are unwanted => please fix them!\n";
223  }
224}
225main();
Note: See TracBrowser for help on using the repository browser.