llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Chen Li (thechenli) <details> <summary>Changes</summary> ## Summary `ProcessElfCore` already parses `NT_FILE`, but its cached `PT_LOAD` memory-region entries retain only permissions. As a result, memory-region queries cannot report their backing filenames. - retain the pathname from an exact-matching `NT_FILE` entry alongside each cached region permission set - populate names after all program headers are parsed, making the result independent of `PT_LOAD` and `PT_NOTE` ordering - return the cached name from `DoGetMemoryRegionInfo`, including for file-backed mappings with `p_filesz == 0` - add API coverage for a zero-file-size HSACO-style mapping and ensure the adjacent unmapped range remains unnamed ## Testing - `ninja -C build -j64 lldb yaml2obj lldb-api-test-deps` - `build/bin/llvm-lit -sv lldb/test/API/functionalities/postmortem/elf-core` (4/4 passed) in lldb after ``` (lldb) memory region 0x7fc4f25fd000 [0x00007fc4f25fd000-0x00007fc4f2600000) r-- /tmp/aot_inductor_loaded_modelaCZzUI/ckq4hskzrtwkbxruge7ofytm2zmahqgcizkszojgcp3eepdubxc2.hsaco ``` before ``` (lldb) memory region 0x7fc4f25fd000 [0x00007fc4f25fd000-0x00007fc4f2600000) r-- ``` --- Full diff: https://github.com/llvm/llvm-project/pull/212666.diff 4 Files Affected: - (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp (+35-13) - (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.h (+17-4) - (modified) lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py (+35) - (added) lldb/test/API/functionalities/postmortem/elf-core/elf-NT_FILE-memory-region.yaml (+24) ``````````diff diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 4cc760de54a5c..aca4133f71e1d 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -8,6 +8,7 @@ #include <cstdlib> +#include <map> #include <memory> #include "lldb/Core/Module.h" @@ -139,8 +140,8 @@ lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment( ((header.p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) | ((header.p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u); - m_core_range_infos.Append( - VMRangeToPermissions::Entry(addr, header.p_memsz, permissions)); + m_core_range_infos.Append(VMRangeToPermissionsAndName::Entry( + addr, header.p_memsz, PermissionsAndName{permissions, {}})); return addr; } @@ -228,6 +229,8 @@ Status ProcessElfCore::DoLoadCore() { m_core_tag_ranges.Sort(); } + UpdateMemoryRegionNames(); + // Ensure we found at least one thread that was stopped on a signal. bool siginfo_signal_found = false; bool prstatus_signal_found = false; @@ -316,6 +319,24 @@ void ProcessElfCore::UpdateBuildIdForNTFileEntries() { } } +void ProcessElfCore::UpdateMemoryRegionNames() { + using AddressRange = std::pair<lldb::addr_t, lldb::addr_t>; + std::map<AddressRange, const std::string *> nt_file_names; + for (const NT_FILE_Entry &file_entry : m_nt_file_entries) { + nt_file_names.try_emplace({file_entry.start, file_entry.end}, + &file_entry.path); + } + + for (size_t i = 0; i < m_core_range_infos.GetSize(); ++i) { + VMRangeToPermissionsAndName::Entry *range_entry = + m_core_range_infos.GetMutableEntryAtIndex(i); + auto name = nt_file_names.find( + {range_entry->GetRangeBase(), range_entry->GetRangeEnd()}); + if (name != nt_file_names.end()) + range_entry->data.name = *name->second; + } +} + /// Correctly create a FileSpec from a path found in a core file. /// /// This method will guess the path style more intelligently that specifying @@ -466,13 +487,13 @@ size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size, Status ProcessElfCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo ®ion_info) { region_info.Clear(); - const VMRangeToPermissions::Entry *permission_entry = + const VMRangeToPermissionsAndName::Entry *range_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); - if (permission_entry) { - if (permission_entry->Contains(load_addr)) { - region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); - region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); - const Flags permissions(permission_entry->data); + if (range_entry) { + if (range_entry->Contains(load_addr)) { + region_info.GetRange().SetRangeBase(range_entry->GetRangeBase()); + region_info.GetRange().SetRangeEnd(range_entry->GetRangeEnd()); + const Flags permissions(range_entry->data.permissions); region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable) ? eLazyBoolYes : eLazyBoolNo); @@ -483,18 +504,19 @@ Status ProcessElfCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr, ? eLazyBoolYes : eLazyBoolNo); region_info.SetMapped(eLazyBoolYes); + if (!range_entry->data.name.empty()) + region_info.SetName(range_entry->data.name.c_str()); // A region is memory tagged if there is a memory tag segment that covers // the exact same range. region_info.SetMemoryTagged(eLazyBoolNo); const VMRangeToFileOffset::Entry *tag_entry = - m_core_tag_ranges.FindEntryStartsAt(permission_entry->GetRangeBase()); - if (tag_entry && - tag_entry->GetRangeEnd() == permission_entry->GetRangeEnd()) + m_core_tag_ranges.FindEntryStartsAt(range_entry->GetRangeBase()); + if (tag_entry && tag_entry->GetRangeEnd() == range_entry->GetRangeEnd()) region_info.SetMemoryTagged(eLazyBoolYes); - } else if (load_addr < permission_entry->GetRangeBase()) { + } else if (load_addr < range_entry->GetRangeBase()) { region_info.GetRange().SetRangeBase(load_addr); - region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); + region_info.GetRange().SetRangeEnd(range_entry->GetRangeBase()); region_info.SetReadable(eLazyBoolNo); region_info.SetWritable(eLazyBoolNo); region_info.SetExecutable(eLazyBoolNo); diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h index 846d8cb91cadf..45a89bc6d5b33 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -120,12 +120,22 @@ class ProcessElfCore : public lldb_private::PostMortemProcess { std::string path; }; + struct PermissionsAndName { + uint32_t permissions = 0; + std::string name; + + bool operator<(const PermissionsAndName &rhs) const { + return permissions < rhs.permissions; + } + }; + // For ProcessElfCore only typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange; typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange> VMRangeToFileOffset; - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> - VMRangeToPermissions; + typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, + PermissionsAndName> + VMRangeToPermissionsAndName; lldb::ModuleSP m_core_module_sp; std::string m_dyld_plugin_name; @@ -142,8 +152,8 @@ class ProcessElfCore : public lldb_private::PostMortemProcess { // Address ranges found in the core VMRangeToFileOffset m_core_aranges; - // Permissions for all ranges - VMRangeToPermissions m_core_range_infos; + // Permissions and names for all ranges + VMRangeToPermissionsAndName m_core_range_infos; // Memory tag ranges found in the core VMRangeToFileOffset m_core_tag_ranges; @@ -170,6 +180,9 @@ class ProcessElfCore : public lldb_private::PostMortemProcess { // Populate gnu uuid for each NT_FILE entry void UpdateBuildIdForNTFileEntries(); + // Populate memory region names from NT_FILE entries. + void UpdateMemoryRegionNames(); + bool FindModuleUUID(lldb_private::ModuleSpec &spec) override; // Extract the executable module spec for the executable in this core file. diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py index f211ac4454209..d4e504096ec3a 100644 --- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py +++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -1437,6 +1437,41 @@ def do_test(self, filename, pid, region_count, thread_name): self.dbg.DeleteTarget(target) + @skipIfLLVMTargetMissing("X86") + @skipIfWindows + def test_memory_region_name_from_nt_file(self): + yaml_path = self.getSourcePath("elf-NT_FILE-memory-region.yaml") + core_path = self.getBuildArtifact("elf-NT_FILE-memory-region.core") + self.yaml2obj(yaml_path, core_path) + target = self.dbg.CreateTarget(None) + process = target.LoadCore(core_path) + self.assertTrue(process.IsValid()) + + region = lldb.SBMemoryRegionInfo() + self.assertSuccess(process.GetMemoryRegionInfo(0x400000, region)) + self.assertEqual(region.GetRegionBase(), 0x400000) + self.assertEqual(region.GetRegionEnd(), 0x401000) + self.assertTrue(region.IsMapped()) + self.assertTrue(region.IsReadable()) + self.assertFalse(region.IsWritable()) + self.assertTrue(region.IsExecutable()) + self.assertEqual(region.GetName(), "/tmp/kernel.hsaco") + + regions = process.GetMemoryRegions() + self.assertEqual(regions.GetSize(), 1) + listed_region = lldb.SBMemoryRegionInfo() + self.assertTrue( + regions.GetMemoryRegionContainingAddress(0x400000, listed_region) + ) + self.assertEqual(listed_region, region) + + unmapped_region = lldb.SBMemoryRegionInfo() + self.assertSuccess(process.GetMemoryRegionInfo(0x401000, unmapped_region)) + self.assertFalse(unmapped_region.IsMapped()) + self.assertIsNone(unmapped_region.GetName()) + + self.dbg.DeleteTarget(target) + @skipIfLLVMTargetMissing("X86") @skipIfWindows def test_exe_name_extraction_nt_file(self): diff --git a/lldb/test/API/functionalities/postmortem/elf-core/elf-NT_FILE-memory-region.yaml b/lldb/test/API/functionalities/postmortem/elf-core/elf-NT_FILE-memory-region.yaml new file mode 100644 index 0000000000000..6c61edeb3f8a6 --- /dev/null +++ b/lldb/test/API/functionalities/postmortem/elf-core/elf-NT_FILE-memory-region.yaml @@ -0,0 +1,24 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_CORE + Machine: EM_X86_64 + OSABI: ELFOSABI_LINUX +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_R, PF_X ] + VAddr: 0x400000 + Align: 0x1000 + FileSize: 0 + MemSize: 0x1000 + - Type: PT_NOTE + FirstSec: .note + LastSec: .note +Sections: + - Name: .note + Type: SHT_NOTE + Notes: + - Name: CORE + Type: NT_FILE + Desc: 010000000000000000100000000000000000400000000000001040000000000000000000000000002f746d702f6b65726e656c2e687361636f00 `````````` </details> https://github.com/llvm/llvm-project/pull/212666 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
