mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Breno Rodrigues Alves <breno3011alves@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Andy Whitcroft <apw@canonical.com>, Joe Perches <joe@perches.com>,
	Dwaipayan Ray <dwaipayanray1@gmail.com>,
	Lukas Bulwahn <lukas.bulwahn@gmail.com>,
	Breno Rodrigues Alves <breno3011alves@gmail.com>
Subject: [RFC PATCH 4/7] scripts: convert generate_initcall_order.pl to Python
Date: Sun, 18 Oct 2026 08:06:35 -0300	[thread overview]
Message-ID: <20261018110638.9947-5-breno3011alves@gmail.com> (raw)
In-Reply-To: <20261018110638.9947-1-breno3011alves@gmail.com>

Faithful re-implementation of generate_initcall_order.pl in
Python 3 (stdlib only). Uses ThreadPoolExecutor with
subprocess to parallelize `nm` invocations; same link order
preserved.

Signed-off-by: Breno Rodrigues Alves <breno3011alves@gmail.com>
---
 scripts/generate_initcall_order.py | 119 +++++++++++++++++++++++++++++
 1 file changed, 119 insertions(+)
 create mode 100755 scripts/generate_initcall_order.py

diff --git a/scripts/generate_initcall_order.py b/scripts/generate_initcall_order.py
new file mode 100755
index 000000000..8ac466f34
--- /dev/null
+++ b/scripts/generate_initcall_order.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generates a linker script that specifies the correct initcall order.
+# Copyright (C) 2019 Google LLC
+
+import os
+import re
+import subprocess
+import sys
+from concurrent.futures import ThreadPoolExecutor
+
+NM     = os.environ.get('NM') or sys.exit("ERROR: NM not set?")
+OBJTREE = os.environ.get('objtree') or '.'
+
+RE_INITCALL = re.compile(r'[a-z]\s+__initcall__(\S*)__(\d+)_(\d+)_(.*)$')
+RE_FUNC_LEVEL = re.compile(r'^(.*)((early|rootfs|con|[0-9])s?)$')
+RE_ARCHIVE_HDR = re.compile(r'^(.+):$')
+
+
+def find_initcalls(index, file):
+    """Return list of (level, secname) for one object/archive."""
+    if not os.path.isfile(file):
+        sys.exit(f"ERROR: file {file} doesn't exist?")
+    try:
+        output = subprocess.check_output(
+            [NM, '--defined-only', file],
+            stderr=subprocess.DEVNULL, text=True)
+    except (subprocess.CalledProcessError, FileNotFoundError) as e:
+        sys.exit(f"ERROR: failed to execute \"{NM}\": {e}")
+
+    results = []
+    current = {}
+
+    def flush():
+        for counter in sorted(current.keys(), key=int):
+            e = current[counter]
+            secname = f"{e['module']}__{counter}_{e['line']}_{e['function']}"
+            results.append((e['level'], secname))
+
+    for raw in output.splitlines():
+        line = raw.strip()
+        m = RE_ARCHIVE_HDR.match(line)
+        if m:
+            flush()
+            current = {}
+            continue
+
+        m = RE_INITCALL.search(line)
+        if not m:
+            continue
+        module = m.group(1) or ''
+        counter = m.group(2)
+        line_no = m.group(3)
+        symbol = m.group(4)
+
+        fm = RE_FUNC_LEVEL.match(symbol)
+        if not fm:
+            sys.exit(f"ERROR: invalid initcall name {symbol} in "
+                     f"{file}({m.group(1)})")
+        function, level = fm.group(1), fm.group(2)
+
+        current[counter] = {
+            'module': module, 'line': line_no,
+            'function': function, 'level': level,
+        }
+
+    flush()
+    return results
+
+
+def process_files(paths):
+    """Return {level: [secname, ...]} preserving link order."""
+    njobs = int(os.environ.get('PARALLELISM')
+                or os.cpu_count() or 1)
+
+    indexed = [(i, os.path.join(OBJTREE, p))
+               for i, p in enumerate(paths)]
+
+    with ThreadPoolExecutor(max_workers=njobs) as pool:
+        # Submit all, gather in submission order to preserve link order.
+        futures = [pool.submit(find_initcalls, i, f)
+                   for i, f in indexed]
+        results_by_index = [f.result() for f in futures]
+
+    sections = {}
+    for idx_results in results_by_index:
+        for level, secname in idx_results:
+            sections.setdefault(level, []).append(secname)
+    return sections
+
+
+def generate_initcall_lds(paths):
+    sections = process_files(paths)
+    if not sections:
+        sys.exit("ERROR: no initcalls?")
+
+    print("SECTIONS {")
+    for level in sorted(sections):
+        if level == 'con':
+            section = '.con_initcall.init'
+        else:
+            section = f".initcall{level}.init"
+        print(f"\t{section} : {{")
+        for secname in sections[level]:
+            print(f"\t\t*({section}..{secname}) ;")
+        print("\t}")
+    print("}")
+
+
+def main(argv):
+    if not argv:
+        sys.exit("usage: generate_initcall_order.py <object files...>")
+    generate_initcall_lds(argv)
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
\ No newline at end of file
-- 
2.43.0


  parent reply	other threads:[~2026-10-18 11:06 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-18 11:06 [RFC PATCH 0/7] scripts: convert seven more Perl utilities " Breno Rodrigues Alves
2026-10-18 11:06 ` [RFC PATCH 1/7] scripts: convert checkdeclares.pl " Breno Rodrigues Alves
2026-10-18 11:06 ` [RFC PATCH 2/7] scripts: convert checkversion.pl " Breno Rodrigues Alves
2026-10-18 11:06 ` [RFC PATCH 3/7] scripts: convert extract_xc3028.pl " Breno Rodrigues Alves
2026-10-18 11:06 ` Breno Rodrigues Alves [this message]
2026-10-18 11:06 ` [RFC PATCH 5/7] scripts: convert get_maintainer.pl " Breno Rodrigues Alves
2026-10-18 11:06 ` [RFC PATCH 6/7] scripts: convert leaking_addresses.pl " Breno Rodrigues Alves
2026-10-18 11:06 ` [RFC PATCH 7/7] scripts: convert recordmcount.pl " Breno Rodrigues Alves
2026-10-18 20:59 ` [RFC PATCH 0/7] scripts: convert seven more Perl utilities " Jonathan Corbet
2026-10-18 23:19   ` Breno Rodrigues Alves
2026-10-19 10:05     ` Heiko Carstens

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261018110638.9947-5-breno3011alves@gmail.com \
    --to=breno3011alves@gmail.com \
    --cc=apw@canonical.com \
    --cc=dwaipayanray1@gmail.com \
    --cc=joe@perches.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lukas.bulwahn@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®