Merge pull request #1727 from volatilityfoundation/kallsyms_fixes_round2

Hopefully final round of kallsym fixes
This commit is contained in:
ikelos
2025-03-20 18:26:23 +00:00
committed by GitHub
3 changed files with 61 additions and 13 deletions
@@ -73,6 +73,9 @@ class Kallsyms(plugins.PluginInterface):
# resulting in incorrect values. Unfortunately, there isn't much that can be done
# in such cases.
# See comments on .init.scratch in arch/x86/kernel/vmlinux.lds.S for details
if not kassymbol or not kassymbol.size:
return renderers.NotAvailableValue()
return kassymbol.size if kassymbol.size >= 0 else renderers.NotAvailableValue()
def _generator(self):
@@ -95,6 +98,7 @@ class Kallsyms(plugins.PluginInterface):
include_core = include_modules = include_ftrace = include_bpf = True
symbol_generators = []
if include_core:
symbol_generators.append(kas.get_core_symbols())
if include_modules:
@@ -114,11 +118,17 @@ class Kallsyms(plugins.PluginInterface):
# the last symbol, resulting in a negative size.
# See comments on .init.scratch in arch/x86/kernel/vmlinux.lds.S for details
symbol_size = self._get_symbol_size(kassymbol)
if kassymbol.exported is None:
exported = renderers.NotAvailableValue()
else:
exported = kassymbol.exported
fields = (
format_hints.Hex(kassymbol.address),
kassymbol.type,
kassymbol.type or renderers.NotAvailableValue(),
symbol_size,
kassymbol.exported,
exported,
kassymbol.subsystem,
kassymbol.module_name,
kassymbol.name,
@@ -3053,7 +3053,7 @@ class kernel_symbol(objects.StructType):
long_mask = (1 << layer.bits_per_register) - 1
return (self.vol.offset + off) & long_mask
def get_name(self) -> str:
def _do_get_name(self) -> str:
if self.has_member("name_offset"):
# kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
# See 7290d58095712a89f845e1bca05334796dd49ed2
@@ -3073,7 +3073,13 @@ class kernel_symbol(objects.StructType):
return name_bytes.decode("utf-8", errors="ignore")
def get_value(self) -> int:
def get_name(self) -> Optional[str]:
try:
return self._do_get_name()
except exceptions.InvalidAddressException:
return None
def _do_get_value(self) -> int:
if self.has_member("value_offset"):
# kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
# See 7290d58095712a89f845e1bca05334796dd49ed2
@@ -3084,7 +3090,13 @@ class kernel_symbol(objects.StructType):
raise AttributeError("Unsupported kernel_symbol type implementation")
def get_namespace(self) -> str:
def get_value(self) -> Optional[int]:
try:
return self._do_get_value()
except exceptions.InvalidAddressException:
return None
def _do_get_namespace(self) -> str:
if self.has_member("namespace_offset"):
# kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
# See 7290d58095712a89f845e1bca05334796dd49ed2
@@ -3103,3 +3115,9 @@ class kernel_symbol(objects.StructType):
namespace_bytes = namespace_bytes[:idx]
return namespace_bytes.decode("utf-8", errors="ignore")
def get_namespace(self) -> Optional[str]:
try:
return self._do_get_namespace()
except exceptions.InvalidAddressException:
return None
@@ -186,7 +186,10 @@ class KASSymbol(KASSymbolBasic):
# If lowercase, the symbol is usually local; if uppercase, the symbol is
# global (external). There are however a few lowercase symbols that are shown
# for special global symbols ("u", "v" and "w").
self.exported = bool(self.type.isupper() or self.type in ("u", "v", "w"))
if self.type:
self.exported = bool(self.type.isupper() or self.type in ("u", "v", "w"))
else:
self.exported = None
@functools.cached_property
def type_description(self) -> Optional[str]:
@@ -200,10 +203,12 @@ class KASSymbol(KASSymbolBasic):
if symbol_type_description:
return symbol_type_description
# Otherwise, use the lowercase version
symbol_type_description = linux_constants.NM_TYPES_DESC.get(
self.type.lower(), None
)
if self.type:
# Otherwise, use the lowercase version
symbol_type_description = linux_constants.NM_TYPES_DESC.get(
self.type.lower(), None
)
return symbol_type_description
@@ -767,7 +772,13 @@ class Kallsyms(interfaces.configuration.VersionableInterface):
self._kas_config.stop_ksymtab,
)
return kernel_symbol is not None and kernel_symbol.get_value() == address
if kernel_symbol is not None:
if hasattr(kernel_symbol, "get_value"):
return kernel_symbol.get_value() == address
else:
return kernel_symbol.vol.offset == address
return None
def _elfsym_to_kassymbol(
self,
@@ -1094,7 +1105,9 @@ class Kallsyms(interfaces.configuration.VersionableInterface):
name: str,
other: str,
) -> int:
if name == other:
if name is None or other is None:
return None
elif name == other:
return 0
elif name < other:
return -1
@@ -1315,7 +1328,14 @@ class Kallsyms(interfaces.configuration.VersionableInterface):
# Even when bpf_jit_kallsyms is disabled (/proc/sys/net/core/bpf_jit_kallsyms = 0),
# this function will still be able to gather the symbols.
bpf_kallsyms_list = vmlinux.object_from_symbol("bpf_kallsyms")
try:
bpf_kallsyms_list = vmlinux.object_from_symbol("bpf_kallsyms")
except exceptions.SymbolError:
vollog.debug(
"`bpf_kallsyms` symbol not present in the symbol table. Cannot proceed."
)
return None
for elem in bpf_kallsyms_list.to_list(list_type_symname, list_head_member):
try:
# See kernel's bpf_get_kallsym()