diff mbox series

[5/6] lib/oe/package: use elfutils instead of objdump to extract SONAME etc

Message ID 20261019145837.2487873-5-ross.burton@arm.com
State New
Headers show
Series [1/6] lib/oe/sstatesig: cache the user/group lookups in OEOuthashBasic | expand

Commit Message

Ross Burton Oct. 19, 2026, 2:58 p.m. UTC
Currently the process_shlibs() function uses OBJDUMP (typically, objdump
from binutils) to extract the NEEDED/SONAME/RPATH values from the ELF.

However, there is no explicit dependency on binutils in do_package,
instead it comes into the sysroot via the default toolchain dependencies
in do_configure, so a recipe that does INHIBIT_DEFAULT_DEPS and also
packages an executable file will try and then fail to run objdump.

Currently this error is silently ignored, which is acceptable if the
executable is a script, but if the recipe contains ELFs without ever
depending on binutils (precompiled, or a different toolchain) then the
shlibs code won't actually run correctly.

do_package() already depends on elfutils-native for eu-srcfiles, so
switch the code to use eu-readelf instead.

Also use subprocess.run() with a command list instead of a string to
os.popen().  The os.popen() code didn't have any error handling meaning
it silently ignored both "objdump not found" and "file is not ELF", we
can assume that eu-readelf exists but we still need to absorb errors
from not passing a valid ELF.

Signed-off-by: Ross Burton <ross.burton@arm.com>
---
 meta/lib/oe/package.py | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/meta/lib/oe/package.py b/meta/lib/oe/package.py
index 8ecb2555f3a..e706e359cc3 100644
--- a/meta/lib/oe/package.py
+++ b/meta/lib/oe/package.py
@@ -1654,23 +1654,24 @@  def process_shlibs(pkgfiles, d):
         needed = set()
         sonames = set()
         ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
-        cmd = d.getVar('OBJDUMP') + " -p " + shlex.quote(file) + " 2>/dev/null"
-        fd = os.popen(cmd)
-        lines = fd.readlines()
-        fd.close()
         rpath = tuple()
+        cmd = ["eu-readelf", "--dynamic", file]
+        # Don't check for errors as we may be passed non-ELF
+        ret = subprocess.run(cmd, capture_output=True, text=True)
+
+        lines = ret.stdout.splitlines()
         for l in lines:
-            m = re.match(r"\s+RPATH\s+([^\s]*)", l)
+            m = re.match(r"\s+RPATH\s+.+\[(.+)\]", l)
             if m:
                 rpaths = m.group(1).replace("$ORIGIN", ldir).split(":")
                 rpath = tuple(map(os.path.normpath, rpaths))
         for l in lines:
-            m = re.match(r"\s+NEEDED\s+([^\s]*)", l)
+            m = re.match(r"\s+NEEDED\s+.+\[(.+)\]", l)
             if m:
                 dep = m.group(1)
                 if dep not in needed:
                     needed.add((dep, file, rpath))
-            m = re.match(r"\s+SONAME\s+([^\s]*)", l)
+            m = re.match(r"\s+SONAME\s+.+\[(.+)\]", l)
             if m:
                 this_soname = m.group(1)
                 prov = (this_soname, ldir, pkgver)