brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.4 KiB · b741310 Raw
103 lines · python
1"""A tool for extracting a list of private lldb symbols to export for MSVC.2 3When exporting symbols from a dll or exe we either need to mark the symbols in4the source code as __declspec(dllexport) or supply a list of symbols to the5linker. Private symbols in LLDB don't explicitly specific dllexport, so we6automate that by examining the symbol table.7"""8 9import argparse10import os11import re12import subprocess13import sys14 15 16def extract_symbols(nm_path: str, lib: str):17    """Extract all of the private lldb symbols from the given path to llvm-nm and18    library to extract from."""19 20    # Matches mangled symbols containing 'lldb_private'.21    lldb_sym_re = r"[0-9a-zA-Z]* [BT] (?P<symbol>[?]+[^?].*lldb_private.*)"22 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,31    )32    process.stdin.close()33 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(" ") == 041            ), "Regex matched too much, probably got undecorated name as well"42            # Deleting destructors start with ?_G or ?_E and can be discarded43            # because link.exe gives you a warning telling you they can't be44            # exported if you don't.45            if symbol.startswith("??_G") or symbol.startswith("??_E"):46                continue47            lldb_symbols.add(symbol)48 49    return lldb_symbols50 51 52def 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."56    )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.",64    )65    args = parser.parse_args()66 67    # Get the list of libraries to extract symbols from68    libs = list()69    for lib in args.libs:70        # When invoked by cmake the arguments are the cmake target names of the71        # libraries, so we need to add .lib/.a to the end and maybe lib to the72        # 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 + suffix78                    break79                if os.path.exists("lib" + lib + suffix):80                    lib = "lib" + lib + suffix81                    break82        if not any([lib.endswith(s) for s in suffixes]):83            print(84                "Unknown extension type for library argument: " + lib, file=sys.stderr85            )86            exit(1)87        libs.append(lib)88 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)94 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")99 100 101if __name__ == "__main__":102    main()103