Skip to content

Commit

Permalink
Implement GetMemoryRegionInfo for mini dumps.
Browse files Browse the repository at this point in the history
Differential Revision: http://reviews.llvm.org/D15218

llvm-svn: 254780
  • Loading branch information
amccarth-google committed Dec 4, 2015
1 parent 072bff8 commit 0c35cde
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 13 deletions.
3 changes: 2 additions & 1 deletion lldb/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
Expand Up @@ -39,7 +39,8 @@ SaveMiniDump(const lldb::ProcessSP &process_sp,
return false;
}
HANDLE file_handle = ::CreateFileW(wide_name.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
const auto result = ::MiniDumpWriteDump(process_handle, process_sp->GetID(), file_handle, MiniDumpNormal, NULL, NULL, NULL);
const auto result = ::MiniDumpWriteDump(process_handle, process_sp->GetID(), file_handle,
MiniDumpWithFullMemoryInfo, NULL, NULL, NULL);
::CloseHandle(file_handle);
::CloseHandle(process_handle);
if (!result)
Expand Down
23 changes: 23 additions & 0 deletions lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
Expand Up @@ -15,6 +15,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
Expand Down Expand Up @@ -74,4 +75,26 @@ ProcessWindows::GetImageInfoAddress()
return LLDB_INVALID_ADDRESS;
}

// The Windows page protection bits are NOT independent masks that can be bitwise-ORed
// together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE | PAGE_READ).
// To test for an access type, it's necessary to test for any of the bits that provide
// that access type.
bool
ProcessWindows::IsPageReadable(uint32_t protect)
{
return (protect & PAGE_NOACCESS) == 0;
}

bool
ProcessWindows::IsPageWritable(uint32_t protect)
{
return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
}

bool
ProcessWindows::IsPageExecutable(uint32_t protect)
{
return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0;
}

}
11 changes: 11 additions & 0 deletions lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
Expand Up @@ -34,6 +34,17 @@ class ProcessWindows : public lldb_private::Process
size_t PutSTDIN(const char *buf, size_t buf_size, lldb_private::Error &error) override;

lldb::addr_t GetImageInfoAddress() override;

protected:
// These decode the page protection bits.
static bool
IsPageReadable(uint32_t protect);

static bool
IsPageWritable(uint32_t protect);

static bool
IsPageExecutable(uint32_t protect);
};

}
Expand Down
Expand Up @@ -743,12 +743,13 @@ ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo &
error.GetError(), vm_addr);
return error;
}
bool readable = !(mem_info.Protect & PAGE_NOACCESS);
bool executable = mem_info.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
bool writable = mem_info.Protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOPY);
const bool readable = IsPageReadable(mem_info.Protect);
const bool executable = IsPageExecutable(mem_info.Protect);
const bool writable = IsPageWritable(mem_info.Protect);
info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);

error.SetError(::GetLastError(), eErrorTypeWin32);
WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: readable=%s, executable=%s, writable=%s",
BOOL_STR(readable), BOOL_STR(executable), BOOL_STR(writable));
Expand Down
Expand Up @@ -17,21 +17,22 @@
#include <memory>
#include <mutex>

#include "lldb/Core/PluginManager.h"
#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/UnixSignals.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ConvertUTF.h"
#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"

#include "ExceptionRecord.h"
#include "ThreadWinMiniDump.h"
Expand Down Expand Up @@ -272,6 +273,51 @@ ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Erro
return overlap;
}

Error
ProcessWinMiniDump::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info)
{
Error error;
size_t size;
const auto list = reinterpret_cast<const MINIDUMP_MEMORY_INFO_LIST *>(FindDumpStream(MemoryInfoListStream, &size));
if (list == nullptr || size < sizeof(MINIDUMP_MEMORY_INFO_LIST))
{
error.SetErrorString("the mini dump contains no memory range information");
return error;
}

if (list->SizeOfEntry < sizeof(MINIDUMP_MEMORY_INFO))
{
error.SetErrorString("the entries in the mini dump memory info list are smaller than expected");
return error;
}

if (size < list->SizeOfHeader + list->SizeOfEntry * list->NumberOfEntries)
{
error.SetErrorString("the mini dump memory info list is incomplete");
return error;
}

for (int i = 0; i < list->NumberOfEntries; ++i)
{
const auto entry = reinterpret_cast<const MINIDUMP_MEMORY_INFO *>(reinterpret_cast<const char *>(list) +
list->SizeOfHeader + i * list->SizeOfEntry);
const auto head = entry->BaseAddress;
const auto tail = head + entry->RegionSize;
if (head <= load_addr && load_addr < tail)
{
info.SetReadable(IsPageReadable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
info.SetWritable(IsPageWritable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
info.SetExecutable(IsPageExecutable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
return error;
}
}
// Note that the memory info list doesn't seem to contain ranges in kernel space,
// so if you're walking a stack that has kernel frames, the stack may appear
// truncated.
error.SetErrorString("address is not in a known range");
return error;
}

void
ProcessWinMiniDump::Clear()
{
Expand Down
Expand Up @@ -23,7 +23,7 @@ struct ThreadData;

class ProcessWinMiniDump : public lldb_private::ProcessWindows
{
public:
public:
static lldb::ProcessSP
CreateInstance (lldb::TargetSP target_sp,
lldb_private::Listener &listener,
Expand Down Expand Up @@ -84,15 +84,18 @@ class ProcessWinMiniDump : public lldb_private::ProcessWindows
lldb_private::ArchSpec
GetArchitecture();

protected:
lldb_private::Error
GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &range_info) override;

protected:
void
Clear();

bool
UpdateThreadList(lldb_private::ThreadList &old_thread_list,
lldb_private::ThreadList &new_thread_list) override;

private:
private:
// Describes a range of memory captured in the mini dump.
struct Range {
lldb::addr_t start; // virtual address of the beginning of the range
Expand Down

0 comments on commit 0c35cde

Please sign in to comment.