mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-25 03:55:32 +08:00
c438ab79bf
GCC does not export construction vtable symbols from shared libraries. The symbols are marked hidden in the objects; for Darwin that makes them also external (“private_extern” is Darwin’s hidden) which means that they show up in the list of possible symbols for export from libstdc++, and there are sufficiently relaxed match conditions that they reach the exports list. When Darwin’s static linker encounters them it generates a warning that they cannot be exported. This patch prunes them from the list of symbols to be considered, thus eliminating the warnings. No functional Change inended to the library exports. 2018-12-06 Iain Sandoe <iain@sandoe.co.uk> * scripts/make_exports.pl (check names): Don’t try to export construction vtable symbols. From-SVN: r266864
153 lines
4.4 KiB
Perl
153 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 '[]' are available.
|
|
if (/^[ \t]*([^ \t;{}#]+);?[ \t]*$/) {
|
|
my $ptn = $1;
|
|
# Turn the glob into a regex by 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;
|
|
}
|