1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
#!/usr/bin/perl -w
# Copyright (C) 2010-2015 Free Software Foundation, Inc.
#
# This file is part of the GNU ISO C++ Library. This library is free
# software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this library; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# Extract symbol version information on Solaris 2.
#
# Sun ld doesn't record symbol versions in .dynsym entries and they cannot
# easily be extracted from readelf --versions output, so use pvs instead.
# This way, we don't require GNU binutils in the native case. Also ensures
# that baseline_symbols.txt is identical between native (pvs, elfdump) and
# cross (readelf) cases.
my $lib = shift;
open PVS, "pvs -dsvo $lib |" or die $!;
while (<PVS>) {
chomp;
# Remove trailing semicolon.
s/;$//;
# shared object, dash, version, symbol, [size]
(undef, undef, $version, $symbol, $size) = split;
# Remove colon separator from version field.
$version =~ s/:$//;
# Record base version. The [BASE] field was only added in Solaris 11,
# so simply use the first record instead.
if ($. == 1) {
$basever = $version;
next;
}
# Skip version declarations.
next unless defined ($symbol);
# Ignore version dependencies.
next if ($symbol =~ /\{.*\}/);
# Emit objects.
if (defined ($size)) {
# Strip parens from object size.
$size =~ s/\((\d+)\)/$1/;
$type{$symbol} = "OBJECT";
$version{$symbol} = $version;
$size{$symbol} = $size;
next;
}
if ($version eq $symbol or $version eq $basever) {
# Emit versions or symbols bound to base versions as objects.
$type{$symbol} = "OBJECT";
if ($version eq $basever) {
$version{$symbol} = $version;
} else {
$version{$symbol} = $symbol;
}
$size{$symbol} = 0;
} else {
# Everything else without a size field is a function.
$type{$symbol} = "FUNC";
$version{$symbol} = $version;
}
}
close PVS or die "pvs error";
# Only look at .dynsym table, like readelf in extract_symvers.
# Ignore error output to avoid getting confused by
# .gnu.version_r: zero sh_entsize information, expected 0x1
# warning with Solaris 11 elfdump on gld-produced shared objects.
open ELFDUMP, "/usr/ccs/bin/elfdump -s -N .dynsym $lib 2>/dev/null |" or die $!;
while (<ELFDUMP>) {
chomp;
# Ignore empty lines.
next if (/^$/);
# Ignore object name header.
next if (/:$/);
# Ignore table header lines.
next if (/^Symbol Table Section:/);
next if (/index.*value.*size/);
# Split table.
(undef, undef, undef, $type, $bind, $oth, undef, $shndx, $name) = split;
# Error out for unknown input.
die "unknown input line:\n$_" unless defined($bind);
# Ignore local symbols.
next if ($bind eq "LOCL");
# Ignore hidden symbols.
next if ($oth eq "H");
# Ignore undefined symbols.
next if ($shndx eq "UNDEF");
# Error out for unhandled cases. _GLOBAL_OFFSET_TABLE_ is P (protected).
die "unhandled symbol:\n$_" if ($bind !~ /^(GLOB|WEAK)/ or $oth !~ /[DP]/);
# Adapt to readelf type naming convention.
$type = "NOTYPE" if ($type eq "NOTY");
$type = "OBJECT" if ($type eq "OBJT");
# Use correct symbol type.
$type{$name} = $type if ($type{$name} ne $type);
}
close ELFDUMP or die "elfdump error";
foreach $symbol (keys %type) {
if ($type{$symbol} eq "FUNC" || $type{$symbol} eq "NOTYPE") {
push @lines, "$type{$symbol}:$symbol\@\@$version{$symbol}\n";
} elsif ($type{$symbol} eq "OBJECT" and $size{$symbol} == 0) {
# Omit symbols bound to base version; details can differ depending
# on the toolchain used.
next if $version{$symbol} eq $basever;
push @lines, "$type{$symbol}:$size{$symbol}:$version{$symbol}\n";
} else {
push @lines, "$type{$symbol}:$size{$symbol}:$symbol\@\@$version{$symbol}\n";
}
}
print sort @lines;
|