[Lldb-commits] [lldb] [lldb][elf-core] Populate memory region names from NT_FILE (PR #212666)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Jul 28 19:53:20 PDT 2026
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
More information about the lldb-commits
mailing list