Fix typo
[LibreOffice.git] / bin / find-mergedlib-can-be-private.py
blobb879ba260cbe6de7a92ed6990d839276595fe168
1 #!/usr/bin/python3
3 # Generate a custom linker script/map file for the --enabled-mergedlibs merged library
4 # which reduces the startup time and enables further optimisations with --enable-lto because 60% or more
5 # of the symbols become internal only.
8 import subprocess
9 import re
10 import multiprocessing
12 exported_symbols = set()
13 imported_symbols = set()
16 # look for symbols exported by libmerged
17 subprocess_nm = subprocess.Popen("nm -D instdir/program/libmergedlo.so", stdout=subprocess.PIPE, shell=True)
18 with subprocess_nm.stdout as txt:
19 # We are looking for lines something like:
20 # 0000000000036ed0 T flash_component_getFactory
21 line_regex = re.compile(r'^[0-9a-fA-F]+ T ')
22 for line in txt:
23 line = line.strip().decode("utf-8")
24 if line_regex.match(line):
25 exported_symbols.add(line.split(" ")[2])
26 subprocess_nm.terminate()
28 # look for symbols imported from libmerged
29 subprocess_find = subprocess.Popen("(find instdir/program/ -type f; ls ./workdir/LinkTarget/CppunitTest/*.so) | xargs grep -l mergedlo",
30 stdout=subprocess.PIPE, shell=True)
31 with subprocess_find.stdout as txt:
32 for line in txt:
33 sharedlib = line.strip().decode("utf-8")
34 s = sharedlib[sharedlib.find("/lib") + 4 : len(sharedlib) - 3]
35 # look for imported symbols
36 subprocess_objdump = subprocess.Popen("objdump -T " + sharedlib, stdout=subprocess.PIPE, shell=True)
37 with subprocess_objdump.stdout as txt2:
38 # ignore some header bumpf
39 txt2.readline()
40 txt2.readline()
41 txt2.readline()
42 txt2.readline()
43 # We are looking for lines something like (noting that one of them uses spaces, and the other tabs)
44 # 0000000000000000 DF *UND* 0000000000000000 _ZN16FilterConfigItem10WriteInt32ERKN3rtl8OUStringEi
45 for line2 in txt2:
46 line2 = line2.strip().decode("utf-8")
47 if line2.find("*UND*") == -1: continue
48 tokens = line2.split(" ")
49 sym = tokens[len(tokens)-1].strip()
50 imported_symbols.add(sym)
51 subprocess_objdump.terminate()
52 subprocess_find.terminate()
54 intersec_symbols = exported_symbols.intersection(imported_symbols)
55 print("no symbols exported from libmerged = " + str(len(exported_symbols)))
56 print("no symbols that can be made internal = " + str(len(intersec_symbols)))
58 # Now look for classes where none of the class symbols are imported,
59 # i.e. we can mark the whole class as hidden
61 def extract_class(sym):
62 filtered_sym = subprocess.check_output(["c++filt", sym]).strip().decode("utf-8")
63 if filtered_sym.startswith("vtable for "):
64 classname = filtered_sym[11:]
65 return classname
66 if filtered_sym.startswith("non-virtual thunk to "):
67 filtered_sym = filtered_sym[21:]
68 elif filtered_sym.startswith("virtual thunk to "):
69 filtered_sym = filtered_sym[17:]
70 i = filtered_sym.find("(")
71 if i != -1:
72 i = filtered_sym.rfind("::", 0, i)
73 if i != -1:
74 classname = filtered_sym[:i]
75 return classname
76 return ""
78 pool = multiprocessing.Pool(multiprocessing.cpu_count())
79 classes_with_exported_symbols = set(pool.map(extract_class, list(exported_symbols)))
80 classes_with_imported_symbols = set(pool.map(extract_class, list(imported_symbols)))
82 # Some stuff is particular to Windows, so won't be found by a Linux analysis, so remove
83 # those classes.
84 can_be_private_classes = classes_with_exported_symbols - classes_with_imported_symbols;
85 can_be_private_classes.discard("SpinField")
87 with open("bin/find-mergedlib-can-be-private.classes.results", "wt") as f:
88 for sym in sorted(can_be_private_classes):
89 if sym.startswith("std::") or sym.startswith("void std::"): continue
90 f.write(sym + "\n")