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