SymbolFile.pm 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. # Copyright (C) 2007 Raphael Hertzog
  2. # This program is free software; you can redistribute it and/or modify
  3. # it under the terms of the GNU General Public License as published by
  4. # the Free Software Foundation; either version 2 of the License, or
  5. # (at your option) any later version.
  6. # This program is distributed in the hope that it will be useful,
  7. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. # GNU General Public License for more details.
  10. # You should have received a copy of the GNU General Public License along
  11. # with this program; if not, write to the Free Software Foundation, Inc.,
  12. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  13. package Dpkg::Shlibs::SymbolFile;
  14. require 'dpkg-gettext.pl';
  15. use Dpkg::Version qw(vercmp);
  16. sub new {
  17. my $this = shift;
  18. my $file = shift;
  19. my $class = ref($this) || $this;
  20. my $self = { };
  21. bless $self, $class;
  22. if (defined($file) ) {
  23. $self->{file} = $file;
  24. $self->load($file) if -e $file;
  25. }
  26. return $self;
  27. }
  28. sub clear {
  29. my ($self) = @_;
  30. $self->{objects} = {};
  31. }
  32. sub clear_except {
  33. my ($self, @ids) = @_;
  34. my %has;
  35. $has{$_} = 1 foreach (@ids);
  36. foreach my $objid (keys %{$self->{objects}}) {
  37. delete $self->{objects}{$objid} unless exists $has{$objid};
  38. }
  39. }
  40. sub load {
  41. my ($self, $file) = @_;
  42. $self->{file} = $file;
  43. open(SYM_FILE, "<", $file) || main::syserr(sprintf(_g("Can't open %s: %s"), $file));
  44. my ($object);
  45. while (defined($_ = <SYM_FILE>)) {
  46. chomp($_);
  47. if (/^\s+(\S+)\s(\S+)(?:\s(\d+))?/) {
  48. # New symbol
  49. my $sym = {
  50. 'minver' => $2,
  51. 'dep_id' => defined($3) ? $3 : 0,
  52. 'deprecated' => 0
  53. };
  54. $self->{objects}{$object}{syms}{$1} = $sym;
  55. } elsif (/^#DEPRECATED: ([^#]+)#\s*(\S+)\s(\S+)(?:\s(\d+))?/) {
  56. my $sym = {
  57. 'minver' => $3,
  58. 'dep_id' => defined($4) ? $4 : 0,
  59. 'deprecated' => $1
  60. };
  61. $self->{objects}{$object}{syms}{$2} = $sym;
  62. } elsif (/^\|\s*(.*)$/) {
  63. # Alternative dependency template
  64. push @{$self->{objects}{$object}{deps}}, "$1";
  65. } elsif (/^(\S+)\s+(.*)$/) {
  66. # New object and dependency template
  67. $object = $1;
  68. $self->{objects}{$object} = {
  69. 'syms' => {},
  70. 'deps' => [ "$2" ]
  71. };
  72. } else {
  73. main::warning(sprintf(_g("Failed to parse a line in %s: %s"), $file, $_));
  74. }
  75. }
  76. close(SYM_FILE);
  77. }
  78. sub save {
  79. my ($self, $file) = @_;
  80. $file = $self->{file} unless defined($file);
  81. my $fh;
  82. if ($file eq "-") {
  83. $fh = \*STDOUT;
  84. } else {
  85. open(SYM_FILE, "> $file") || main::syserr(sprintf(_g("Can't open %s for writing: %s"), $file, $!));
  86. $fh = \*SYM_FILE;
  87. }
  88. $self->dump($fh);
  89. close($fh) if ($file ne "-");
  90. }
  91. sub dump {
  92. my ($self, $fh) = @_;
  93. foreach my $soname (sort keys %{$self->{objects}}) {
  94. print $fh "$soname $self->{objects}{$soname}{deps}[0]\n";
  95. print $fh "| $_" foreach (@{$self->{objects}{$soname}{deps}}[ 1 .. -1 ]);
  96. foreach my $sym (sort keys %{$self->{objects}{$soname}{syms}}) {
  97. my $info = $self->{objects}{$soname}{syms}{$sym};
  98. print $fh "#DEPRECATED: $info->{deprecated}#" if $info->{deprecated};
  99. print $fh " $sym $info->{minver}";
  100. print $fh " $info->{dep_id}" if $info->{dep_id};
  101. print $fh "\n";
  102. }
  103. }
  104. }
  105. # merge_symbols($object, $minver)
  106. # Needs $Objdump->get_object($soname) as parameter
  107. sub merge_symbols {
  108. my ($self, $object, $minver) = @_;
  109. my $soname = $object->{SONAME} || main::error(_g("Can't merge symbols from objects without SONAME."));
  110. my %dynsyms = map { $_ => $object->{dynsyms}{$_} }
  111. grep { local $a = $object->{dynsyms}{$_}; $a->{dynamic} && $a->{defined} }
  112. keys %{$object->{dynsyms}};
  113. # Scan all symbols provided by the objects
  114. foreach my $sym (keys %dynsyms) {
  115. if (exists $self->{objects}{$soname}{syms}{$sym}) {
  116. # If the symbol is already listed in the file
  117. my $info = $self->{objects}{$soname}{syms}{$sym};
  118. if ($info->{deprecated}) {
  119. # Symbol reappeared somehow
  120. $info->{deprecated} = 0;
  121. $info->{minver} = $minver;
  122. next;
  123. }
  124. # We assume that the right dependency information is already
  125. # there.
  126. if (vercmp($minver, $info->{minver}) < 0) {
  127. $info->{minver} = $minver;
  128. }
  129. } else {
  130. # The symbol is new and not present in the file
  131. my $info = {
  132. 'minver' => $minver,
  133. 'deprecated' => 0,
  134. 'dep_id' => 0
  135. };
  136. $self->{objects}{$soname}{syms}{$sym} = $info;
  137. }
  138. }
  139. # Scan all symbols in the file and mark as deprecated those that are
  140. # no more provided
  141. foreach my $sym (keys %{$self->{objects}{$soname}{syms}}) {
  142. if (! exists $dynsyms{$sym}) {
  143. $self->{objects}{$soname}{syms}{$sym}{deprecated} = $minver;
  144. }
  145. }
  146. }
  147. sub has_object {
  148. my ($self, $soname) = @_;
  149. return exists $self->{objects}{$soname};
  150. }
  151. sub create_object {
  152. my ($self, $soname, @deps) = @_;
  153. $self->{objects}{$soname} = {
  154. "syms" => {},
  155. "deps" => [ @deps ]
  156. };
  157. }
  158. sub get_dependency {
  159. my ($self, $soname, $dep_id) = @_;
  160. $dep_id = 0 unless defined($dep_id);
  161. return $self->{objects}{$soname}{deps}[$dep_id];
  162. }
  163. sub lookup_symbol {
  164. my ($self, $name, $sonames) = @_;
  165. foreach my $so (@{$sonames}) {
  166. next if (! exists $self->{objects}{$so});
  167. if (exists $self->{objects}{$so}{syms}{$name} and
  168. not $self->{objects}{$so}{syms}{$name}{deprecated})
  169. {
  170. my $dep_id = $self->{objects}{$so}{syms}{$name}{dep_id};
  171. return {
  172. 'depends' => $self->{objects}{$so}{deps}[$dep_id],
  173. 'soname' => $so,
  174. %{$self->{objects}{$so}{syms}{$name}}
  175. };
  176. }
  177. }
  178. return undef;
  179. }
  180. sub has_lost_symbols {
  181. my ($self, $ref) = @_;
  182. foreach my $soname (keys %{$self->{objects}}) {
  183. my $mysyms = $self->{objects}{$soname}{syms};
  184. next if not exists $ref->{objects}{$soname};
  185. my $refsyms = $ref->{objects}{$soname}{syms};
  186. foreach my $sym (grep { not $refsyms->{$_}{deprecated} }
  187. keys %{$refsyms})
  188. {
  189. if ((not exists $mysyms->{$sym}) or
  190. $mysyms->{$sym}{deprecated})
  191. {
  192. return 1;
  193. }
  194. }
  195. }
  196. return 0;
  197. }
  198. sub has_new_symbols {
  199. my ($self, $ref) = @_;
  200. foreach my $soname (keys %{$self->{objects}}) {
  201. my $mysyms = $self->{objects}{$soname}{syms};
  202. next if not exists $ref->{objects}{$soname};
  203. my $refsyms = $ref->{objects}{$soname}{syms};
  204. foreach my $sym (grep { not $mysyms->{$_}{deprecated} }
  205. keys %{$mysyms})
  206. {
  207. if ((not exists $refsyms->{$sym}) or
  208. $refsyms->{$sym}{deprecated})
  209. {
  210. return 1;
  211. }
  212. }
  213. }
  214. return 0;
  215. }
  216. sub has_new_libs {
  217. my ($self, $ref) = @_;
  218. foreach my $soname (keys %{$self->{objects}}) {
  219. return 1 if not exists $ref->{objects}{$soname};
  220. }
  221. return 0;
  222. }
  223. sub has_lost_libs {
  224. my ($self, $ref) = @_;
  225. foreach my $soname (keys %{$ref->{objects}}) {
  226. return 1 if not exists $self->{objects}{$soname};
  227. }
  228. return 0;
  229. }
  230. 1;