nxgdb/fs: fix exception when failed to parse symbol

Parse struct fields to determine array length.

Signed-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
xuxingliang
2025-01-14 22:26:26 +08:00
committed by Xiang Xiao
parent 5aa45e328e
commit 00304a18ed
2 changed files with 49 additions and 20 deletions
+2 -2
View File
@@ -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"
)
+47 -18
View File
@@ -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