diff mbox series

[RFC,v2,3/3] packagedata: Extract GNU build ID during pkgdata creation

Message ID 20240305161856.4163138-4-philip.lorenz@bmw.de
State New
Headers show
Series package.bbclass: Expose list of split out debug files | expand

Commit Message

Philip Lorenz March 5, 2024, 4:18 p.m. UTC
Extract the GNU build ID from all files containing debug symbols and
store it within the "extended" package information of pkgdata as an
attribute of the files contained within a package - e.g.

{
  "files_info": {
    "/lib/.debug/ld-linux-x86-64.so.2": {
      "gnu_build_id": "a165bf2a6c9c6a0818450293bd6bb66a316eaa4f",
      "size":1170552
    }
  }
}

Tools can then consume this data for different purposes such as building
an build ID index into the generated package feed or to preseed the
database of a debug info server such as debuginfod.

Sequentially reading out the GNU build ID of ~8000 debug symbol files
(from a core-image-minimal build) took approximately 90 seconds on my
machine. Given that the read out in a typical build will be highly
parallel, I deemed this figure low enough to simply enable it without
an additional configuration flag.

Signed-off-by: Philip Lorenz <philip.lorenz@bmw.de>
---
 meta/lib/oe/packagedata.py              | 25 +++++++++++++++++++++++++
 meta/lib/oeqa/selftest/cases/pkgdata.py |  2 ++
 2 files changed, 27 insertions(+)
diff mbox series

Patch

diff --git a/meta/lib/oe/packagedata.py b/meta/lib/oe/packagedata.py
index 2d1d6ddeb75..3404c2a5cd2 100644
--- a/meta/lib/oe/packagedata.py
+++ b/meta/lib/oe/packagedata.py
@@ -255,6 +255,27 @@  fi
         fd.write("PACKAGES: %s\n" % packages)
 
     pkgdebugsource = d.getVar("PKGDEBUGSOURCES") or []
+    pkgdebugfiles = d.getVar("PKGDEBUGFILES") or []
+
+    pkgd = d.getVar("PKGD")
+    readelf = d.getVar("READELF")
+
+    def extract_gnu_build_id(file):
+        import subprocess
+
+        cmd = "%s -n '%s' | grep '^    Build ID: '" % (readelf, pkgd + file)
+        try:
+            result = subprocess.check_output(cmd, shell=True)
+            # If grep hadn't matched it would've returned a non-zero exit code
+            # and the CalledProcessError would've been raised. It is therefore
+            # safe to assume that the output has the format "    Build ID: "
+            gnu_build_id = result[result.rfind(b" ") + 1:].rstrip().decode()
+            return (file, gnu_build_id)
+        except subprocess.CalledProcessError:
+            return (None, None)
+
+    pkg_debug_build_ids = { debug_file: build_id \
+        for debug_file, build_id in oe.utils.multiprocess_launch(extract_gnu_build_id, pkgdebugfiles, d) if debug_file}
 
     pn = d.getVar('PN')
     global_variants = (d.getVar('MULTILIB_GLOBAL_VARIANTS') or "").split()
@@ -300,6 +321,10 @@  fi
             if fpath in pkgdebugsource:
                 extended_data["files_info"][fpath]['debugsrc'] = pkgdebugsource[fpath]
                 del pkgdebugsource[fpath]
+            if fpath in pkg_debug_build_ids:
+                extended_data["files_info"][fpath]['gnu_build_id'] = pkg_debug_build_ids[fpath]
+                del pkg_debug_build_ids[fpath]
+
 
         d.setVar('FILES_INFO:' + pkg , json.dumps(files, sort_keys=True))
 
diff --git a/meta/lib/oeqa/selftest/cases/pkgdata.py b/meta/lib/oeqa/selftest/cases/pkgdata.py
index 6c5b7a84f47..8b993261055 100644
--- a/meta/lib/oeqa/selftest/cases/pkgdata.py
+++ b/meta/lib/oeqa/selftest/cases/pkgdata.py
@@ -241,3 +241,5 @@  class OePkgdataUtilTests(OESelftestTestCase):
 
         file_info = files_info[libz_file_name]
         self.assertIn('size', file_info, "Couldn't find key 'size' in '%s'" % file_info)
+        self.assertIn('gnu_build_id', file_info, "Couldn't find key 'gnu_build_id' in '%s'" % file_info)
+        self.assertGreater(len(file_info['gnu_build_id']), 0)