diff --git a/tools/pynuttx/nxgdb/fs.py b/tools/pynuttx/nxgdb/fs.py index 9a52d56dbd5..d281f40ed3b 100644 --- a/tools/pynuttx/nxgdb/fs.py +++ b/tools/pynuttx/nxgdb/fs.py @@ -30,12 +30,12 @@ from . import utils from .protocols import fs as p from .protocols.thread import Tcb -FSNODEFLAG_TYPE_MASK = utils.get_symbol_value("FSNODEFLAG_TYPE_MASK") +FSNODEFLAG_TYPE_MASK = 0x0000000F CONFIG_PSEUDOFS_FILE = utils.get_symbol_value("CONFIG_PSEUDOFS_FILE") CONFIG_PSEUDOFS_ATTRIBUTES = utils.get_symbol_value("CONFIG_PSEUDOFS_ATTRIBUTES") -CONFIG_FS_BACKTRACE = utils.get_symbol_value("CONFIG_FS_BACKTRACE") +CONFIG_FS_BACKTRACE = utils.get_field_nitems("struct fd", "f_backtrace") CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = utils.get_field_nitems( "struct fdlist", "fl_prefds" ) diff --git a/tools/pynuttx/nxgdb/utils.py b/tools/pynuttx/nxgdb/utils.py index c627382a52c..cff1f0d57de 100644 --- a/tools/pynuttx/nxgdb/utils.py +++ b/tools/pynuttx/nxgdb/utils.py @@ -41,6 +41,7 @@ g_symbol_cache = {} g_type_cache = {} g_macro_ctx = None g_backtrace_cache = {} +TypeOrStr = Union[gdb.Type, str] class Value(gdb.Value): @@ -240,6 +241,42 @@ def lookup_type(name, block=None) -> gdb.Type: return g_type_cache[key] +def get_fieldnames(t: TypeOrStr) -> List[str]: + """Return the field names of a type""" + if isinstance(t, str): + t = lookup_type(t) + + return [f.name for f in t.fields()] + + +def get_type_field(obj: Union[TypeOrStr, gdb.Value], field: str) -> gdb.Field: + """ + Get the type field descriptor from a type or string, or value object. + """ + + if isinstance(obj, str): + t = lookup_type(obj) + elif isinstance(obj, gdb.Type): + t = obj + elif isinstance(obj, gdb.Value): + t = obj.type + else: + raise gdb.GdbError(f"Unsupported type {type(obj)}") + + while t.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY, gdb.TYPE_CODE_TYPEDEF): + t = t.target() + + for f in t.fields(): + if f.name == field: + return f + + +def get_field_nitems(t: TypeOrStr, field: str) -> Union[int, None]: + """Return the array length of a field in type, or None if no such field""" + if field := get_type_field(t, field): + return nitems(field) + + long_type = lookup_type("long") # Common Helper Functions @@ -251,7 +288,7 @@ def get_long_type(): return long_type -def offset_of(typeobj: Union[gdb.Type, str], field: str) -> Union[int, None]: +def offset_of(typeobj: TypeOrStr, field: str) -> Union[int, None]: """Return the offset of a field in a structure""" if type(typeobj) is str: typeobj = gdb.lookup_type(typeobj) @@ -269,7 +306,7 @@ def offset_of(typeobj: Union[gdb.Type, str], field: str) -> Union[int, None]: def container_of( - ptr: Union[gdb.Value, int], typeobj: Union[gdb.Type, str], member: str + ptr: Union[gdb.Value, int], typeobj: TypeOrStr, member: str ) -> gdb.Value: """ Return a pointer to the containing data structure. @@ -433,26 +470,18 @@ def get_symbol_value(name, locspec="nx_start", cacheable=True): return value -def get_field(val, key, default=None): - """Get a field from a gdb.Value, return default if key not found""" +def get_field(obj: gdb.Value, field: Union[str, gdb.Field], default=None) -> gdb.Value: + """ + Get a field value from a gdb.Value, return default if field is not found. + """ try: - return val[key] if val else default + return obj[field] if obj else default except gdb.error: return default -def has_field(obj: Union[gdb.Type, gdb.Value], key): - if isinstance(obj, gdb.Type): - t = obj - elif isinstance(obj, gdb.Value): - t = obj.type - else: - raise gdb.GdbError(f"Unsupported type {type(obj)}") - - while t.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY, gdb.TYPE_CODE_TYPEDEF): - t = t.target() - - return any(f.name == key for f in t.fields()) +def has_field(obj: Union[TypeOrStr, gdb.Value], field): + return get_type_field(obj, field) is not None def get_bytes(val, size): @@ -522,7 +551,7 @@ def alias(name, command): pass -def nitems(array): +def nitems(array: Union[gdb.Field, gdb.Type]) -> int: array_type = array.type element_type = array_type.target() element_size = element_type.sizeof