From 3c8773a854703467fdc6c0ee4854c79d993a1e86 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 28 Sep 2022 17:07:10 +0800 Subject: [PATCH] tools: Optimizing mkallsyms scripts with python When compiling my project, the time to generate allsyms decreased from tens of seconds to 2 seconds Signed-off-by: yinshengkai --- tools/mkallsyms.py | 148 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100755 tools/mkallsyms.py diff --git a/tools/mkallsyms.py b/tools/mkallsyms.py new file mode 100755 index 0000000000..f67e7445f4 --- /dev/null +++ b/tools/mkallsyms.py @@ -0,0 +1,148 @@ +#!/usr/bin/python3 +############################################################################ +# tools/mkallsyms.py +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +import errno +import os +import re +import sys + +try: + import cxxfilt + from elftools import __version__ + from elftools.elf.elffile import ELFFile + from elftools.elf.sections import SymbolTableSection + +except ModuleNotFoundError: + print("Please execute the following command to install dependencies:") + print("pip install pyelftools cxxfilt") + + +class SymbolTables(object): + def __init__(self, elffile, output): + try: + file = open(elffile, "rb") + self.elffile = ELFFile(file) + except FileNotFoundError: + self.elffile = None + self.output = output + self.symbol_list = [] + + def symbol_filter(self, symbol): + if symbol["st_info"]["type"] != "STT_FUNC": + return None + if symbol["st_info"]["bind"] == "STB_WEAK": + return None + if symbol["st_shndx"] == "SHN_UNDEF": + return None + return symbol + + def print_symbol_tables(self, isnoconst=False): + noconst = "const" + if not isnoconst: + noconst = "" + + self.emitline("#include ") + self.emitline("#include \n") + self.emitline("%s int g_nallsyms = %d + 2;" % (noconst, len(self.symbol_list))) + self.emitline( + "%s struct symtab_s g_allsyms[%d + 2] =\n{" + % (noconst, len(self.symbol_list)) + ) + self.emitline(' { "Unknown", (FAR %s void *)0x00000000 },' % (noconst)) + for symbol in self.symbol_list: + self.emitline( + ' { "%s", (FAR %s void *)%s },' % (symbol[1], noconst, hex(symbol[0])) + ) + self.emitline(' { "Unknown", (FAR %s void *)0xffffffff }\n};' % (noconst)) + + def get_symtable(self): + symbol_tables = [ + (idx, s) + for idx, s in enumerate(self.elffile.iter_sections()) + if isinstance(s, SymbolTableSection) + ] + + if not symbol_tables and self.elffile.num_sections() == 0: + self.emitline("") + return + + for section_index, section in symbol_tables: + if not isinstance(section, SymbolTableSection): + continue + + if section["sh_entsize"] == 0 or section.name != ".symtab": + continue + + return section + + def parse_symbol(self): + if self.elffile is None: + return + symtable = self.get_symtable() + for nsym, symbol in enumerate(symtable.iter_symbols()): + if self.symbol_filter(symbol) is not None: + symbol_name = cxxfilt.demangle(symbol.name) + func_name = re.sub(r"\(.*$", "", symbol_name) + self.symbol_list.append((symbol["st_value"], func_name)) + self.symbol_list = sorted(self.symbol_list, key=lambda item: item[0]) + + def emitline(self, s=""): + self.output.write(str(s) + "\n") + + +def usage(): + print("Usage: mkallsyms.py [noconst] [output file]") + os._exit(errno.ENOENT) + + +def parse_args(argv): + index = 1 + argc = len(argv) + outfile = None + elffile = None + + if argc > index and argv[index] == "--version": + print("mkallsyms.py: based on pyelftools %s" % __version__) + os.exit(0) + + if argc > index and argv[index] == "noconst": + noconst = True + index += 1 + else: + noconst = False + + if argc > index: + elffile = argv[index] + index += 1 + + if argc > index: + outfile = open(argv[index], "w") + else: + outfile = sys.stdout + + return noconst, elffile, outfile + + +if __name__ == "__main__": + noconst, elffile, outfile = parse_args(sys.argv) + readelf = SymbolTables(elffile, outfile) + readelf.parse_symbol() + readelf.print_symbol_tables(noconst)