forked from OSchip/llvm-project
Minidump: use ThreadList parsing code from llvm/Object
llvm-svn: 360412
This commit is contained in:
parent
4dea1378ea
commit
6d40c29a7e
|
@ -89,13 +89,15 @@ UUID MinidumpParser::GetModuleUUID(const minidump::Module *module) {
|
|||
return UUID();
|
||||
}
|
||||
|
||||
llvm::ArrayRef<MinidumpThread> MinidumpParser::GetThreads() {
|
||||
llvm::ArrayRef<uint8_t> data = GetStream(StreamType::ThreadList);
|
||||
llvm::ArrayRef<minidump::Thread> MinidumpParser::GetThreads() {
|
||||
auto ExpectedThreads = GetMinidumpFile().getThreadList();
|
||||
if (ExpectedThreads)
|
||||
return *ExpectedThreads;
|
||||
|
||||
if (data.size() == 0)
|
||||
return llvm::None;
|
||||
|
||||
return MinidumpThread::ParseThreadList(data);
|
||||
LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD),
|
||||
ExpectedThreads.takeError(),
|
||||
"Failed to read thread list: {0}");
|
||||
return {};
|
||||
}
|
||||
|
||||
llvm::ArrayRef<uint8_t>
|
||||
|
@ -106,19 +108,19 @@ MinidumpParser::GetThreadContext(const LocationDescriptor &location) {
|
|||
}
|
||||
|
||||
llvm::ArrayRef<uint8_t>
|
||||
MinidumpParser::GetThreadContext(const MinidumpThread &td) {
|
||||
return GetThreadContext(td.thread_context);
|
||||
MinidumpParser::GetThreadContext(const minidump::Thread &td) {
|
||||
return GetThreadContext(td.Context);
|
||||
}
|
||||
|
||||
llvm::ArrayRef<uint8_t>
|
||||
MinidumpParser::GetThreadContextWow64(const MinidumpThread &td) {
|
||||
MinidumpParser::GetThreadContextWow64(const minidump::Thread &td) {
|
||||
// On Windows, a 32-bit process can run on a 64-bit machine under WOW64. If
|
||||
// the minidump was captured with a 64-bit debugger, then the CONTEXT we just
|
||||
// grabbed from the mini_dump_thread is the one for the 64-bit "native"
|
||||
// process rather than the 32-bit "guest" process we care about. In this
|
||||
// case, we can get the 32-bit CONTEXT from the TEB (Thread Environment
|
||||
// Block) of the 64-bit process.
|
||||
auto teb_mem = GetMemory(td.teb, sizeof(TEB64));
|
||||
auto teb_mem = GetMemory(td.EnvironmentBlock, sizeof(TEB64));
|
||||
if (teb_mem.empty())
|
||||
return {};
|
||||
|
||||
|
@ -329,15 +331,14 @@ MinidumpParser::FindMemoryRange(lldb::addr_t addr) {
|
|||
return llvm::None;
|
||||
|
||||
if (!data.empty()) {
|
||||
llvm::ArrayRef<MinidumpMemoryDescriptor> memory_list =
|
||||
MinidumpMemoryDescriptor::ParseMemoryList(data);
|
||||
llvm::ArrayRef<MemoryDescriptor> memory_list = ParseMemoryList(data);
|
||||
|
||||
if (memory_list.empty())
|
||||
return llvm::None;
|
||||
|
||||
for (const auto &memory_desc : memory_list) {
|
||||
const LocationDescriptor &loc_desc = memory_desc.memory;
|
||||
const lldb::addr_t range_start = memory_desc.start_of_memory_range;
|
||||
const LocationDescriptor &loc_desc = memory_desc.Memory;
|
||||
const lldb::addr_t range_start = memory_desc.StartOfMemoryRange;
|
||||
const size_t range_size = loc_desc.DataSize;
|
||||
|
||||
if (loc_desc.RVA + loc_desc.DataSize > GetData().size())
|
||||
|
@ -452,16 +453,16 @@ CreateRegionsCacheFromMemoryList(MinidumpParser &parser,
|
|||
auto data = parser.GetStream(StreamType::MemoryList);
|
||||
if (data.empty())
|
||||
return false;
|
||||
auto memory_list = MinidumpMemoryDescriptor::ParseMemoryList(data);
|
||||
auto memory_list = ParseMemoryList(data);
|
||||
if (memory_list.empty())
|
||||
return false;
|
||||
regions.reserve(memory_list.size());
|
||||
for (const auto &memory_desc : memory_list) {
|
||||
if (memory_desc.memory.DataSize == 0)
|
||||
if (memory_desc.Memory.DataSize == 0)
|
||||
continue;
|
||||
MemoryRegionInfo region;
|
||||
region.GetRange().SetRangeBase(memory_desc.start_of_memory_range);
|
||||
region.GetRange().SetByteSize(memory_desc.memory.DataSize);
|
||||
region.GetRange().SetRangeBase(memory_desc.StartOfMemoryRange);
|
||||
region.GetRange().SetByteSize(memory_desc.Memory.DataSize);
|
||||
region.SetReadable(MemoryRegionInfo::eYes);
|
||||
region.SetMapped(MemoryRegionInfo::eYes);
|
||||
regions.push_back(region);
|
||||
|
|
|
@ -54,13 +54,13 @@ public:
|
|||
|
||||
UUID GetModuleUUID(const minidump::Module *module);
|
||||
|
||||
llvm::ArrayRef<MinidumpThread> GetThreads();
|
||||
llvm::ArrayRef<minidump::Thread> GetThreads();
|
||||
|
||||
llvm::ArrayRef<uint8_t> GetThreadContext(const LocationDescriptor &location);
|
||||
|
||||
llvm::ArrayRef<uint8_t> GetThreadContext(const MinidumpThread &td);
|
||||
llvm::ArrayRef<uint8_t> GetThreadContext(const minidump::Thread &td);
|
||||
|
||||
llvm::ArrayRef<uint8_t> GetThreadContextWow64(const MinidumpThread &td);
|
||||
llvm::ArrayRef<uint8_t> GetThreadContextWow64(const minidump::Thread &td);
|
||||
|
||||
ArchSpec GetArchitecture();
|
||||
|
||||
|
|
|
@ -14,33 +14,6 @@
|
|||
using namespace lldb_private;
|
||||
using namespace minidump;
|
||||
|
||||
// MinidumpThread
|
||||
const MinidumpThread *MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data) {
|
||||
const MinidumpThread *thread = nullptr;
|
||||
Status error = consumeObject(data, thread);
|
||||
if (error.Fail())
|
||||
return nullptr;
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
llvm::ArrayRef<MinidumpThread>
|
||||
MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) {
|
||||
const auto orig_size = data.size();
|
||||
const llvm::support::ulittle32_t *thread_count;
|
||||
Status error = consumeObject(data, thread_count);
|
||||
if (error.Fail() || *thread_count * sizeof(MinidumpThread) > data.size())
|
||||
return {};
|
||||
|
||||
// Compilers might end up padding an extra 4 bytes depending on how the
|
||||
// structure is padded by the compiler and the #pragma pack settings.
|
||||
if (4 + *thread_count * sizeof(MinidumpThread) < orig_size)
|
||||
data = data.drop_front(4);
|
||||
|
||||
return llvm::ArrayRef<MinidumpThread>(
|
||||
reinterpret_cast<const MinidumpThread *>(data.data()), *thread_count);
|
||||
}
|
||||
|
||||
// MinidumpMiscInfo
|
||||
const MinidumpMiscInfo *MinidumpMiscInfo::Parse(llvm::ArrayRef<uint8_t> &data) {
|
||||
const MinidumpMiscInfo *misc_info;
|
||||
|
@ -95,22 +68,22 @@ MinidumpExceptionStream::Parse(llvm::ArrayRef<uint8_t> &data) {
|
|||
return exception_stream;
|
||||
}
|
||||
|
||||
llvm::ArrayRef<MinidumpMemoryDescriptor>
|
||||
MinidumpMemoryDescriptor::ParseMemoryList(llvm::ArrayRef<uint8_t> &data) {
|
||||
llvm::ArrayRef<MemoryDescriptor>
|
||||
minidump::ParseMemoryList(llvm::ArrayRef<uint8_t> &data) {
|
||||
const auto orig_size = data.size();
|
||||
const llvm::support::ulittle32_t *mem_ranges_count;
|
||||
Status error = consumeObject(data, mem_ranges_count);
|
||||
if (error.Fail() ||
|
||||
*mem_ranges_count * sizeof(MinidumpMemoryDescriptor) > data.size())
|
||||
*mem_ranges_count * sizeof(MemoryDescriptor) > data.size())
|
||||
return {};
|
||||
|
||||
// Compilers might end up padding an extra 4 bytes depending on how the
|
||||
// structure is padded by the compiler and the #pragma pack settings.
|
||||
if (4 + *mem_ranges_count * sizeof(MinidumpMemoryDescriptor) < orig_size)
|
||||
if (4 + *mem_ranges_count * sizeof(MemoryDescriptor) < orig_size)
|
||||
data = data.drop_front(4);
|
||||
|
||||
return llvm::makeArrayRef(
|
||||
reinterpret_cast<const MinidumpMemoryDescriptor *>(data.data()),
|
||||
reinterpret_cast<const MemoryDescriptor *>(data.data()),
|
||||
*mem_ranges_count);
|
||||
}
|
||||
|
||||
|
|
|
@ -75,17 +75,7 @@ Status consumeObject(llvm::ArrayRef<uint8_t> &Buffer, const T *&Object) {
|
|||
return error;
|
||||
}
|
||||
|
||||
// Reference:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680384(v=vs.85).aspx
|
||||
struct MinidumpMemoryDescriptor {
|
||||
llvm::support::ulittle64_t start_of_memory_range;
|
||||
LocationDescriptor memory;
|
||||
|
||||
static llvm::ArrayRef<MinidumpMemoryDescriptor>
|
||||
ParseMemoryList(llvm::ArrayRef<uint8_t> &data);
|
||||
};
|
||||
static_assert(sizeof(MinidumpMemoryDescriptor) == 16,
|
||||
"sizeof MinidumpMemoryDescriptor is not correct!");
|
||||
llvm::ArrayRef<MemoryDescriptor> ParseMemoryList(llvm::ArrayRef<uint8_t> &data);
|
||||
|
||||
struct MinidumpMemoryDescriptor64 {
|
||||
llvm::support::ulittle64_t start_of_memory_range;
|
||||
|
@ -181,25 +171,6 @@ struct MinidumpMemoryInfo {
|
|||
static_assert(sizeof(MinidumpMemoryInfo) == 48,
|
||||
"sizeof MinidumpMemoryInfo is not correct!");
|
||||
|
||||
// Reference:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx
|
||||
struct MinidumpThread {
|
||||
llvm::support::ulittle32_t thread_id;
|
||||
llvm::support::ulittle32_t suspend_count;
|
||||
llvm::support::ulittle32_t priority_class;
|
||||
llvm::support::ulittle32_t priority;
|
||||
llvm::support::ulittle64_t teb;
|
||||
MinidumpMemoryDescriptor stack;
|
||||
LocationDescriptor thread_context;
|
||||
|
||||
static const MinidumpThread *Parse(llvm::ArrayRef<uint8_t> &data);
|
||||
|
||||
static llvm::ArrayRef<MinidumpThread>
|
||||
ParseThreadList(llvm::ArrayRef<uint8_t> &data);
|
||||
};
|
||||
static_assert(sizeof(MinidumpThread) == 48,
|
||||
"sizeof MinidumpThread is not correct!");
|
||||
|
||||
// TODO misc2, misc3 ?
|
||||
// Reference:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx
|
||||
|
|
|
@ -326,12 +326,12 @@ void ProcessMinidump::Clear() { Process::m_thread_list.Clear(); }
|
|||
|
||||
bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list,
|
||||
ThreadList &new_thread_list) {
|
||||
for (const MinidumpThread& thread : m_thread_list) {
|
||||
LocationDescriptor context_location = thread.thread_context;
|
||||
for (const minidump::Thread &thread : m_thread_list) {
|
||||
LocationDescriptor context_location = thread.Context;
|
||||
|
||||
// If the minidump contains an exception context, use it
|
||||
if (m_active_exception != nullptr &&
|
||||
m_active_exception->thread_id == thread.thread_id) {
|
||||
m_active_exception->thread_id == thread.ThreadId) {
|
||||
context_location = m_active_exception->thread_context;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ protected:
|
|||
private:
|
||||
FileSpec m_core_file;
|
||||
lldb::DataBufferSP m_core_data;
|
||||
llvm::ArrayRef<MinidumpThread> m_thread_list;
|
||||
llvm::ArrayRef<minidump::Thread> m_thread_list;
|
||||
const MinidumpExceptionStream *m_active_exception;
|
||||
lldb::CommandObjectSP m_command_sp;
|
||||
bool m_is_wow64;
|
||||
|
|
|
@ -33,9 +33,9 @@ using namespace lldb;
|
|||
using namespace lldb_private;
|
||||
using namespace minidump;
|
||||
|
||||
ThreadMinidump::ThreadMinidump(Process &process, const MinidumpThread &td,
|
||||
ThreadMinidump::ThreadMinidump(Process &process, const minidump::Thread &td,
|
||||
llvm::ArrayRef<uint8_t> gpregset_data)
|
||||
: Thread(process, td.thread_id), m_thread_reg_ctx_sp(),
|
||||
: Thread(process, td.ThreadId), m_thread_reg_ctx_sp(),
|
||||
m_gpregset_data(gpregset_data) {}
|
||||
|
||||
ThreadMinidump::~ThreadMinidump() {}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace minidump {
|
|||
|
||||
class ThreadMinidump : public Thread {
|
||||
public:
|
||||
ThreadMinidump(Process &process, const MinidumpThread &td,
|
||||
ThreadMinidump(Process &process, const minidump::Thread &td,
|
||||
llvm::ArrayRef<uint8_t> gpregset_data);
|
||||
|
||||
~ThreadMinidump() override;
|
||||
|
|
|
@ -91,14 +91,14 @@ Streams:
|
|||
|
||||
TEST_F(MinidumpParserTest, GetThreadsAndGetThreadContext) {
|
||||
SetUpData("linux-x86_64.dmp");
|
||||
llvm::ArrayRef<MinidumpThread> thread_list;
|
||||
llvm::ArrayRef<minidump::Thread> thread_list;
|
||||
|
||||
thread_list = parser->GetThreads();
|
||||
ASSERT_EQ(1UL, thread_list.size());
|
||||
|
||||
const MinidumpThread thread = thread_list[0];
|
||||
const minidump::Thread &thread = thread_list[0];
|
||||
|
||||
EXPECT_EQ(16001UL, thread.thread_id);
|
||||
EXPECT_EQ(16001UL, thread.ThreadId);
|
||||
|
||||
llvm::ArrayRef<uint8_t> context = parser->GetThreadContext(thread);
|
||||
EXPECT_EQ(1232UL, context.size());
|
||||
|
@ -108,12 +108,12 @@ TEST_F(MinidumpParserTest, GetThreadListNotPadded) {
|
|||
// Verify that we can load a thread list that doesn't have 4 bytes of padding
|
||||
// after the thread count.
|
||||
SetUpData("thread-list-not-padded.dmp");
|
||||
llvm::ArrayRef<MinidumpThread> thread_list;
|
||||
llvm::ArrayRef<minidump::Thread> thread_list;
|
||||
|
||||
thread_list = parser->GetThreads();
|
||||
ASSERT_EQ(2UL, thread_list.size());
|
||||
EXPECT_EQ(0x11223344UL, thread_list[0].thread_id);
|
||||
EXPECT_EQ(0x55667788UL, thread_list[1].thread_id);
|
||||
EXPECT_EQ(0x11223344UL, thread_list[0].ThreadId);
|
||||
EXPECT_EQ(0x55667788UL, thread_list[1].ThreadId);
|
||||
}
|
||||
|
||||
TEST_F(MinidumpParserTest, GetThreadListPadded) {
|
||||
|
@ -122,8 +122,8 @@ TEST_F(MinidumpParserTest, GetThreadListPadded) {
|
|||
SetUpData("thread-list-padded.dmp");
|
||||
auto thread_list = parser->GetThreads();
|
||||
ASSERT_EQ(2UL, thread_list.size());
|
||||
EXPECT_EQ(0x11223344UL, thread_list[0].thread_id);
|
||||
EXPECT_EQ(0x55667788UL, thread_list[1].thread_id);
|
||||
EXPECT_EQ(0x11223344UL, thread_list[0].ThreadId);
|
||||
EXPECT_EQ(0x55667788UL, thread_list[1].ThreadId);
|
||||
}
|
||||
|
||||
TEST_F(MinidumpParserTest, GetMemoryListNotPadded) {
|
||||
|
@ -460,8 +460,8 @@ TEST_F(MinidumpParserTest, GetPidWow64) {
|
|||
|
||||
TEST_F(MinidumpParserTest, GetThreadContext_x86_32) {
|
||||
SetUpData("linux-i386.dmp");
|
||||
llvm::ArrayRef<MinidumpThread> thread_list = parser->GetThreads();
|
||||
const MinidumpThread thread = thread_list[0];
|
||||
llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
|
||||
const minidump::Thread &thread = thread_list[0];
|
||||
llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));
|
||||
const MinidumpContext_x86_32 *context;
|
||||
EXPECT_TRUE(consumeObject(registers, context).Success());
|
||||
|
@ -491,8 +491,8 @@ TEST_F(MinidumpParserTest, GetThreadContext_x86_32) {
|
|||
|
||||
TEST_F(MinidumpParserTest, GetThreadContext_x86_64) {
|
||||
SetUpData("linux-x86_64.dmp");
|
||||
llvm::ArrayRef<MinidumpThread> thread_list = parser->GetThreads();
|
||||
const MinidumpThread thread = thread_list[0];
|
||||
llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
|
||||
const minidump::Thread &thread = thread_list[0];
|
||||
llvm::ArrayRef<uint8_t> registers(parser->GetThreadContext(thread));
|
||||
const MinidumpContext_x86_64 *context;
|
||||
EXPECT_TRUE(consumeObject(registers, context).Success());
|
||||
|
@ -526,8 +526,8 @@ TEST_F(MinidumpParserTest, GetThreadContext_x86_64) {
|
|||
|
||||
TEST_F(MinidumpParserTest, GetThreadContext_x86_32_wow64) {
|
||||
SetUpData("fizzbuzz_wow64.dmp");
|
||||
llvm::ArrayRef<MinidumpThread> thread_list = parser->GetThreads();
|
||||
const MinidumpThread thread = thread_list[0];
|
||||
llvm::ArrayRef<minidump::Thread> thread_list = parser->GetThreads();
|
||||
const minidump::Thread &thread = thread_list[0];
|
||||
llvm::ArrayRef<uint8_t> registers(parser->GetThreadContextWow64(thread));
|
||||
const MinidumpContext_x86_32 *context;
|
||||
EXPECT_TRUE(consumeObject(registers, context).Success());
|
||||
|
|
Loading…
Reference in New Issue