* gcc.target/powerpc/altivec-volatile.c: Adjust expected warning.
[official-gcc.git] / contrib / make_sunver.pl
blob8d7ccc3ebb2c1603f09505249c6f1ec6c005696c
1 #!/usr/bin/perl -w
3 # make_sunver.pl
5 # This script takes at least two arguments, a GNU style version script and
6 # a list of object and archive files, and generates a corresponding Sun
7 # style version script as follows:
9 # Each glob pattern, C++ mangled pattern or literal in the input script is
10 # matched against all global symbols in the input objects, emitting those
11 # that matched (or nothing if no match was found).
12 # A comment with the original pattern and its type is left in the output
13 # file to make it easy to understand the matches.
15 # It expects a 'nm' with the POSIX '-P' option, but everyone has one of
16 # those, right?
17 # It depends on the GNU version of c++filt, since it must understand the
18 # GNU mangling style.
20 use File::Glob ':glob';
21 use FileHandle;
22 use IPC::Open2;
24 # Input version script, GNU style.
25 my $symvers = shift;
27 ##########
28 # Get all the symbols from the library, match them, and add them to a hash.
30 my %sym_hash = ();
32 # List of objects and archives to process.
33 my @OBJECTS = ();
35 # List of shared objects to omit from processing.
36 my @SHAREDOBJS = ();
38 # Filter out those input archives that have corresponding shared objects to
39 # avoid adding all symbols matched in the archive to the output map.
40 foreach $file (@ARGV) {
41 if (($so = $file) =~ s/\.a$/.so/ && -e $so) {
42 printf STDERR "omitted $file -> $so\n";
43 push (@SHAREDOBJS, $so);
44 } else {
45 push (@OBJECTS, $file);
49 # The nm command to use.
50 my $nm = $ENV{'NM_FOR_TARGET'} || "nm";
52 # Process each symbol.
53 open NM,$nm.' -P '.(join ' ',@OBJECTS).'|' or die $!;
54 while (<NM>) {
55 my $i;
56 chomp;
58 # nm prints out stuff at the start, ignore it.
59 next if (/^$/);
60 next if (/:$/);
61 # Ignore register (SPARC only), undefined and local symbols. The
62 # symbol name is optional; Sun nm emits none for local or .bss symbols.
63 next if (/^([^ ]+)?[ \t]+[RUa-z][ \t]+ /);
64 # Ignore objects without symbol table. Message goes to stdout with Sun
65 # nm, while GNU nm emits the corresponding message to stderr.
66 next if (/.* - No symbol table data/);
68 # $sym is the name of the symbol.
69 die "unknown nm output $_" if (! /^([^ ]+)[ \t]+[A-Z][ \t]+/);
70 my $sym = $1;
72 # Remember symbol.
73 $sym_hash{$sym}++;
75 close NM or die "nm error";
77 ##########
78 # The various types of glob patterns.
80 # A glob pattern that is to be applied to the demangled name: 'cxx'.
81 # A glob patterns that applies directly to the name in the .o files: 'glob'.
82 # This pattern is ignored; used for local variables (usually just '*'): 'ign'.
84 # The type of the current pattern.
85 my $glob = 'glob';
87 # We're currently inside `extern "C++"', which Sun ld doesn't understand.
88 my $in_extern = 0;
90 # We're currently inside a conditional section: just skip it.
91 my $in_ifdef = 0;
93 # The c++filt command to use. This *must* be GNU c++filt; the Sun Studio
94 # c++filt doesn't handle the GNU mangling style.
95 my $cxxfilt = $ENV{'CXXFILT'} || "c++filt";
97 # The current version name.
98 my $current_version = "";
100 # Was there any attempt to match a symbol to this version?
101 my $matches_attempted;
103 # The number of versions which matched this symbol.
104 my $matched_symbols;
106 open F,$symvers or die $!;
108 # Print information about generating this file
109 print "# This file was generated by make_sunver.pl. DO NOT EDIT!\n";
110 print "# It was generated by:\n";
111 printf "# %s %s %s\n", $0, $symvers, (join ' ',@ARGV);
112 printf "# Omitted archives with corresponding shared libraries: %s\n",
113 (join ' ', @SHAREDOBJS) if $#SHAREDOBJS >= 0;
114 print "#\n\n";
116 while (<F>) {
117 # End of skipped section.
118 if (/^[ \t]*\#endif/) {
119 $in_ifdef = 0;
120 next;
123 # Just skip a conditional section.
124 if ($in_ifdef) { next; }
126 # Lines of the form '};'
127 if (/^([ \t]*)(\}[ \t]*;[ \t]*)$/) {
128 $glob = 'glob';
129 if ($in_extern) {
130 $in_extern--;
131 print "$1##$2";
132 } else {
133 print;
135 next;
138 # Lines of the form '} SOME_VERSION_NAME_1.0;'
139 if (/^[ \t]*\}[ \tA-Z0-9_.a-z]+;[ \t]*$/) {
140 $glob = 'glob';
141 # We tried to match symbols agains this version, but none matched.
142 # Emit dummy hidden symbol to avoid marking this version WEAK.
143 if ($matches_attempted && $matched_symbols == 0) {
144 print " hidden:\n";
145 print " .force_WEAK_off_$current_version = DATA S0x0 V0x0;\n";
147 print; next;
150 # Special comments that look like C preprocessor conditionals.
151 # Just skip the contents for now.
152 # FIXME: Allow passing in conditionals from the command line to really
153 # control the skipping.
154 if (/^[ \t]*\#ifdef/) {
155 $in_ifdef = 1;
156 next;
159 # Comment and blank lines
160 if (/^[ \t]*\#/) { print; next; }
161 if (/^[ \t]*$/) { print; next; }
163 # Lines of the form '{'
164 if (/^([ \t]*){$/) {
165 if ($in_extern) {
166 print "$1##{\n";
167 } else {
168 print;
170 next;
173 # Lines of the form 'SOME_VERSION_NAME_1.1 {'
174 if (/^([A-Z0-9_.]+)[ \t]+{$/) {
175 # Record version name.
176 $current_version = $1;
177 # Reset match attempts, #matched symbols for this version.
178 $matches_attempted = 0;
179 $matched_symbols = 0;
180 print;
181 next;
184 # Ignore 'global:'
185 if (/^[ \t]*global:$/) { print; next; }
187 # After 'local:', globs should be ignored, they won't be exported.
188 if (/^[ \t]*local:$/) {
189 $glob = 'ign';
190 print;
191 next;
194 # After 'extern "C++"', globs are C++ patterns
195 if (/^([ \t]*)(extern \"C\+\+\"[ \t]*)$/) {
196 $in_extern++;
197 $glob = 'cxx';
198 # Need to comment, Sun ld cannot handle this.
199 print "$1##$2\n"; next;
202 # Chomp newline now we're done with passing through the input file.
203 chomp;
205 # Catch globs. Note that '{}' is not allowed in globs by this script,
206 # so only '*' and '[]' are available.
207 if (/^([ \t]*)([^ \t;{}#]+);?[ \t]*$/) {
208 my $ws = $1;
209 my $ptn = $2;
210 # Turn the glob into a regex by replacing '*' with '.*'.
211 # Keep $ptn so we can still print the original form.
212 ($pattern = $ptn) =~ s/\*/\.\*/g;
214 if ($glob eq 'ign') {
215 # We're in a local: * section; just continue.
216 print "$_\n";
217 next;
220 # Print the glob commented for human readers.
221 print "$ws##$ptn ($glob)\n";
222 # We tried to match a symbol to this version.
223 $matches_attempted++;
225 if ($glob eq 'glob') {
226 my %ptn_syms = ();
228 # Match ptn against symbols in %sym_hash.
229 foreach my $sym (keys %sym_hash) {
230 # Maybe it matches one of the patterns based on the symbol in
231 # the .o file.
232 $ptn_syms{$sym}++ if ($sym =~ /^$pattern$/);
235 foreach my $sym (sort keys(%ptn_syms)) {
236 $matched_symbols++;
237 print "$ws$sym;\n";
239 } elsif ($glob eq 'cxx') {
240 my %dem_syms = ();
242 # Verify that we're actually using GNU c++filt. Other versions
243 # most likely cannot handle GNU style symbol mangling.
244 my $cxxout = `$cxxfilt --version 2>&1`;
245 $cxxout =~ m/GNU/ or die "$0 requires GNU c++filt to function";
247 # Talk to c++filt through a pair of file descriptors.
248 # Need to start a fresh instance per pattern, otherwise the
249 # process grows to 500+ MB.
250 my $pid = open2(*FILTIN, *FILTOUT, $cxxfilt) or die $!;
252 # Match ptn against symbols in %sym_hash.
253 foreach my $sym (keys %sym_hash) {
254 # No? Well, maybe its demangled form matches one of those
255 # patterns.
256 printf FILTOUT "%s\n",$sym;
257 my $dem = <FILTIN>;
258 chomp $dem;
259 $dem_syms{$sym}++ if ($dem =~ /^$pattern$/);
262 close FILTOUT or die "c++filt error";
263 close FILTIN or die "c++filt error";
264 # Need to wait for the c++filt process to avoid lots of zombies.
265 waitpid $pid, 0;
267 foreach my $sym (sort keys(%dem_syms)) {
268 $matched_symbols++;
269 print "$ws$sym;\n";
271 } else {
272 # No? Well, then ignore it.
274 next;
276 # Important sanity check. This script can't handle lots of formats
277 # that GNU ld can, so be sure to error out if one is seen!
278 die "strange line `$_'";
280 close F;