Skip to content

Commit b443dd5

Browse files
Fix for stack memory access from core file (#40)
* Fix for stack memory access in core file
1 parent b776a1d commit b443dd5

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,33 @@ ProcessAIXCore::~ProcessAIXCore() {
9494
Finalize(true /* destructing */);
9595
}
9696

97+
lldb::addr_t ProcessAIXCore::AddAddressRanges(AIXCORE::AIXCore64Header header) {
98+
const lldb::addr_t addr = header.StackBaseAddr;
99+
FileRange file_range(header.StackOffset, header.StackSize);
100+
VMRangeToFileOffset::Entry range_entry(addr, header.StackSize, file_range);
101+
102+
if (header.StackSize > 0) {
103+
VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
104+
if (last_entry &&
105+
last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
106+
last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
107+
last_entry->GetByteSize() == last_entry->data.GetByteSize()) {
108+
last_entry->SetRangeEnd(range_entry.GetRangeEnd());
109+
last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
110+
} else {
111+
m_core_aranges.Append(range_entry);
112+
}
113+
}
114+
115+
const uint32_t permissions = lldb::ePermissionsReadable |
116+
lldb::ePermissionsWritable;
117+
118+
m_core_range_infos.Append(
119+
VMRangeToPermissions::Entry(addr, header.StackSize, permissions));
120+
121+
return addr;
122+
}
123+
97124
bool ProcessAIXCore::CanDebug(lldb::TargetSP target_sp,
98125
bool plugin_specified_by_name) {
99126

@@ -170,6 +197,7 @@ Status ProcessAIXCore::DoLoadCore() {
170197
}
171198

172199
FileSpec file = m_core_module_sp->GetObjectFile()->GetFileSpec();
200+
Log *log = GetLog(LLDBLog::Process);
173201

174202
if (file) {
175203
const size_t header_size = sizeof(AIXCORE::AIXCore64Header);
@@ -180,6 +208,9 @@ Status ProcessAIXCore::DoLoadCore() {
180208
DataExtractor data(data_sp, lldb::eByteOrderBig, 4);
181209
lldb::offset_t data_offset = 0;
182210
m_aixcore_header.ParseCoreHeader(data, &data_offset);
211+
lldb::addr_t addr = AddAddressRanges(m_aixcore_header);
212+
if (addr == LLDB_INVALID_ADDRESS)
213+
LLDB_LOGF(log, "ProcessAIXCore: Invalid base address. Stack information will be limited");
183214
auto dyld = static_cast<DynamicLoaderAIXDYLD *>(GetDynamicLoader());
184215
dyld->FillCoreLoaderData(data, m_aixcore_header.LoaderOffset,
185216
m_aixcore_header.LoaderSize);
@@ -246,7 +277,48 @@ size_t ProcessAIXCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
246277
}
247278

248279
size_t ProcessAIXCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
249-
Status &error) { return 0; }
280+
Status &error) {
281+
ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
282+
if (core_objfile == nullptr)
283+
return 0;
284+
// Get the address range
285+
const VMRangeToFileOffset::Entry *address_range =
286+
m_core_aranges.FindEntryThatContains(addr);
287+
if (address_range == nullptr || address_range->GetRangeEnd() < addr) {
288+
error = Status::FromErrorStringWithFormat(
289+
"core file does not contain 0x%" PRIx64, addr);
290+
return 0;
291+
}
292+
293+
// Convert the address into core file offset
294+
const lldb::addr_t offset = addr - address_range->GetRangeBase();
295+
const lldb::addr_t file_start = address_range->data.GetRangeBase();
296+
const lldb::addr_t file_end = address_range->data.GetRangeEnd();
297+
size_t bytes_to_read = size; // Number of bytes to read from the core file
298+
size_t bytes_copied = 0; // Number of bytes actually read from the core file
299+
// Number of bytes available in the core file from the given address
300+
lldb::addr_t bytes_left = 0;
301+
302+
// Don't proceed if core file doesn't contain the actual data for this
303+
// address range.
304+
if (file_start == file_end)
305+
return 0;
306+
307+
// Figure out how many on-disk bytes remain in this segment starting at the
308+
// given offset
309+
if (file_end > file_start + offset)
310+
bytes_left = file_end - (file_start + offset);
311+
312+
if (bytes_to_read > bytes_left)
313+
bytes_to_read = bytes_left;
314+
315+
// If there is data available on the core file read it
316+
if (bytes_to_read)
317+
bytes_copied =
318+
core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
319+
320+
return bytes_copied;
321+
}
250322

251323
Status ProcessAIXCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
252324
MemoryRegionInfo &region_info) {

lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,22 @@ class ProcessAIXCore : public lldb_private::PostMortemProcess {
8585

8686
void ParseAIXCoreFile();
8787

88+
lldb::addr_t AddAddressRanges(AIXCORE::AIXCore64Header header);
8889

8990
private:
9091
lldb::ModuleSP m_core_module_sp;
9192
std::string m_dyld_plugin_name;
9293

94+
typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
95+
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange>
96+
VMRangeToFileOffset;
97+
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t>
98+
VMRangeToPermissions;
99+
100+
// Address ranges found in the core
101+
VMRangeToFileOffset m_core_aranges;
102+
VMRangeToPermissions m_core_range_infos;
103+
93104
// True if m_thread_contexts contains valid entries
94105
bool m_thread_data_valid = false;
95106
AIXCORE::AIXCore64Header m_aixcore_header;

0 commit comments

Comments
 (0)