SymbolFile.pm 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. # Copyright © 2007 Raphaël Hertzog <hertzog@debian.org>
  2. # Copyright © 2009 Modestas Vainius <modestas@vainius.eu>
  3. #
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. package Dpkg::Shlibs::SymbolFile;
  17. use strict;
  18. use warnings;
  19. use Dpkg::Gettext;
  20. use Dpkg::ErrorHandling;
  21. use Dpkg::Version;
  22. use Dpkg::Control::Fields;
  23. use Dpkg::Shlibs::Symbol;
  24. use Dpkg::Arch qw(get_host_arch);
  25. # Supported alias types in the order of matching preference
  26. # See: find_matching_pattern().
  27. use constant 'ALIAS_TYPES' => qw(c++ wildcard);
  28. my %blacklist = (
  29. '__bss_end__' => 1, # arm
  30. '__bss_end' => 1, # arm
  31. '_bss_end__' => 1, # arm
  32. '__bss_start' => 1, # ALL
  33. '__bss_start__' => 1, # arm
  34. '__data_start' => 1, # arm
  35. '__do_global_ctors_aux' => 1, # ia64
  36. '__do_global_dtors_aux' => 1, # ia64
  37. '__do_jv_register_classes' => 1,# ia64
  38. '_DYNAMIC' => 1, # ALL
  39. '_edata' => 1, # ALL
  40. '_end' => 1, # ALL
  41. '__end__' => 1, # arm
  42. '__exidx_end' => 1, # armel
  43. '__exidx_start' => 1, # armel
  44. '_fbss' => 1, # mips, mipsel
  45. '_fdata' => 1, # mips, mipsel
  46. '_fini' => 1, # ALL
  47. '_ftext' => 1, # mips, mipsel
  48. '_GLOBAL_OFFSET_TABLE_' => 1, # hppa, mips, mipsel
  49. '__gmon_start__' => 1, # hppa
  50. '__gnu_local_gp' => 1, # mips, mipsel
  51. '_gp' => 1, # mips, mipsel
  52. '_init' => 1, # ALL
  53. '_PROCEDURE_LINKAGE_TABLE_' => 1, # sparc, alpha
  54. '_SDA2_BASE_' => 1, # powerpc
  55. '_SDA_BASE_' => 1, # powerpc
  56. );
  57. for (my $i = 14; $i <= 31; $i++) {
  58. # Many powerpc specific symbols
  59. $blacklist{"_restfpr_$i"} = 1;
  60. $blacklist{"_restfpr_$i\_x"} = 1;
  61. $blacklist{"_restgpr_$i"} = 1;
  62. $blacklist{"_restgpr_$i\_x"} = 1;
  63. $blacklist{"_savefpr_$i"} = 1;
  64. $blacklist{"_savegpr_$i"} = 1;
  65. }
  66. # Many armel-specific symbols
  67. $blacklist{"__aeabi_$_"} = 1 foreach (qw(cdcmpeq cdcmple cdrcmple cfcmpeq
  68. cfcmple cfrcmple d2f d2iz d2lz d2uiz d2ulz dadd dcmpeq dcmpge dcmpgt
  69. dcmple dcmplt dcmpun ddiv dmul dneg drsub dsub f2d f2iz f2lz f2uiz f2ulz
  70. fadd fcmpeq fcmpge fcmpgt fcmple fcmplt fcmpun fdiv fmul fneg frsub fsub
  71. i2d i2f idiv idivmod l2d l2f lasr lcmp ldivmod llsl llsr lmul ui2d ui2f
  72. uidiv uidivmod ul2d ul2f ulcmp uldivmod unwind_cpp_pr0 unwind_cpp_pr1
  73. unwind_cpp_pr2 uread4 uread8 uwrite4 uwrite8));
  74. sub new {
  75. my $this = shift;
  76. my %opts=@_;
  77. my $class = ref($this) || $this;
  78. my $self = \%opts;
  79. bless $self, $class;
  80. $self->{arch} = get_host_arch() unless exists $self->{arch};
  81. $self->clear();
  82. if (exists $self->{file}) {
  83. $self->load($self->{file}) if -e $self->{file};
  84. }
  85. return $self;
  86. }
  87. sub clear {
  88. my ($self) = @_;
  89. $self->{objects} = {};
  90. $self->{used_wildcards} = 0;
  91. }
  92. sub clear_except {
  93. my ($self, @ids) = @_;
  94. my %has;
  95. $has{$_} = 1 foreach (@ids);
  96. foreach my $objid (keys %{$self->{objects}}) {
  97. delete $self->{objects}{$objid} unless exists $has{$objid};
  98. }
  99. }
  100. sub add_symbol {
  101. my ($self, $soname, $symbol) = @_;
  102. my $object = (ref $soname) ? $soname : $self->{objects}{$soname};
  103. if ($symbol->is_pattern()) {
  104. if (my $alias_type = $symbol->get_alias_type()) {
  105. unless (exists $object->{patterns}{aliases}{$alias_type}) {
  106. $object->{patterns}{aliases}{$alias_type} = {};
  107. }
  108. my $aliases = $object->{patterns}{aliases}{$alias_type};
  109. # A converter object for transforming a raw symbol name to alias
  110. # of this type. Must support convert_to_alias() method.
  111. unless (exists $aliases->{converter}) {
  112. $aliases->{converter} = $symbol;
  113. }
  114. # Alias hash for matching.
  115. $aliases->{names}{$symbol->get_symbolname()} = $symbol;
  116. } else {
  117. # Otherwise assume this is a generic sequential pattern. This
  118. # should be always safe.
  119. push @{$object->{patterns}{generic}}, $symbol;
  120. }
  121. return 'pattern';
  122. } else {
  123. # invalidate the minimum version cache
  124. $object->{minver_cache} = [];
  125. $object->{syms}{$symbol->get_symbolname()} = $symbol;
  126. return 'sym';
  127. }
  128. }
  129. # Parameter seen is only used for recursive calls
  130. sub load {
  131. my ($self, $file, $seen, $obj_ref, $base_symbol) = @_;
  132. sub new_symbol {
  133. my $base = shift || 'Dpkg::Shlibs::Symbol';
  134. return (ref $base) ? $base->dclone(@_) : $base->new(@_);
  135. }
  136. if (defined($seen)) {
  137. return if exists $seen->{$file}; # Avoid include loops
  138. } else {
  139. $self->{file} = $file;
  140. $seen = {};
  141. }
  142. $seen->{$file} = 1;
  143. if (not ref($obj_ref)) { # Init ref to name of current object/lib
  144. $$obj_ref = undef;
  145. }
  146. open(my $sym_file, "<", $file)
  147. || syserr(_g("cannot open %s"), $file);
  148. while (defined($_ = <$sym_file>)) {
  149. chomp($_);
  150. if (/^(?:\s+|#(?:DEPRECATED|MISSING): ([^#]+)#\s*)(.*)/) {
  151. if (not defined ($$obj_ref)) {
  152. error(_g("Symbol information must be preceded by a header (file %s, line %s)."), $file, $.);
  153. }
  154. # Symbol specification
  155. my $deprecated = ($1) ? $1 : 0;
  156. my $sym = new_symbol($base_symbol, deprecated => $deprecated);
  157. if ($sym->parse($2)) {
  158. $sym->initialize(arch => $self->{arch});
  159. $self->add_symbol($$obj_ref, $sym);
  160. } else {
  161. warning(_g("Failed to parse line in %s: %s"), $file, $_);
  162. }
  163. } elsif (/^(\(.*\))?#include\s+"([^"]+)"/) {
  164. my $tagspec = $1;
  165. my $filename = $2;
  166. my $dir = $file;
  167. my $new_base_symbol;
  168. if (defined $tagspec) {
  169. $new_base_symbol = new_symbol($base_symbol);
  170. $new_base_symbol->parse_tagspec($tagspec);
  171. }
  172. $dir =~ s{[^/]+$}{}; # Strip filename
  173. $self->load("$dir$filename", $seen, $obj_ref, $new_base_symbol);
  174. } elsif (/^#/) {
  175. # Skip possible comments
  176. } elsif (/^\|\s*(.*)$/) {
  177. # Alternative dependency template
  178. push @{$self->{objects}{$$obj_ref}{deps}}, "$1";
  179. } elsif (/^\*\s*([^:]+):\s*(.*\S)\s*$/) {
  180. # Add meta-fields
  181. $self->{objects}{$$obj_ref}{fields}{field_capitalize($1)} = $2;
  182. } elsif (/^(\S+)\s+(.*)$/) {
  183. # New object and dependency template
  184. $$obj_ref = $1;
  185. if (exists $self->{objects}{$$obj_ref}) {
  186. # Update/override infos only
  187. $self->{objects}{$$obj_ref}{deps} = [ "$2" ];
  188. } else {
  189. # Create a new object
  190. $self->create_object($$obj_ref, "$2");
  191. }
  192. } else {
  193. warning(_g("Failed to parse a line in %s: %s"), $file, $_);
  194. }
  195. }
  196. close($sym_file);
  197. delete $seen->{$file};
  198. }
  199. # Beware: we reuse the data structure of the provided symfile so make
  200. # sure to not modify them after having called this function
  201. sub merge_object_from_symfile {
  202. my ($self, $src, $objid) = @_;
  203. if (not $self->has_object($objid)) {
  204. $self->{objects}{$objid} = $src->{objects}{$objid};
  205. } else {
  206. warning(_g("Tried to merge the same object (%s) twice in a symfile."), $objid);
  207. }
  208. }
  209. sub save {
  210. my ($self, $file, %opts) = @_;
  211. $file = $self->{file} unless defined($file);
  212. my $fh;
  213. if ($file eq "-") {
  214. $fh = \*STDOUT;
  215. } else {
  216. open($fh, ">", $file)
  217. || syserr(_g("cannot write %s"), $file);
  218. }
  219. $self->dump($fh, %opts);
  220. close($fh) if ($file ne "-");
  221. }
  222. sub dump {
  223. my ($self, $fh, %opts) = @_;
  224. $opts{template_mode} = 0 unless exists $opts{template_mode};
  225. $opts{with_deprecated} = 1 unless exists $opts{with_deprecated};
  226. $opts{with_pattern_matches} = 0 unless exists $opts{with_pattern_matches};
  227. foreach my $soname (sort keys %{$self->{objects}}) {
  228. my @deps = @{$self->{objects}{$soname}{deps}};
  229. my $dep = shift @deps;
  230. $dep =~ s/#PACKAGE#/$opts{package}/g if exists $opts{package};
  231. print $fh "$soname $dep\n";
  232. foreach $dep (@deps) {
  233. $dep =~ s/#PACKAGE#/$opts{package}/g if exists $opts{package};
  234. print $fh "| $dep\n";
  235. }
  236. my $f = $self->{objects}{$soname}{fields};
  237. foreach my $field (sort keys %{$f}) {
  238. my $value = $f->{$field};
  239. $value =~ s/#PACKAGE#/$opts{package}/g if exists $opts{package};
  240. print $fh "* $field: $value\n";
  241. }
  242. my $syms = $self->{objects}{$soname}{syms};
  243. my @symbols;
  244. if ($opts{template_mode}) {
  245. # Exclude symbols matching a pattern, but include patterns themselves
  246. @symbols = grep { not $_->get_pattern() } values %$syms;
  247. push @symbols, $self->get_soname_patterns($soname);
  248. } else {
  249. @symbols = values %$syms;
  250. }
  251. foreach my $sym (sort { $a->get_symboltempl() cmp
  252. $b->get_symboltempl() } @symbols) {
  253. next if $sym->{deprecated} and not $opts{with_deprecated};
  254. # Do not dump symbols from foreign arch unless dumping a template.
  255. next if not $opts{template_mode} and
  256. not $sym->arch_is_concerned($self->{arch});
  257. # Dump symbol specification. Dump symbol tags only in template mode.
  258. print $fh $sym->get_symbolspec($opts{template_mode}), "\n";
  259. # Dump pattern matches as comments (if requested)
  260. if ($opts{with_pattern_matches} && $sym->is_pattern()) {
  261. for my $match (sort { $a->get_symboltempl() cmp
  262. $b->get_symboltempl() } $sym->get_pattern_matches())
  263. {
  264. print $fh "#MATCH:", $match->get_symbolspec(0), "\n";
  265. }
  266. }
  267. }
  268. }
  269. }
  270. # Tries to match a symbol name and/or version against the patterns defined.
  271. # Returns a pattern which matches (if any).
  272. sub find_matching_pattern {
  273. my ($self, $name, $sonames, $inc_deprecated) = @_;
  274. $inc_deprecated = 0 unless defined $inc_deprecated;
  275. my $pattern_ok = sub {
  276. my $p = shift;
  277. return defined $p && ($inc_deprecated || !$p->{deprecated}) &&
  278. $p->arch_is_concerned($self->{arch});
  279. };
  280. foreach my $soname (@$sonames) {
  281. my $obj = (ref $soname) ? $soname : $self->{objects}{$soname};
  282. my ($type, $pattern);
  283. next unless defined $obj;
  284. my $all_aliases = $obj->{patterns}{aliases};
  285. for my $type (ALIAS_TYPES) {
  286. if (exists $all_aliases->{$type}) {
  287. my $aliases = $all_aliases->{$type};
  288. if (my $alias = $aliases->{converter}->convert_to_alias($name)) {
  289. if ($alias && exists $aliases->{names}{$alias}) {
  290. $pattern = $aliases->{names}{$alias};
  291. last if &$pattern_ok($pattern);
  292. $pattern = undef; # otherwise not found yet
  293. }
  294. }
  295. }
  296. }
  297. # Now try generic patterns and use the first that matches
  298. if (not defined $pattern) {
  299. for my $p (@{$obj->{patterns}{generic}}) {
  300. if (&$pattern_ok($p) && $p->matches_rawname($name)) {
  301. $pattern = $p;
  302. last;
  303. }
  304. }
  305. }
  306. if (defined $pattern) {
  307. return $pattern;
  308. }
  309. }
  310. return undef;
  311. }
  312. # merge_symbols($object, $minver)
  313. # Needs $Objdump->get_object($soname) as parameter
  314. # Don't merge blacklisted symbols related to the internal (arch-specific)
  315. # machinery
  316. sub merge_symbols {
  317. my ($self, $object, $minver) = @_;
  318. my $soname = $object->{SONAME} || error(_g("Can't merge symbols from objects without SONAME."));
  319. my %dynsyms;
  320. foreach my $sym ($object->get_exported_dynamic_symbols()) {
  321. my $name = $sym->{name} . '@' .
  322. ($sym->{version} ? $sym->{version} : "Base");
  323. my $symobj = $self->lookup_symbol($name, [ $soname ]);
  324. if (exists $blacklist{$sym->{name}}) {
  325. next unless (defined $symobj and $symobj->has_tag("ignore-blacklist"));
  326. }
  327. $dynsyms{$name} = $sym;
  328. }
  329. unless (exists $self->{objects}{$soname}) {
  330. $self->create_object($soname, '');
  331. }
  332. # Scan all symbols provided by the objects
  333. my $obj = $self->{objects}{$soname};
  334. my @obj = ( $obj );
  335. # invalidate the minimum version cache - it is not sufficient to
  336. # invalidate in add_symbol, since we might change a minimum
  337. # version for a particular symbol without adding it
  338. $obj->{minver_cache} = [];
  339. foreach my $name (keys %dynsyms) {
  340. my $sym;
  341. if (exists $obj->{syms}{$name}) {
  342. # If the symbol is already listed in the file
  343. $sym = $obj->{syms}{$name};
  344. $sym->mark_found_in_library($minver, $self->{arch});
  345. } else {
  346. # The exact symbol is not present in the file, but it might match a
  347. # pattern.
  348. my $symobj = $dynsyms{$name};
  349. my $pattern = $self->find_matching_pattern($name, \@obj, 1);
  350. if (defined $pattern) {
  351. $pattern->mark_found_in_library($minver, $self->{arch});
  352. $sym = $pattern->create_pattern_match(symbol => $name);
  353. } else {
  354. # Symbol without any special info as no pattern matched
  355. $sym = Dpkg::Shlibs::Symbol->new(symbol => $name,
  356. minver => $minver);
  357. }
  358. $self->add_symbol($obj, $sym);
  359. }
  360. }
  361. # Process all symbols which could not be found in the library.
  362. foreach my $name (keys %{$self->{objects}{$soname}{syms}}) {
  363. if (not exists $dynsyms{$name}) {
  364. my $sym = $self->{objects}{$soname}{syms}{$name};
  365. $sym->mark_not_found_in_library($minver, $self->{arch});
  366. }
  367. }
  368. # Deprecate patterns which didn't match anything
  369. for my $pattern (grep { $_->get_pattern_matches() == 0 }
  370. $self->get_soname_patterns($soname)) {
  371. $pattern->mark_not_found_in_library($minver, $self->{arch});
  372. }
  373. }
  374. sub is_empty {
  375. my ($self) = @_;
  376. return scalar(keys %{$self->{objects}}) ? 0 : 1;
  377. }
  378. sub has_object {
  379. my ($self, $soname) = @_;
  380. return exists $self->{objects}{$soname};
  381. }
  382. sub create_object {
  383. my ($self, $soname, @deps) = @_;
  384. $self->{objects}{$soname} = {
  385. syms => {},
  386. fields => {},
  387. wildcards => {},
  388. patterns => {
  389. aliases => {},
  390. generic => [],
  391. },
  392. deps => [ @deps ],
  393. minver_cache => []
  394. };
  395. }
  396. sub get_dependency {
  397. my ($self, $soname, $dep_id) = @_;
  398. $dep_id = 0 unless defined($dep_id);
  399. return $self->{objects}{$soname}{deps}[$dep_id];
  400. }
  401. sub get_smallest_version {
  402. my ($self, $soname, $dep_id) = @_;
  403. $dep_id = 0 unless defined($dep_id);
  404. my $so_object = $self->{objects}{$soname};
  405. return $so_object->{minver_cache}[$dep_id] if(defined($so_object->{minver_cache}[$dep_id]));
  406. my $minver;
  407. foreach my $sym (values %{$so_object->{syms}}) {
  408. next if $dep_id != $sym->{dep_id};
  409. $minver = $sym->{minver} unless defined($minver);
  410. if (version_compare($minver, $sym->{minver}) > 0) {
  411. $minver = $sym->{minver};
  412. }
  413. }
  414. $so_object->{minver_cache}[$dep_id] = $minver;
  415. return $minver;
  416. }
  417. sub get_dependencies {
  418. my ($self, $soname) = @_;
  419. return @{$self->{objects}{$soname}{deps}};
  420. }
  421. sub get_field {
  422. my ($self, $soname, $name) = @_;
  423. if (exists $self->{objects}{$soname}{fields}{$name}) {
  424. return $self->{objects}{$soname}{fields}{$name};
  425. }
  426. return undef;
  427. }
  428. sub contains_wildcards {
  429. my ($self) = @_;
  430. my $res = 0;
  431. foreach my $soname (sort keys %{$self->{objects}}) {
  432. if (scalar keys %{$self->{objects}{$soname}{wildcards}}) {
  433. $res = 1;
  434. }
  435. }
  436. return $res;
  437. }
  438. sub used_wildcards {
  439. my ($self) = @_;
  440. return $self->{used_wildcards};
  441. }
  442. sub lookup_symbol {
  443. my ($self, $name, $sonames, $inc_deprecated) = @_;
  444. $inc_deprecated = 0 unless defined($inc_deprecated);
  445. foreach my $so (@{$sonames}) {
  446. next if (! exists $self->{objects}{$so});
  447. if (exists $self->{objects}{$so}{syms}{$name} and
  448. ($inc_deprecated or not
  449. $self->{objects}{$so}{syms}{$name}{deprecated}))
  450. {
  451. my $dep_id = $self->{objects}{$so}{syms}{$name}{dep_id};
  452. my $clone = $self->{objects}{$so}{syms}{$name}->sclone();
  453. $clone->{depends} = $self->{objects}{$so}{deps}[$dep_id];
  454. $clone->{soname} = $so;
  455. return $clone;
  456. }
  457. }
  458. return undef;
  459. }
  460. # Tries to find a pattern like the $refpat and returns it. If not found, undef
  461. # is returned.
  462. sub lookup_pattern {
  463. my ($self, $refpat, $sonames, $inc_deprecated) = @_;
  464. $inc_deprecated = 0 unless defined($inc_deprecated);
  465. foreach my $soname (@$sonames) {
  466. my $object = (ref $soname) ? $soname : $self->{objects}{$soname};
  467. my $pat;
  468. next unless defined $object;
  469. if (my $type = $refpat->get_alias_type()) {
  470. $pat = $object->{patterns}{aliases}{$type}{names}{$refpat->get_symbolname()};
  471. } elsif ($refpat->get_pattern_type() eq "generic") {
  472. for my $p (@{$object->{patterns}{generic}}) {
  473. if (($inc_deprecated || !$p->{deprecated}) &&
  474. $p->equals($refpat))
  475. {
  476. $pat = $p;
  477. last;
  478. }
  479. }
  480. }
  481. if ($pat && ($inc_deprecated || !$pat->{deprecated})) {
  482. return $pat;
  483. }
  484. }
  485. return undef;
  486. }
  487. # Collects all patterns of the given soname and returns them as an array.
  488. sub get_soname_patterns {
  489. my ($self, $soname) = @_;
  490. my $object = (ref $soname) ? $soname : $self->{objects}{$soname};
  491. my @aliases;
  492. foreach my $alias (values %{$object->{patterns}{aliases}}) {
  493. push @aliases, values %{$alias->{names}};
  494. }
  495. return (@aliases, @{$object->{patterns}{generic}});
  496. }
  497. sub get_new_symbols {
  498. my ($self, $ref) = @_;
  499. my @res;
  500. foreach my $soname (keys %{$self->{objects}}) {
  501. my $mysyms = $self->{objects}{$soname}{syms};
  502. next if not exists $ref->{objects}{$soname};
  503. my $refsyms = $ref->{objects}{$soname}{syms};
  504. my @soname = ( $soname );
  505. # Scan raw symbols first.
  506. foreach my $sym (grep { $_->is_eligible_as_new($self->{arch}) }
  507. values %$mysyms)
  508. {
  509. my $refsym = $refsyms->{$sym->get_symbolname()};
  510. my $isnew;
  511. if (defined $refsym) {
  512. # If the symbol exists in the reference symbol file, it might
  513. # still be new if it is either deprecated or from foreign arch
  514. # there.
  515. $isnew = ($refsym->{deprecated} or
  516. not $refsym->arch_is_concerned($self->{arch}));
  517. } else {
  518. # If the symbol does not exist in the $ref symbol file, it does
  519. # not mean that it's new. It might still match a pattern in the
  520. # symbol file. However, due to performance reasons, first check
  521. # if the pattern that the symbol matches (if any) exists in the
  522. # ref symbol file as well.
  523. $isnew = not (
  524. ($sym->get_pattern() and $ref->lookup_pattern($sym->get_pattern(), \@soname, 1)) or
  525. $ref->find_matching_pattern($sym->get_symbolname(), \@soname, 1)
  526. );
  527. }
  528. push @res, $sym->sclone(soname => $soname) if $isnew;
  529. }
  530. # Now scan patterns
  531. foreach my $p (grep { $_->is_eligible_as_new($self->{arch}) }
  532. $self->get_soname_patterns($soname))
  533. {
  534. my $refpat = $ref->lookup_pattern($p, \@soname, 0);
  535. # If reference pattern was not found or it is deprecated or
  536. # it's from foreign arch, considering current one as new.
  537. if (not defined $refpat or
  538. not $refpat->arch_is_concerned($self->{arch}))
  539. {
  540. push @res, $p->sclone(soname => $soname);
  541. }
  542. }
  543. }
  544. return @res;
  545. }
  546. sub get_lost_symbols {
  547. my ($self, $ref) = @_;
  548. return $ref->get_new_symbols($self);
  549. }
  550. sub get_new_libs {
  551. my ($self, $ref) = @_;
  552. my @res;
  553. foreach my $soname (keys %{$self->{objects}}) {
  554. push @res, $soname if not exists $ref->{objects}{$soname};
  555. }
  556. return @res;
  557. }
  558. sub get_lost_libs {
  559. my ($self, $ref) = @_;
  560. return $ref->get_new_libs($self);
  561. }
  562. 1;