diff options
author | Yabin Cui <yabinc@google.com> | 2020-11-25 15:37:38 -0800 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2020-11-25 15:55:31 -0800 |
commit | f3da1edd7d18db0c89c02c786cbd5eb76c0c1425 (patch) | |
tree | af4f2e6635dd42f62af77d6bb06653b322b666c4 /simpleperf/dso_test.cpp | |
parent | dacfcca550b5d72ffb08a6d1f0ac30fda8243aaf (diff) | |
download | extras-f3da1edd7d18db0c89c02c786cbd5eb76c0c1425.tar.gz |
simpleperf: fix symbolization for kernel modules.
Simpleperf makes a wrong assumption that the kernel always load
.text section of a kernel module at the start of its module memory.
This can map an ip addr of a module to a wrong symbol.
To fix it:
1. In KernelModuleDso, calculate min_vaddr and memory_offset, which
are used to do the conversion in IpToVaddrInFile().
2. Change record_file_reader/writer to store min_vaddr and memory_offset
of KernelModuleDso in the recording file.
3. To get module start addresses, Use CheckKernelSymbolAddress() in
GetLoadedModules().
Bug: 174076407
Test: run simpleperf_unit_test.
Test: run simpleperf manually to check symbols of kernel modules.
Change-Id: I2498564f78dcc34761c5fe3ae9ffa6b88a98a048
Diffstat (limited to 'simpleperf/dso_test.cpp')
-rw-r--r-- | simpleperf/dso_test.cpp | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/simpleperf/dso_test.cpp b/simpleperf/dso_test.cpp index 96663d6b..331353f8 100644 --- a/simpleperf/dso_test.cpp +++ b/simpleperf/dso_test.cpp @@ -257,10 +257,42 @@ TEST(dso, kernel_module) { std::vector<std::pair<std::string, BuildId>> build_ids; build_ids.emplace_back(ELF_FILE, BuildId(ELF_FILE_BUILD_ID)); Dso::SetBuildIds(build_ids); - std::unique_ptr<Dso> dso = Dso::CreateDso(DSO_KERNEL_MODULE, ELF_FILE, false); + std::unique_ptr<Dso> kernel_dso = Dso::CreateDso(DSO_KERNEL, DEFAULT_KERNEL_MMAP_NAME); + ASSERT_TRUE(kernel_dso); + std::unique_ptr<Dso> dso = Dso::CreateKernelModuleDso(ELF_FILE, 0, 0, kernel_dso.get()); ASSERT_EQ(dso->GetDebugFilePath(), GetTestData(ELF_FILE)); } +TEST(dso, kernel_module_CalculateMinVaddr) { + // Create fake Dso objects. + auto kernel_dso = Dso::CreateDso(DSO_KERNEL, DEFAULT_KERNEL_MMAP_NAME); + ASSERT_TRUE(kernel_dso); + const uint64_t module_memory_start = 0xffffffa9bc790000ULL; + const uint64_t module_memory_size = 0x8d7000ULL; + auto module_dso = + Dso::CreateKernelModuleDso("fake_module.ko", module_memory_start, + module_memory_start + module_memory_size, kernel_dso.get()); + ASSERT_TRUE(module_dso); + + // Provide symbol info for calculating min vaddr. + std::vector<Symbol> kernel_symbols; + kernel_symbols.emplace_back("fake_module_function [fake_module]", 0xffffffa9bc7a64e8ULL, 0x60c); + kernel_dso->SetSymbols(&kernel_symbols); + std::vector<Symbol> module_symbols; + module_symbols.emplace_back("fake_module_function", 0x144e8, 0x60c); + module_dso->SetSymbols(&module_symbols); + + // Calculate min vaddr. + uint64_t min_vaddr; + uint64_t memory_offset; + module_dso->GetMinExecutableVaddr(&min_vaddr, &memory_offset); + ASSERT_EQ(min_vaddr, 0x144e8); + ASSERT_EQ(memory_offset, 0x164e8); + + // Use min vaddr in IpToVaddrInFile(). + ASSERT_EQ(module_dso->IpToVaddrInFile(0xffffffa9bc7a64e8ULL, module_memory_start, 0), 0x144e8); +} + TEST(dso, symbol_map_file) { auto dso = Dso::CreateDso(DSO_SYMBOL_MAP_FILE, "perf-123.map"); ASSERT_TRUE(dso); |