In https://reviews.llvm.org/D39681, we started using a map instead passing a long list of register sets to the ppc64le register context. However, existing register contexts were still using the old method. This converts the remaining register contexts to use this approach. While doing that, I've had to modify the approach a bit: - the general purpose register set is still kept as a separate field, because this one is always present, and it's parsing is somewhat different than that of other register sets. - since the same register sets have different IDs on different operating systems, but we use the same register context class to represent different register sets, I've needed to add a layer of indirection to translate os-specific constants (e.g. NETBSD::NT_AMD64_FPREGS) into more generic terms (e.g. floating point register set). While slightly more complicated, this setup allows for better separation of concerns. The parsing code in ProcessElfCore can focus on parsing OS-specific core file notes, and can completely ignore architecture-specific register sets (by just storing any unrecognised notes in a map). These notes will then be passed on to the architecture-specific register context, which can just deal with architecture specifics, because the OS-specific note types are hidden in a register set description map. This way, adding an register set, which is already supported on other OSes, to a new OS, should in most cases be as simple as adding a new entry into the register set description map. Differential Revision: https://reviews.llvm.org/D40133 llvm-svn: 319162
111 lines
3.5 KiB
C++
111 lines
3.5 KiB
C++
//===-- ThreadMinidump.cpp --------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Project includes
|
|
#include "ThreadMinidump.h"
|
|
#include "ProcessMinidump.h"
|
|
|
|
#include "RegisterContextMinidump_x86_32.h"
|
|
#include "RegisterContextMinidump_x86_64.h"
|
|
|
|
// Other libraries and framework includes
|
|
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
|
|
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
|
#include "Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h"
|
|
#include "Plugins/Process/elf-core/RegisterUtilities.h"
|
|
|
|
#include "lldb/Target/RegisterContext.h"
|
|
#include "lldb/Target/StopInfo.h"
|
|
#include "lldb/Target/Target.h"
|
|
#include "lldb/Target/Unwind.h"
|
|
#include "lldb/Utility/DataExtractor.h"
|
|
#include "lldb/Utility/Log.h"
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace minidump;
|
|
|
|
ThreadMinidump::ThreadMinidump(Process &process, const MinidumpThread &td,
|
|
llvm::ArrayRef<uint8_t> gpregset_data)
|
|
: Thread(process, td.thread_id), m_thread_reg_ctx_sp(),
|
|
m_gpregset_data(gpregset_data) {}
|
|
|
|
ThreadMinidump::~ThreadMinidump() {}
|
|
|
|
void ThreadMinidump::RefreshStateAfterStop() {}
|
|
|
|
RegisterContextSP ThreadMinidump::GetRegisterContext() {
|
|
if (!m_reg_context_sp) {
|
|
m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
|
|
}
|
|
return m_reg_context_sp;
|
|
}
|
|
|
|
RegisterContextSP
|
|
ThreadMinidump::CreateRegisterContextForFrame(StackFrame *frame) {
|
|
RegisterContextSP reg_ctx_sp;
|
|
uint32_t concrete_frame_idx = 0;
|
|
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
|
|
|
|
if (frame)
|
|
concrete_frame_idx = frame->GetConcreteFrameIndex();
|
|
|
|
if (concrete_frame_idx == 0) {
|
|
if (m_thread_reg_ctx_sp)
|
|
return m_thread_reg_ctx_sp;
|
|
|
|
ProcessMinidump *process =
|
|
static_cast<ProcessMinidump *>(GetProcess().get());
|
|
ArchSpec arch = process->GetArchitecture();
|
|
RegisterInfoInterface *reg_interface = nullptr;
|
|
|
|
// TODO write other register contexts and add them here
|
|
switch (arch.GetMachine()) {
|
|
case llvm::Triple::x86: {
|
|
reg_interface = new RegisterContextLinux_i386(arch);
|
|
lldb::DataBufferSP buf =
|
|
ConvertMinidumpContext_x86_32(m_gpregset_data, reg_interface);
|
|
DataExtractor gpregset(buf, lldb::eByteOrderLittle, 4);
|
|
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64(
|
|
*this, reg_interface, gpregset, {}));
|
|
break;
|
|
}
|
|
case llvm::Triple::x86_64: {
|
|
reg_interface = new RegisterContextLinux_x86_64(arch);
|
|
lldb::DataBufferSP buf =
|
|
ConvertMinidumpContext_x86_64(m_gpregset_data, reg_interface);
|
|
DataExtractor gpregset(buf, lldb::eByteOrderLittle, 8);
|
|
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64(
|
|
*this, reg_interface, gpregset, {}));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!reg_interface) {
|
|
if (log)
|
|
log->Printf("elf-core::%s:: Architecture(%d) not supported",
|
|
__FUNCTION__, arch.GetMachine());
|
|
assert(false && "Architecture not supported");
|
|
}
|
|
|
|
reg_ctx_sp = m_thread_reg_ctx_sp;
|
|
} else if (m_unwinder_ap) {
|
|
reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame);
|
|
}
|
|
|
|
return reg_ctx_sp;
|
|
}
|
|
|
|
bool ThreadMinidump::CalculateStopInfo() { return false; }
|