mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-19 00:55:13 +08:00
7bf710b511
The scripts/make_exports.pl script used for darwin only replaces '*' wildcards in globs, it doesn't handle '?'. This means the recent changes to std::__timepunct exports broke darwin. Rather than use mangled names in the linker script, this adds support for '?' to the perl script. This also removes some unnecessary escaping of the replacement strings in s// substitutions. libstdc++-v3/ChangeLog: * scripts/make_exports.pl: Replace '?' with '.' when turning a glob into a regex.
155 lines
4.4 KiB
Perl
155 lines
4.4 KiB
Perl
#!/usr/bin/perl -w
|
|
|
|
# This script takes two arguments, a version script and a dynamic library
|
|
# (in that order), and prints a list of symbols to be exported from the
|
|
# library.
|
|
# It expects a 'nm' with the POSIX '-P' option, but everyone has one of
|
|
# those, right? It also expects that symbol names have a leading underscore,
|
|
# which is somewhat less likely.
|
|
|
|
use File::Glob ':glob';
|
|
use FileHandle;
|
|
use IPC::Open2;
|
|
|
|
# The glob patterns that are to be applied to the demangled name
|
|
my @cxx_globs = ();
|
|
# The glob patterns that apply directly to the name in the .o files
|
|
my @globs = ();
|
|
# The patterns for local variables (usually just '*').
|
|
my @ignored = ();
|
|
|
|
##########
|
|
# Fill in the various glob arrays.
|
|
|
|
# The next pattern will go into this array.
|
|
my $glob = \@globs;
|
|
my $symvers = shift;
|
|
|
|
open F,$symvers or die $!;
|
|
|
|
while (<F>) {
|
|
chomp;
|
|
# Lines of the form '} SOME_VERSION_NAME_1.0;'
|
|
if (/^[ \t]*\}[ \tA-Z0-9_.a-z]*;[ \t]*$/) {
|
|
$glob = \@globs;
|
|
next;
|
|
}
|
|
# Comment and blank lines
|
|
next if (/^[ \t]*\#/);
|
|
next if (/^[ \t]*$/);
|
|
# Lines of the form 'SOME_VERSION_NAME_1.1 {'
|
|
next if (/^[A-Z0-9_. \t]*{$/);
|
|
# Ignore 'global:'
|
|
next if (/^[ \t]*global:$/);
|
|
# After 'local:', globs should be ignored, they won't be exported.
|
|
if (/^[ \t]*local:$/) {
|
|
$glob = \@ignored;
|
|
next;
|
|
}
|
|
# After 'extern "C++"', globs are C++ patterns
|
|
if (/^[ \t]*extern \"C\+\+\"[ \t]*$/) {
|
|
$glob = \@cxx_globs;
|
|
next;
|
|
}
|
|
# Catch globs. Note that '{}' is not allowed in globs by this script,
|
|
# so only '*' and '?' and '[]' are available.
|
|
if (/^[ \t]*([^ \t;{}#]+);?[ \t]*$/) {
|
|
my $ptn = $1;
|
|
# Turn the glob into a regex by replacing '*' with '.*'.
|
|
$ptn =~ s/\*/.*/g;
|
|
# And replacing '?' with '.'.
|
|
$ptn =~ s/\?/./g;
|
|
push @$glob,$ptn;
|
|
next;
|
|
}
|
|
# Important sanity check. This script can't handle lots of formats
|
|
# that GNU ld can, so be sure to error out if one is seen!
|
|
die "strange line `$_'";
|
|
}
|
|
close F;
|
|
|
|
# Make 'if (1)' for debugging.
|
|
if (0) {
|
|
print "cxx:\n";
|
|
(printf "%s\n",$_) foreach (@cxx_globs);
|
|
print "globs:\n";
|
|
(printf "%s\n", $_) foreach (@globs);
|
|
print "ignored:\n";
|
|
(printf "%s\n", $_) foreach (@ignored);
|
|
}
|
|
|
|
##########
|
|
# Combine the arrays into single regular expressions
|
|
# This cuts the time required from about 30 seconds to about 0.5 seconds.
|
|
|
|
my $glob_regex = '^_(' . (join '|',@globs) . ')$';
|
|
my $cxx_regex = (join '|',@cxx_globs);
|
|
|
|
##########
|
|
# Get all the symbols from the library, match them, and add them to a hash.
|
|
|
|
my %export_hash = ();
|
|
my $nm = $ENV{'NM_FOR_TARGET'} || "nm";
|
|
# Process each symbol.
|
|
print STDERR $nm.' -P '.(join ' ',@ARGV).'|';
|
|
open NM,$nm.' -P '.(join ' ',@ARGV).'|' or die $!;
|
|
# Talk to c++filt through a pair of file descriptors.
|
|
open2(*FILTIN, *FILTOUT, "c++filt -_") or die $!;
|
|
NAME: while (<NM>) {
|
|
my $i;
|
|
chomp;
|
|
|
|
# nm prints out stuff at the start, ignore it.
|
|
next if (/^$/);
|
|
next if (/:$/);
|
|
# Ignore undefined and local symbols.
|
|
next if (/^([^ ]+) [Ua-z] /);
|
|
|
|
# GCC does not export construction vtables from shared libraries.
|
|
# However the symbols are marked hidden, for Darwin that makes them
|
|
# also external "private_extern", which means that they show up in
|
|
# this list. When ld64 encounters them it generates a warning that
|
|
# they cannot be exported, so trim them from the set now.
|
|
next if (/^construction vtable.*$/);
|
|
next if (/^__ZTC.*$/);
|
|
|
|
# $sym is the name of the symbol, $noeh_sym is the same thing with
|
|
# any '.eh' suffix removed.
|
|
die "unknown nm output $_" if (! /^([^ ]+) [A-Z] /);
|
|
my $sym = $1;
|
|
my $noeh_sym = $sym;
|
|
$noeh_sym =~ s/\.eh$//;
|
|
|
|
# Maybe it matches one of the patterns based on the symbol in the .o file.
|
|
if ($noeh_sym =~ /$glob_regex/) {
|
|
$export_hash{$sym} = 1;
|
|
next NAME;
|
|
}
|
|
|
|
# No? Well, maybe its demangled form matches one of those patterns.
|
|
printf FILTOUT "%s\n",$noeh_sym;
|
|
my $dem = <FILTIN>;
|
|
chomp $dem;
|
|
if ($dem =~ /$cxx_regex/) {
|
|
$export_hash{$sym} = 2;
|
|
next NAME;
|
|
}
|
|
|
|
# No? Well, then ignore it.
|
|
}
|
|
close NM or die "nm error";
|
|
close FILTOUT or die "c++filt error";
|
|
close FILTIN or die "c++filt error";
|
|
|
|
##########
|
|
# Print out the export file
|
|
|
|
# Print information about generating this file
|
|
print "# This is a generated file.\n";
|
|
print "# It was generated by:\n";
|
|
printf "# %s %s %s\n", $0, $symvers, (join ' ',@ARGV);
|
|
|
|
foreach my $i (keys %export_hash) {
|
|
printf "%s\n",$i or die;
|
|
}
|