Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / scripts / msvc_extract_private_symbols.py
blobb741310d717c23c1d019a233b7d2a577984f36e8
1 """A tool for extracting a list of private lldb symbols to export for MSVC.
3 When exporting symbols from a dll or exe we either need to mark the symbols in
4 the source code as __declspec(dllexport) or supply a list of symbols to the
5 linker. Private symbols in LLDB don't explicitly specific dllexport, so we
6 automate that by examining the symbol table.
7 """
9 import argparse
10 import os
11 import re
12 import subprocess
13 import sys
16 def extract_symbols(nm_path: str, lib: str):
17 """Extract all of the private lldb symbols from the given path to llvm-nm and
18 library to extract from."""
20 # Matches mangled symbols containing 'lldb_private'.
21 lldb_sym_re = r"[0-9a-zA-Z]* [BT] (?P<symbol>[?]+[^?].*lldb_private.*)"
23 # '-g' means we only get global symbols.
24 # '-p' do not waste time sorting the symbols.
25 process = subprocess.Popen(
26 [nm_path, "-g", "-p", lib],
27 bufsize=1,
28 stdout=subprocess.PIPE,
29 stdin=subprocess.PIPE,
30 universal_newlines=True,
32 process.stdin.close()
34 lldb_symbols = set()
35 for line in process.stdout:
36 match = re.match(lldb_sym_re, line)
37 if match:
38 symbol = match.group("symbol")
39 assert (
40 symbol.count(" ") == 0
41 ), "Regex matched too much, probably got undecorated name as well"
42 # Deleting destructors start with ?_G or ?_E and can be discarded
43 # because link.exe gives you a warning telling you they can't be
44 # exported if you don't.
45 if symbol.startswith("??_G") or symbol.startswith("??_E"):
46 continue
47 lldb_symbols.add(symbol)
49 return lldb_symbols
52 def main():
53 parser = argparse.ArgumentParser(description="Generate LLDB dll exports")
54 parser.add_argument(
55 "-o", metavar="file", type=str, help="The name of the resultant export file."
57 parser.add_argument("--nm", help="Path to the llvm-nm executable.")
58 parser.add_argument(
59 "libs",
60 metavar="lib",
61 type=str,
62 nargs="+",
63 help="The libraries to extract symbols from.",
65 args = parser.parse_args()
67 # Get the list of libraries to extract symbols from
68 libs = list()
69 for lib in args.libs:
70 # When invoked by cmake the arguments are the cmake target names of the
71 # libraries, so we need to add .lib/.a to the end and maybe lib to the
72 # start to get the filename. Also allow objects.
73 suffixes = [".lib", ".a", ".obj", ".o"]
74 if not any([lib.endswith(s) for s in suffixes]):
75 for suffix in suffixes:
76 if os.path.exists(lib + suffix):
77 lib = lib + suffix
78 break
79 if os.path.exists("lib" + lib + suffix):
80 lib = "lib" + lib + suffix
81 break
82 if not any([lib.endswith(s) for s in suffixes]):
83 print(
84 "Unknown extension type for library argument: " + lib, file=sys.stderr
86 exit(1)
87 libs.append(lib)
89 # Extract symbols from the input libraries.
90 symbols = set()
91 for lib in libs:
92 for sym in list(extract_symbols(args.nm, lib)):
93 symbols.add(sym)
95 # Write out the symbols to the output file.
96 with open(args.o, "w", newline="") as f:
97 for s in sorted(symbols):
98 f.write(f"{s}\n")
101 if __name__ == "__main__":
102 main()