1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
# Copyright (c) Meta Platforms, Inc. and affiliates.
# SPDX-License-Identifier: LGPL-2.1-or-later
import os
from pathlib import Path
import tempfile
from drgn import (
DebugInfoOptions,
KmodSearchMethod,
MainModule,
Program,
RelocatableModule,
)
from drgn.helpers.linux.module import find_module
from tests import modifyenv
from tests.linux_kernel import LinuxKernelTestCase, skip_unless_have_test_kmod
def iter_proc_modules():
try:
f = open("/proc/modules", "r")
except FileNotFoundError:
return
with f:
for line in f:
tokens = line.split()
yield tokens[0], int(tokens[5], 16)
class TestDebugInfo(LinuxKernelTestCase):
def test_debug_info(self):
# This is actually two test cases squished into one to avoid indexing
# vmlinux another time.
prog = Program()
prog.set_kernel()
prog.set_enabled_debug_info_finders([])
with self.subTest("vmlinux_no_build_id"):
for module, _ in prog.loaded_modules():
if isinstance(module, MainModule):
module.build_id = None
break
else:
self.fail("main module not found")
prog.load_debug_info([self.prog.main_module().debug_file_path])
self.assertEqual(
prog.main_module().debug_file_path,
self.prog.main_module().debug_file_path,
)
with self.subTest("kmod_walk"), tempfile.TemporaryDirectory() as temp_dir:
temp_dir = Path(temp_dir)
found_modules = set()
for i, module in enumerate(self.prog.modules()):
if isinstance(module, RelocatableModule) and module.debug_file_path:
found_modules.add(module.name)
link = temp_dir / str(i) / (module.name + ".ko")
link.parent.mkdir()
link.symlink_to(module.debug_file_path)
modules = [
module
for module, _ in prog.loaded_modules()
if module.name in found_modules
]
prog.find_standard_debug_info(
modules,
options=DebugInfoOptions(
kernel_directories=(temp_dir,), try_kmod=KmodSearchMethod.WALK
),
)
for module in modules:
with self.subTest(module=module.name):
self.assertIsNotNone(module.debug_file_path)
class TestModule(LinuxKernelTestCase):
def test_loaded_modules(self):
expected = [("kernel", None), *iter_proc_modules()]
loaded_modules = []
for module, _ in self.prog.loaded_modules():
if isinstance(module, RelocatableModule):
loaded_modules.append((module.name, module.address))
else:
loaded_modules.append((module.name, None))
self.assertCountEqual(loaded_modules, expected)
@skip_unless_have_test_kmod
def test_find(self):
self.assertEqual(self.prog.main_module().name, "kernel")
for name, address in iter_proc_modules():
if name == "drgn_test":
self.assertEqual(
self.prog.relocatable_module(name, address).name, "drgn_test"
)
break
else:
self.fail("test module not found")
@skip_unless_have_test_kmod
def test_find_by_obj(self):
for module in self.prog.modules():
if module.name == "drgn_test":
break
else:
self.fail("test module not found")
module_obj = find_module(self.prog, "drgn_test")
self.assertEqual(self.prog.linux_kernel_loadable_module(module_obj), module)
self.assertEqual(
self.prog.linux_kernel_loadable_module(module_obj, create=True), module
)
def test_no_sys_module(self):
# Test that we get the same modules with and without using /sys/module.
def module_dict(prog):
return {
(module.name, module.address): (
module.address_range,
module.build_id,
dict(module.section_addresses),
)
for module, _ in prog.loaded_modules()
if isinstance(module, RelocatableModule)
}
use_sys_module = int(os.environ.get("DRGN_USE_SYS_MODULE", "1")) != 0
with modifyenv({"DRGN_USE_SYS_MODULE": str(int(not use_sys_module))}):
prog = Program()
prog.set_kernel()
if use_sys_module:
with_sys_module = module_dict(self.prog)
without_sys_module = module_dict(prog)
else:
with_sys_module = module_dict(prog)
without_sys_module = module_dict(self.prog)
self.assertEqual(with_sys_module, without_sys_module)
|