summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
Diffstat (limited to 'meta')
-rw-r--r--meta/recipes-core/systemd/dlopen-deps.inc73
-rw-r--r--meta/recipes-core/systemd/systemd_256.7.bb4
2 files changed, 75 insertions, 2 deletions
diff --git a/meta/recipes-core/systemd/dlopen-deps.inc b/meta/recipes-core/systemd/dlopen-deps.inc
new file mode 100644
index 0000000000..eaf6ca1f79
--- /dev/null
+++ b/meta/recipes-core/systemd/dlopen-deps.inc
@@ -0,0 +1,73 @@
1PACKAGEFUNCS =+ "package_generate_dlopen_deps"
2
3python package_generate_dlopen_deps() {
4 # https://systemd.io/ELF_DLOPEN_METADATA/
5
6 import struct, json
7
8 def extract_segment(filename, segment):
9 """
10 Return the named segment from the ELF.
11 """
12 import tempfile, subprocess
13
14 with tempfile.NamedTemporaryFile() as f:
15 cmd = [d.getVar("OBJCOPY"), "--dump-section", f"{segment}={f.name}", filename]
16 subprocess.run(cmd, check=True)
17 return f.read()
18
19 def parse(buffer, is_little):
20 deps = []
21 offset = 0
22 while offset < len(buffer):
23 format = f"{'<' if is_little else '>'}iii"
24 name_size, desc_size, note_type = struct.unpack_from(format, buffer, offset)
25 offset += struct.calcsize(format)
26
27 format = f"{name_size}s0i{desc_size}s0i"
28 if note_type == 0x407c0c0a:
29 name_b, desc_b = struct.unpack_from(format, buffer, offset)
30 name = name_b.strip(b"\x00").decode("ascii")
31 if name == "FDO":
32 desc = desc_b.strip(b"\x00").decode("utf-8")
33 deps.append(*json.loads(desc))
34 offset += struct.calcsize(format)
35 return deps
36
37 dep_map = {
38 "required": "RDEPENDS",
39 "recommended": "RRECOMMENDS",
40 "suggested": "RSUGGESTS"
41 }
42
43 shlibs = oe.package.read_shlib_providers(d)
44
45 for pkg, files in pkgfiles.items():
46 # Skip -dbg packages as we won't need to generate dependencies for those
47 # but scanning can take time
48 if pkg.endswith("-dbg"):
49 continue
50
51 for f in files:
52 # Skip symlinks, just look for real libraries
53 if cpath.islink(f):
54 continue
55
56 if ".so." in f or f.endswith(".so"):
57 try:
58 elf = oe.qa.ELFFile(f)
59 elf.open()
60 for dep in parse(extract_segment(f, ".note.dlopen"), elf.isLittleEndian()):
61 for soname in dep["soname"]:
62 if soname in shlibs:
63 # TODO assumes the first match is good
64 package, version = list(shlibs[soname].values())[0]
65 dependency = dep_map[dep["priority"]]
66 bb.note(f"{pkg}: adding {dependency} on {package} via .note.dlopen")
67 d.appendVar(f"{dependency}:{pkg}", f" {package} (>= {version})")
68 else:
69 bb.warn(f"cannot find {soname}")
70 except oe.qa.NotELFFileError as e:
71 bb.note(f"Cannot extract ELF notes: {e}")
72 pass
73}
diff --git a/meta/recipes-core/systemd/systemd_256.7.bb b/meta/recipes-core/systemd/systemd_256.7.bb
index 8b7ed2efe2..97537d09ba 100644
--- a/meta/recipes-core/systemd/systemd_256.7.bb
+++ b/meta/recipes-core/systemd/systemd_256.7.bb
@@ -742,8 +742,6 @@ INSANE_SKIP:libsystemd-shared += "libdir"
742FILES:libsystemd-shared = "${rootlibdir}/systemd/libsystemd-shared*.so" 742FILES:libsystemd-shared = "${rootlibdir}/systemd/libsystemd-shared*.so"
743 743
744RPROVIDES:udev = "hotplug" 744RPROVIDES:udev = "hotplug"
745# This can be removed when we parse .note.dlopen in the ELF
746RDEPENDS:udev += "libkmod"
747 745
748RDEPENDS:udev-bash-completion += "bash-completion" 746RDEPENDS:udev-bash-completion += "bash-completion"
749RDEPENDS:udev-hwdb += "udev" 747RDEPENDS:udev-hwdb += "udev"
@@ -915,3 +913,5 @@ pkg_postinst:udev-hwdb () {
915pkg_prerm:udev-hwdb () { 913pkg_prerm:udev-hwdb () {
916 rm -f $D${sysconfdir}/udev/hwdb.bin 914 rm -f $D${sysconfdir}/udev/hwdb.bin
917} 915}
916
917require dlopen-deps.inc