mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-09 20:41:14 +00:00
ci: Add python types hints
This commit is contained in:
@@ -8,15 +8,11 @@ import argparse
|
||||
import os
|
||||
import re
|
||||
from functools import partial
|
||||
from typing import BinaryIO, Callable, Dict, Generator, List, Optional, Tuple
|
||||
|
||||
import elftools
|
||||
from elftools.elf import elffile
|
||||
|
||||
try:
|
||||
from typing import BinaryIO, Callable, Dict, Generator, List, Optional, Tuple
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
FUNCTION_REGEX = re.compile(
|
||||
r'^;; Function (?P<mangle>.*)\s+\((?P<function>\S+)(,.*)?\).*$'
|
||||
)
|
||||
@@ -25,29 +21,29 @@ SYMBOL_REF_REGEX = re.compile(r'^.*\(symbol_ref[^()]*\("(?P<target>.*)"\).*$')
|
||||
|
||||
|
||||
class RtlFunction(object):
|
||||
def __init__(self, name, rtl_filename, tu_filename):
|
||||
def __init__(self, name: str, rtl_filename: str, tu_filename: str) -> None:
|
||||
self.name = name
|
||||
self.rtl_filename = rtl_filename
|
||||
self.tu_filename = tu_filename
|
||||
self.calls = list() # type: List[str]
|
||||
self.refs = list() # type: List[str]
|
||||
self.calls: List[str] = list()
|
||||
self.refs: List[str] = list()
|
||||
self.sym = None
|
||||
|
||||
|
||||
class SectionAddressRange(object):
|
||||
def __init__(self, name, addr, size): # type: (str, int, int) -> None
|
||||
def __init__(self, name: str, addr: int, size: int) -> None:
|
||||
self.name = name
|
||||
self.low = addr
|
||||
self.high = addr + size
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return '{}: 0x{:08x} - 0x{:08x}'.format(self.name, self.low, self.high)
|
||||
|
||||
def contains_address(self, addr):
|
||||
def contains_address(self, addr: int) -> bool:
|
||||
return self.low <= addr < self.high
|
||||
|
||||
|
||||
TARGET_SECTIONS = {
|
||||
TARGET_SECTIONS: Dict[str, List[SectionAddressRange]] = {
|
||||
'esp32': [
|
||||
SectionAddressRange('.rom.text', 0x40000000, 0x70000),
|
||||
SectionAddressRange('.rom.rodata', 0x3ff96000, 0x9018)
|
||||
@@ -60,20 +56,20 @@ TARGET_SECTIONS = {
|
||||
SectionAddressRange('.rom.text', 0x40000000, 0x568d0),
|
||||
SectionAddressRange('.rom.rodata', 0x3ff071c0, 0x8e30)
|
||||
]
|
||||
} # type: Dict[str, List[SectionAddressRange]]
|
||||
}
|
||||
|
||||
|
||||
class Symbol(object):
|
||||
def __init__(self, name, addr, local, filename, section): # type: (str, int, bool, Optional[str], Optional[str]) -> None
|
||||
def __init__(self, name: str, addr: int, local: bool, filename: Optional[str], section: Optional[str]) -> None:
|
||||
self.name = name
|
||||
self.addr = addr
|
||||
self.local = local
|
||||
self.filename = filename
|
||||
self.section = section
|
||||
self.refers_to = list() # type: List[Symbol]
|
||||
self.referred_from = list() # type: List[Symbol]
|
||||
self.refers_to: List[Symbol] = list()
|
||||
self.referred_from: List[Symbol] = list()
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return '{} @0x{:08x} [{}]{} {}'.format(
|
||||
self.name,
|
||||
self.addr,
|
||||
@@ -84,11 +80,11 @@ class Symbol(object):
|
||||
|
||||
|
||||
class Reference(object):
|
||||
def __init__(self, from_sym, to_sym): # type: (Symbol, Symbol) -> None
|
||||
def __init__(self, from_sym: Symbol, to_sym: Symbol) -> None:
|
||||
self.from_sym = from_sym
|
||||
self.to_sym = to_sym
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return '{} @0x{:08x} ({}) -> {} @0x{:08x} ({})'.format(
|
||||
self.from_sym.name,
|
||||
self.from_sym.addr,
|
||||
@@ -100,13 +96,13 @@ class Reference(object):
|
||||
|
||||
|
||||
class ElfInfo(object):
|
||||
def __init__(self, elf_file): # type: (BinaryIO) -> None
|
||||
def __init__(self, elf_file: BinaryIO) -> None:
|
||||
self.elf_file = elf_file
|
||||
self.elf_obj = elffile.ELFFile(self.elf_file)
|
||||
self.section_ranges = self._load_sections()
|
||||
self.symbols = self._load_symbols()
|
||||
|
||||
def _load_symbols(self): # type: () -> List[Symbol]
|
||||
def _load_symbols(self) -> List[Symbol]:
|
||||
symbols = []
|
||||
for s in self.elf_obj.iter_sections():
|
||||
if not isinstance(s, elftools.elf.sections.SymbolTableSection):
|
||||
@@ -130,7 +126,7 @@ class ElfInfo(object):
|
||||
)
|
||||
return symbols
|
||||
|
||||
def _load_sections(self): # type: () -> List[SectionAddressRange]
|
||||
def _load_sections(self) -> List[SectionAddressRange]:
|
||||
result = []
|
||||
for segment in self.elf_obj.iter_segments():
|
||||
if segment['p_type'] == 'PT_LOAD':
|
||||
@@ -149,22 +145,22 @@ class ElfInfo(object):
|
||||
|
||||
return result
|
||||
|
||||
def symbols_by_name(self, name): # type: (str) -> List[Symbol]
|
||||
def symbols_by_name(self, name: str) -> List['Symbol']:
|
||||
res = []
|
||||
for sym in self.symbols:
|
||||
if sym.name == name:
|
||||
res.append(sym)
|
||||
return res
|
||||
|
||||
def section_for_addr(self, sym_addr): # type: (int) -> Optional[str]
|
||||
def section_for_addr(self, sym_addr: int) -> Optional[str]:
|
||||
for sar in self.section_ranges:
|
||||
if sar.contains_address(sym_addr):
|
||||
return sar.name
|
||||
return None
|
||||
|
||||
|
||||
def load_rtl_file(rtl_filename, tu_filename, functions): # type: (str, str, List[RtlFunction]) -> None
|
||||
last_function = None # type: Optional[RtlFunction]
|
||||
def load_rtl_file(rtl_filename: str, tu_filename: str, functions: List[RtlFunction]) -> None:
|
||||
last_function: Optional[RtlFunction] = None
|
||||
for line in open(rtl_filename):
|
||||
# Find function definition
|
||||
match = re.match(FUNCTION_REGEX, line)
|
||||
@@ -192,7 +188,7 @@ def load_rtl_file(rtl_filename, tu_filename, functions): # type: (str, str, Lis
|
||||
continue
|
||||
|
||||
|
||||
def rtl_filename_matches_sym_filename(rtl_filename, symbol_filename): # type: (str, str) -> bool
|
||||
def rtl_filename_matches_sym_filename(rtl_filename: str, symbol_filename: str) -> bool:
|
||||
# Symbol file names (from ELF debug info) are short source file names, without path: "cpu_start.c".
|
||||
# RTL file names are paths relative to the build directory, e.g.:
|
||||
# "build/esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.234r.expand"
|
||||
@@ -211,7 +207,7 @@ class SymbolNotFound(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def find_symbol_by_name(name, elfinfo, local_func_matcher): # type: (str, ElfInfo, Callable[[Symbol], bool]) -> Optional[Symbol]
|
||||
def find_symbol_by_name(name: str, elfinfo: ElfInfo, local_func_matcher: Callable[[Symbol], bool]) -> Optional[Symbol]:
|
||||
"""
|
||||
Find an ELF symbol for the given name.
|
||||
local_func_matcher is a callback function which checks is the candidate local symbol is suitable.
|
||||
@@ -238,7 +234,7 @@ def find_symbol_by_name(name, elfinfo, local_func_matcher): # type: (str, ElfIn
|
||||
return local_candidate or global_candidate
|
||||
|
||||
|
||||
def match_local_source_func(rtl_filename, sym): # type: (str, Symbol) -> bool
|
||||
def match_local_source_func(rtl_filename: str, sym: Symbol) -> bool:
|
||||
"""
|
||||
Helper for match_rtl_funcs_to_symbols, checks if local symbol sym is a good candidate for the
|
||||
reference source (caller), based on the RTL file name.
|
||||
@@ -247,7 +243,7 @@ def match_local_source_func(rtl_filename, sym): # type: (str, Symbol) -> bool
|
||||
return rtl_filename_matches_sym_filename(rtl_filename, sym.filename)
|
||||
|
||||
|
||||
def match_local_target_func(rtl_filename, sym_from, sym): # type: (str, Symbol, Symbol) -> bool
|
||||
def match_local_target_func(rtl_filename: str, sym_from: Symbol, sym: Symbol) -> bool:
|
||||
"""
|
||||
Helper for match_rtl_funcs_to_symbols, checks if local symbol sym is a good candidate for the
|
||||
reference target (callee or referenced data), based on RTL filename of the source symbol
|
||||
@@ -263,9 +259,9 @@ def match_local_target_func(rtl_filename, sym_from, sym): # type: (str, Symbol,
|
||||
return rtl_filename_matches_sym_filename(rtl_filename, sym.filename)
|
||||
|
||||
|
||||
def match_rtl_funcs_to_symbols(rtl_functions, elfinfo): # type: (List[RtlFunction], ElfInfo) -> Tuple[List[Symbol], List[Reference]]
|
||||
symbols = [] # type: List[Symbol]
|
||||
refs = [] # type: List[Reference]
|
||||
def match_rtl_funcs_to_symbols(rtl_functions: List[RtlFunction], elfinfo: ElfInfo) -> Tuple[List[Symbol], List[Reference]]:
|
||||
symbols: List[Symbol] = []
|
||||
refs: List[Reference] = []
|
||||
|
||||
# General idea:
|
||||
# - iterate over RTL functions.
|
||||
@@ -308,17 +304,17 @@ def match_rtl_funcs_to_symbols(rtl_functions, elfinfo): # type: (List[RtlFuncti
|
||||
return symbols, refs
|
||||
|
||||
|
||||
def get_symbols_and_refs(rtl_list, elf_file): # type: (List[str], BinaryIO) -> Tuple[List[Symbol], List[Reference]]
|
||||
def get_symbols_and_refs(rtl_list: List[str], elf_file: BinaryIO) -> Tuple[List[Symbol], List[Reference]]:
|
||||
elfinfo = ElfInfo(elf_file)
|
||||
|
||||
rtl_functions = [] # type: List[RtlFunction]
|
||||
rtl_functions: List[RtlFunction] = []
|
||||
for file_name in rtl_list:
|
||||
load_rtl_file(file_name, file_name, rtl_functions)
|
||||
|
||||
return match_rtl_funcs_to_symbols(rtl_functions, elfinfo)
|
||||
|
||||
|
||||
def list_refs_from_to_sections(refs, from_sections, to_sections): # type: (List[Reference], List[str], List[str]) -> int
|
||||
def list_refs_from_to_sections(refs: List[Reference], from_sections: List[str], to_sections: List[str]) -> int:
|
||||
found = 0
|
||||
for ref in refs:
|
||||
if (not from_sections or ref.from_sym.section in from_sections) and \
|
||||
@@ -328,7 +324,7 @@ def list_refs_from_to_sections(refs, from_sections, to_sections): # type: (List
|
||||
return found
|
||||
|
||||
|
||||
def find_files_recursive(root_path, ext): # type: (str, str) -> Generator[str, None, None]
|
||||
def find_files_recursive(root_path: str, ext: str) -> Generator[str, None, None]:
|
||||
for root, _, files in os.walk(root_path):
|
||||
for basename in files:
|
||||
if basename.endswith(ext):
|
||||
@@ -336,7 +332,7 @@ def find_files_recursive(root_path, ext): # type: (str, str) -> Generator[str,
|
||||
yield filename
|
||||
|
||||
|
||||
def main():
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument(
|
||||
@@ -379,7 +375,7 @@ def main():
|
||||
args = parser.parse_args()
|
||||
if args.rtl_list:
|
||||
with open(args.rtl_list, 'r') as rtl_list_file:
|
||||
rtl_list = [line.strip for line in rtl_list_file]
|
||||
rtl_list = [line.strip() for line in rtl_list_file]
|
||||
else:
|
||||
if not args.rtl_dir:
|
||||
raise RuntimeError('Either --rtl-list or --rtl-dir must be specified')
|
||||
|
Reference in New Issue
Block a user