mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-14 23:15:14 -04:00
remove auto orderfile generation, too much hassle. Manually regenerate the two orderfiles. Change it to use newlines so the diff is better.
77 lines
3.9 KiB
Python
Executable File
77 lines
3.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""usage: gen_order.py <hot.text> <hot.rodata> <out.ld> [--v8 <libc_v8.a> <v8.txt>] <obj-or-archive>...
|
|
|
|
Builds a symbol -> (file, section) map from the objects and emits an INSERT
|
|
linker script that places the hot sections in .text.hot / .rodata.hot ahead of
|
|
.text / .rodata. Patterns are scoped to their object file (`*api.o(...)`):
|
|
LLD tests every input section against every unscoped pattern, which turns a
|
|
26k-pattern script into an 80s link; scoped, it is a few seconds.
|
|
|
|
With --v8, symbols defined in that archive are written to <v8.txt> for
|
|
mark_hot_sections.zig instead, and the script matches them with one
|
|
`.text.hot.*` / `.rodata.hot.*` glob (V8's sections are all named `.text`).
|
|
"""
|
|
import sys, subprocess, collections, re, os
|
|
hot_text, hot_rodata, out = sys.argv[1:4]
|
|
objs = sys.argv[4:]
|
|
v8_archive = v8_out = None
|
|
if objs and objs[0] == "--v8":
|
|
v8_archive, v8_out = os.path.basename(objs[1]), objs[2]
|
|
objs = [objs[1]] + objs[3:]
|
|
loc_of = collections.defaultdict(set) # symbol -> {(archive, file, section)}
|
|
for o in objs:
|
|
p = subprocess.run(["objdump", "-t", o], capture_output=True, text=True).stdout
|
|
fname = archive = os.path.basename(o)
|
|
for line in p.splitlines():
|
|
m = re.match(r"^(.+?):\s+file format elf", line)
|
|
if m:
|
|
fname = os.path.basename(m.group(1))
|
|
continue
|
|
# value flags section<TAB>size name -- the section can contain spaces (zig)
|
|
if "\t" not in line: continue
|
|
left, right = line.split("\t", 1)
|
|
parts = right.split(None, 1)
|
|
if len(parts) != 2: continue
|
|
name = parts[1].strip()
|
|
for vis in (".hidden ", ".protected ", ".internal "):
|
|
if name.startswith(vis): name = name[len(vis):]
|
|
fl = left[17:24]
|
|
if "d" in fl: continue # section symbol
|
|
sec = left[24:].strip()
|
|
if sec.startswith((".text", ".rodata")):
|
|
loc_of[name].add((archive, fname, sec))
|
|
def esc(s):
|
|
return re.sub(r'([*?\[\]\\])', r'\\\1', s)
|
|
stats = collections.Counter()
|
|
v8_syms = []
|
|
def emit(hotfile, prefix):
|
|
by_file = collections.OrderedDict(); seen = set()
|
|
for name in open(hotfile).read().split("\n"):
|
|
if not name: continue
|
|
locs = loc_of.get(name)
|
|
if not locs: stats[prefix + " nomap"] += 1; continue
|
|
for archive, fname, sec in sorted(locs):
|
|
if not sec.startswith(prefix): continue
|
|
if archive == v8_archive:
|
|
# The embedded builtins blob is left cold (see
|
|
# mark_hot_sections.zig); don't emit a pattern for it.
|
|
if name.startswith("Builtins_"): stats[prefix + " v8-blob-skip"] += 1; continue
|
|
v8_syms.append(name); stats[prefix + " v8"] += 1; continue
|
|
if sec == prefix or sec.endswith("."): stats[prefix + " generic"] += 1; continue
|
|
if '"' in sec or '"' in fname: stats[prefix + " quote-skip"] += 1; continue
|
|
if (fname, sec) in seen: continue
|
|
seen.add((fname, sec)); by_file.setdefault(fname, []).append(sec)
|
|
stats[prefix + " sections"] = len(seen); stats[prefix + " files"] = len(by_file)
|
|
# LLD unquotes section names but not the file pattern, so that one stays bare.
|
|
lines = [f' *{esc(f)}(\n' + "\n".join(f' "{esc(s)}"' for s in secs) + "\n )" for f, secs in by_file.items()]
|
|
if v8_archive: lines.insert(0, f' *("{prefix}.hot.*")')
|
|
return lines
|
|
t = emit(hot_text, ".text"); r = emit(hot_rodata, ".rodata")
|
|
with open(out, "w") as f:
|
|
f.write("/* Generated by orderfile/tools/gen_order.py, see orderfile/README.md. */\n")
|
|
f.write("SECTIONS {\n .text.hot : {\n" + "\n".join(t) + "\n }\n} INSERT BEFORE .text;\n")
|
|
f.write("SECTIONS {\n .rodata.hot : {\n" + "\n".join(r) + "\n }\n} INSERT BEFORE .rodata;\n")
|
|
if v8_out:
|
|
with open(v8_out, "w") as f: f.write("\n".join(dict.fromkeys(v8_syms)) + "\n")
|
|
for k, v in sorted(stats.items()): print(f"{k}: {v}")
|