office-gobmx/bin/find-mergedlib-can-be-private.py
Noel Grandin 864e752d9e simplify this python script
I dont need to exclude the .so files that have been merged, they exist,
but they contain only a dummy string

Change-Id: I3b008859f4c3d4831025c082dd589e55c46ef078
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163639
Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2024-02-20 12:34:23 +01:00

90 lines
3.7 KiB
Python
Executable file

#!/usr/bin/python3
#
# Generate a custom linker script/map file for the --enabled-mergedlibs merged library
# which reduces the startup time and enables further optimisations with --enable-lto because 60% or more
# of the symbols become internal only.
#
import subprocess
import re
import multiprocessing
exported_symbols = set()
imported_symbols = set()
# look for symbols exported by libmerged
subprocess_nm = subprocess.Popen("nm -D instdir/program/libmergedlo.so", stdout=subprocess.PIPE, shell=True)
with subprocess_nm.stdout as txt:
# We are looking for lines something like:
# 0000000000036ed0 T flash_component_getFactory
line_regex = re.compile(r'^[0-9a-fA-F]+ T ')
for line in txt:
line = line.strip().decode("utf-8")
if line_regex.match(line):
exported_symbols.add(line.split(" ")[2])
subprocess_nm.terminate()
# look for symbols imported from libmerged
subprocess_find = subprocess.Popen("(find instdir/program/ -type f; ls ./workdir/LinkTarget/CppunitTest/*.so) | xargs grep -l mergedlo",
stdout=subprocess.PIPE, shell=True)
with subprocess_find.stdout as txt:
for line in txt:
sharedlib = line.strip().decode("utf-8")
s = sharedlib[sharedlib.find("/lib") + 4 : len(sharedlib) - 3]
# look for imported symbols
subprocess_objdump = subprocess.Popen("objdump -T " + sharedlib, stdout=subprocess.PIPE, shell=True)
with subprocess_objdump.stdout as txt2:
# ignore some header bumpf
txt2.readline()
txt2.readline()
txt2.readline()
txt2.readline()
# We are looking for lines something like (noting that one of them uses spaces, and the other tabs)
# 0000000000000000 DF *UND* 0000000000000000 _ZN16FilterConfigItem10WriteInt32ERKN3rtl8OUStringEi
for line2 in txt2:
line2 = line2.strip().decode("utf-8")
if line2.find("*UND*") == -1: continue
tokens = line2.split(" ")
sym = tokens[len(tokens)-1].strip()
imported_symbols.add(sym)
subprocess_objdump.terminate()
subprocess_find.terminate()
intersec_symbols = exported_symbols.intersection(imported_symbols)
print("no symbols exported from libmerged = " + str(len(exported_symbols)))
print("no symbols that can be made internal = " + str(len(intersec_symbols)))
# Now look for classes where none of the class symbols are imported,
# i.e. we can mark the whole class as hidden
def extract_class(sym):
filtered_sym = subprocess.check_output(["c++filt", sym]).strip().decode("utf-8")
if filtered_sym.startswith("vtable for "):
classname = filtered_sym[11:]
return classname
if filtered_sym.startswith("non-virtual thunk to "):
filtered_sym = filtered_sym[21:]
elif filtered_sym.startswith("virtual thunk to "):
filtered_sym = filtered_sym[17:]
i = filtered_sym.find("(")
if i != -1:
i = filtered_sym.rfind("::", 0, i)
if i != -1:
classname = filtered_sym[:i]
return classname
return ""
pool = multiprocessing.Pool(multiprocessing.cpu_count())
classes_with_exported_symbols = set(pool.map(extract_class, list(exported_symbols)))
classes_with_imported_symbols = set(pool.map(extract_class, list(imported_symbols)))
# Some stuff is particular to Windows, so won't be found by a Linux analysis, so remove
# those classes.
can_be_private_classes = classes_with_exported_symbols - classes_with_imported_symbols;
can_be_private_classes.discard("SpinField")
with open("bin/find-mergedlib-can-be-private.classes.results", "wt") as f:
for sym in sorted(can_be_private_classes):
if sym.startswith("std::") or sym.startswith("void std::"): continue
f.write(sym + "\n")