extract_symvers.pl 4.2 KB

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