d70da0b9e2
Change-Id: If2bf85301eb1523a636d031f6e5a9f78cb1ee06b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97871 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
152 lines
4.8 KiB
Python
Executable file
152 lines
4.8 KiB
Python
Executable file
#!/usr/bin/python2
|
|
#
|
|
# 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 sys
|
|
import re
|
|
import multiprocessing
|
|
|
|
exported_symbols = set()
|
|
imported_symbols = set()
|
|
|
|
|
|
# Copied from solenv/gbuild/extensions/pre_MergedLibsList.mk
|
|
# TODO there has to be a way to run gmake and get it to dump this list for me
|
|
merged_libs = { \
|
|
"avmedia" \
|
|
,"basctl" \
|
|
,"basprov" \
|
|
,"basegfx" \
|
|
,"canvasfactory" \
|
|
,"canvastools" \
|
|
,"comphelper" \
|
|
,"configmgr" \
|
|
,"cppcanvas" \
|
|
,"crashreport)" \
|
|
,"dbtools" \
|
|
,"deployment" \
|
|
,"deploymentmisc" \
|
|
,"desktopbe1)" \
|
|
,"desktop_detector)" \
|
|
,"drawinglayer" \
|
|
,"editeng" \
|
|
,"expwrap" \
|
|
,"filterconfig" \
|
|
,"fsstorage" \
|
|
,"fwk" \
|
|
,"helplinker)" \
|
|
,"i18npool" \
|
|
,"i18nutil" \
|
|
,"lng" \
|
|
,"localebe1" \
|
|
,"mcnttype" \
|
|
,"msfilter" \
|
|
,"mtfrenderer" \
|
|
,"opencl" \
|
|
,"package2" \
|
|
,"sax" \
|
|
,"sb" \
|
|
,"simplecanvas" \
|
|
,"sfx" \
|
|
,"sofficeapp" \
|
|
,"sot" \
|
|
,"spl" \
|
|
,"stringresource" \
|
|
,"svl" \
|
|
,"svt" \
|
|
,"svx" \
|
|
,"svxcore" \
|
|
,"tk" \
|
|
,"tl" \
|
|
,"ucb1" \
|
|
,"ucbhelper" \
|
|
,"ucpexpand1" \
|
|
,"ucpfile1" \
|
|
,"unoxml" \
|
|
,"utl" \
|
|
,"uui" \
|
|
,"vcl" \
|
|
,"xmlscript" \
|
|
,"xo" \
|
|
,"xstor" }
|
|
|
|
# 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()
|
|
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()
|
|
s = sharedlib[sharedlib.find("/lib") + 4 : len(sharedlib) - 3]
|
|
if s in merged_libs: continue
|
|
# 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()
|
|
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()
|
|
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")
|