1 |
In order to account for internal library resolution which a package |
2 |
may implement (useful at least for handling of bundled libraries), |
3 |
generate implicit runpath entries for any needed sonames which are |
4 |
provided by the same owner package. |
5 |
|
6 |
For packages that have bundled versions of system libraries, this will |
7 |
prevent preserve-libs from unecessarily preserving system libraries as |
8 |
reported in bug 705736. For the www-client/firefox-bin-72.0.2 package, |
9 |
this adds an implicit /opt/firefox runpath entry to 15 files. |
10 |
|
11 |
Bug: https://bugs.gentoo.org/705736 |
12 |
Signed-off-by: Zac Medico <zmedico@g.o> |
13 |
--- |
14 |
lib/portage/util/_dyn_libs/LinkageMapELF.py | 63 ++++++++++++++++++--- |
15 |
1 file changed, 54 insertions(+), 9 deletions(-) |
16 |
|
17 |
diff --git a/lib/portage/util/_dyn_libs/LinkageMapELF.py b/lib/portage/util/_dyn_libs/LinkageMapELF.py |
18 |
index 92a50b444..70bec116a 100644 |
19 |
--- a/lib/portage/util/_dyn_libs/LinkageMapELF.py |
20 |
+++ b/lib/portage/util/_dyn_libs/LinkageMapELF.py |
21 |
@@ -1,7 +1,9 @@ |
22 |
-# Copyright 1998-2019 Gentoo Authors |
23 |
+# Copyright 1998-2020 Gentoo Authors |
24 |
# Distributed under the terms of the GNU General Public License v2 |
25 |
|
26 |
+import collections |
27 |
import errno |
28 |
+import itertools |
29 |
import logging |
30 |
import subprocess |
31 |
import sys |
32 |
@@ -14,6 +16,7 @@ from portage import _unicode_encode |
33 |
from portage.cache.mappings import slot_dict_class |
34 |
from portage.const import EPREFIX |
35 |
from portage.dep.soname.multilib_category import compute_multilib_category |
36 |
+from portage.dep.soname.SonameAtom import SonameAtom |
37 |
from portage.exception import CommandNotFound, InvalidData |
38 |
from portage.localization import _ |
39 |
from portage.util import getlibpaths |
40 |
@@ -328,8 +331,13 @@ class LinkageMapELF(object): |
41 |
# Share identical frozenset instances when available, |
42 |
# in order to conserve memory. |
43 |
frozensets = {} |
44 |
+ owner_entries = collections.defaultdict(list) |
45 |
|
46 |
- for owner, location, l in lines: |
47 |
+ while True: |
48 |
+ try: |
49 |
+ owner, location, l = lines.pop() |
50 |
+ except IndexError: |
51 |
+ break |
52 |
l = l.rstrip("\n") |
53 |
if not l: |
54 |
continue |
55 |
@@ -352,18 +360,55 @@ class LinkageMapELF(object): |
56 |
# exists, map e_machine (entry.arch) to an approximate |
57 |
# multilib category. If all else fails, use e_machine, just |
58 |
# as older versions of portage did. |
59 |
- arch = entry.multilib_category |
60 |
- if arch is None: |
61 |
- arch = _approx_multilib_categories.get( |
62 |
+ if entry.multilib_category is None: |
63 |
+ entry.multilib_category = _approx_multilib_categories.get( |
64 |
entry.arch, entry.arch) |
65 |
|
66 |
- obj = entry.filename |
67 |
- soname = entry.soname |
68 |
+ entry.filename = normalize_path(entry.filename) |
69 |
expand = {"ORIGIN": os.path.dirname(entry.filename)} |
70 |
- path = frozenset(normalize_path( |
71 |
+ entry.runpaths = frozenset(normalize_path( |
72 |
varexpand(x, expand, error_leader=lambda: "%s: " % location)) |
73 |
for x in entry.runpaths) |
74 |
- path = frozensets.setdefault(path, path) |
75 |
+ entry.runpaths = frozensets.setdefault(entry.runpaths, entry.runpaths) |
76 |
+ owner_entries[owner].append(entry) |
77 |
+ |
78 |
+ # In order to account for internal library resolution which a package |
79 |
+ # may implement (useful at least for handling of bundled libraries), |
80 |
+ # generate implicit runpath entries for any needed sonames which are |
81 |
+ # provided by the same owner package. |
82 |
+ for owner, entries in owner_entries.items(): |
83 |
+ if owner is None: |
84 |
+ continue |
85 |
+ |
86 |
+ providers = {} |
87 |
+ for entry in entries: |
88 |
+ if entry.soname: |
89 |
+ providers[SonameAtom(entry.multilib_category, entry.soname)] = entry |
90 |
+ |
91 |
+ for entry in entries: |
92 |
+ implicit_runpaths = [] |
93 |
+ for soname in entry.needed: |
94 |
+ soname_atom = SonameAtom(entry.multilib_category, soname) |
95 |
+ provider = providers.get(soname_atom) |
96 |
+ if provider is None: |
97 |
+ continue |
98 |
+ provider_dir = os.path.dirname(provider.filename) |
99 |
+ if provider_dir not in entry.runpaths: |
100 |
+ implicit_runpaths.append(provider_dir) |
101 |
+ |
102 |
+ if implicit_runpaths: |
103 |
+ entry.runpaths = frozenset( |
104 |
+ itertools.chain(entry.runpaths, implicit_runpaths)) |
105 |
+ entry.runpaths = frozensets.setdefault( |
106 |
+ entry.runpaths, entry.runpaths) |
107 |
+ |
108 |
+ for owner, entry in ((owner, entry) |
109 |
+ for (owner, entries) in owner_entries.items() |
110 |
+ for entry in entries): |
111 |
+ arch = entry.multilib_category |
112 |
+ obj = entry.filename |
113 |
+ soname = entry.soname |
114 |
+ path = entry.runpaths |
115 |
needed = frozenset(entry.needed) |
116 |
|
117 |
needed = frozensets.setdefault(needed, needed) |
118 |
-- |
119 |
2.24.1 |