source: trunk/UNIT_TESTER/dupsymwarn.pl

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