2013-08-23 13:46:38 -04:00
|
|
|
//===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===//
|
|
|
|
|
//
|
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
|
//
|
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
#include "lldb/Core/DataExtractor.h"
|
2014-11-25 16:00:58 -05:00
|
|
|
#include "lldb/Core/Log.h"
|
2013-08-23 13:46:38 -04:00
|
|
|
#include "lldb/Target/RegisterContext.h"
|
|
|
|
|
#include "lldb/Target/StopInfo.h"
|
|
|
|
|
#include "lldb/Target/Target.h"
|
|
|
|
|
#include "lldb/Target/Unwind.h"
|
|
|
|
|
|
|
|
|
|
#include "ThreadElfCore.h"
|
|
|
|
|
#include "ProcessElfCore.h"
|
2015-02-06 16:38:51 -05:00
|
|
|
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
|
|
|
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
|
|
|
|
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
|
|
|
|
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
|
|
|
|
|
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
|
2013-11-06 11:48:53 -05:00
|
|
|
#include "RegisterContextPOSIXCore_mips64.h"
|
2015-02-06 16:38:51 -05:00
|
|
|
#include "RegisterContextPOSIXCore_powerpc.h"
|
2013-11-06 11:48:53 -05:00
|
|
|
#include "RegisterContextPOSIXCore_x86_64.h"
|
2013-08-23 13:46:38 -04:00
|
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Construct a Thread object with given data
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
ThreadElfCore::ThreadElfCore (Process &process, tid_t tid,
|
|
|
|
|
const ThreadData &td) :
|
|
|
|
|
Thread(process, tid),
|
|
|
|
|
m_thread_name(td.name),
|
|
|
|
|
m_thread_reg_ctx_sp (),
|
|
|
|
|
m_signo(td.signo),
|
|
|
|
|
m_gpregset_data(td.gpregset),
|
2015-02-08 20:44:09 -05:00
|
|
|
m_fpregset_data(td.fpregset),
|
|
|
|
|
m_vregset_data(td.vregset)
|
2013-08-23 13:46:38 -04:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ThreadElfCore::~ThreadElfCore ()
|
|
|
|
|
{
|
|
|
|
|
DestroyThread();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ThreadElfCore::RefreshStateAfterStop()
|
|
|
|
|
{
|
|
|
|
|
GetRegisterContext()->InvalidateIfNeeded (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ThreadElfCore::ClearStackFrames ()
|
|
|
|
|
{
|
|
|
|
|
Unwind *unwinder = GetUnwinder ();
|
|
|
|
|
if (unwinder)
|
|
|
|
|
unwinder->Clear();
|
|
|
|
|
Thread::ClearStackFrames();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RegisterContextSP
|
|
|
|
|
ThreadElfCore::GetRegisterContext ()
|
|
|
|
|
{
|
|
|
|
|
if (m_reg_context_sp.get() == NULL) {
|
|
|
|
|
m_reg_context_sp = CreateRegisterContextForFrame (NULL);
|
|
|
|
|
}
|
|
|
|
|
return m_reg_context_sp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RegisterContextSP
|
|
|
|
|
ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
|
|
|
|
|
{
|
|
|
|
|
RegisterContextSP reg_ctx_sp;
|
|
|
|
|
uint32_t concrete_frame_idx = 0;
|
2014-11-25 16:00:58 -05:00
|
|
|
Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
|
2013-08-23 13:46:38 -04:00
|
|
|
|
|
|
|
|
if (frame)
|
|
|
|
|
concrete_frame_idx = frame->GetConcreteFrameIndex ();
|
|
|
|
|
|
|
|
|
|
if (concrete_frame_idx == 0)
|
|
|
|
|
{
|
|
|
|
|
if (m_thread_reg_ctx_sp)
|
|
|
|
|
return m_thread_reg_ctx_sp;
|
|
|
|
|
|
|
|
|
|
ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
|
|
|
|
|
ArchSpec arch = process->GetArchitecture();
|
2014-02-18 11:23:10 -05:00
|
|
|
RegisterInfoInterface *reg_interface = NULL;
|
|
|
|
|
|
|
|
|
|
switch (arch.GetTriple().getOS())
|
2013-08-23 13:46:38 -04:00
|
|
|
{
|
2014-02-18 11:23:10 -05:00
|
|
|
case llvm::Triple::FreeBSD:
|
|
|
|
|
{
|
|
|
|
|
switch (arch.GetMachine())
|
2013-11-06 11:48:53 -05:00
|
|
|
{
|
2015-02-06 16:38:51 -05:00
|
|
|
case llvm::Triple::ppc:
|
|
|
|
|
reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
|
|
|
|
|
break;
|
|
|
|
|
case llvm::Triple::ppc64:
|
|
|
|
|
reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
|
|
|
|
|
break;
|
2014-02-18 11:23:10 -05:00
|
|
|
case llvm::Triple::mips64:
|
|
|
|
|
reg_interface = new RegisterContextFreeBSD_mips64(arch);
|
|
|
|
|
break;
|
|
|
|
|
case llvm::Triple::x86:
|
|
|
|
|
reg_interface = new RegisterContextFreeBSD_i386(arch);
|
|
|
|
|
break;
|
|
|
|
|
case llvm::Triple::x86_64:
|
|
|
|
|
reg_interface = new RegisterContextFreeBSD_x86_64(arch);
|
2013-11-06 11:48:53 -05:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2014-02-18 11:23:10 -05:00
|
|
|
}
|
2014-11-25 16:00:58 -05:00
|
|
|
|
2014-02-18 11:23:10 -05:00
|
|
|
case llvm::Triple::Linux:
|
|
|
|
|
{
|
|
|
|
|
switch (arch.GetMachine())
|
2013-08-23 13:46:38 -04:00
|
|
|
{
|
2014-02-18 11:23:10 -05:00
|
|
|
case llvm::Triple::x86_64:
|
|
|
|
|
reg_interface = new RegisterContextLinux_x86_64(arch);
|
2013-08-23 13:46:38 -04:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2014-02-18 11:23:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!reg_interface) {
|
|
|
|
|
if (log)
|
|
|
|
|
log->Printf ("elf-core::%s:: Architecture(%d) or OS(%d) not supported",
|
|
|
|
|
__FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
|
|
|
|
|
assert (false && "Architecture or OS not supported");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (arch.GetMachine())
|
|
|
|
|
{
|
|
|
|
|
case llvm::Triple::mips64:
|
|
|
|
|
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
|
2015-02-06 16:38:51 -05:00
|
|
|
break;
|
|
|
|
|
case llvm::Triple::ppc:
|
|
|
|
|
case llvm::Triple::ppc64:
|
2015-02-08 20:44:09 -05:00
|
|
|
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data));
|
2014-02-18 11:23:10 -05:00
|
|
|
break;
|
|
|
|
|
case llvm::Triple::x86:
|
|
|
|
|
case llvm::Triple::x86_64:
|
|
|
|
|
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
|
|
|
|
|
break;
|
2013-08-23 13:46:38 -04:00
|
|
|
default:
|
2014-02-18 11:23:10 -05:00
|
|
|
break;
|
2013-08-23 13:46:38 -04:00
|
|
|
}
|
2014-02-18 11:23:10 -05:00
|
|
|
|
2013-08-23 13:46:38 -04:00
|
|
|
reg_ctx_sp = m_thread_reg_ctx_sp;
|
|
|
|
|
}
|
|
|
|
|
else if (m_unwinder_ap.get())
|
|
|
|
|
{
|
|
|
|
|
reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
|
|
|
|
|
}
|
|
|
|
|
return reg_ctx_sp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ThreadElfCore::CalculateStopInfo ()
|
|
|
|
|
{
|
|
|
|
|
ProcessSP process_sp (GetProcess());
|
|
|
|
|
if (process_sp)
|
|
|
|
|
{
|
|
|
|
|
SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, m_signo));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
// Parse PRSTATUS from NOTE entry
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
ELFLinuxPrStatus::ELFLinuxPrStatus()
|
|
|
|
|
{
|
|
|
|
|
memset(this, 0, sizeof(ELFLinuxPrStatus));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch)
|
|
|
|
|
{
|
|
|
|
|
ByteOrder byteorder = data.GetByteOrder();
|
|
|
|
|
size_t len;
|
|
|
|
|
switch(arch.GetCore())
|
|
|
|
|
{
|
|
|
|
|
case ArchSpec::eCore_x86_64_x86_64:
|
|
|
|
|
len = data.ExtractBytes(0, ELFLINUXPRSTATUS64_SIZE, byteorder, this);
|
|
|
|
|
return len == ELFLINUXPRSTATUS64_SIZE;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
// Parse PRPSINFO from NOTE entry
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
ELFLinuxPrPsInfo::ELFLinuxPrPsInfo()
|
|
|
|
|
{
|
|
|
|
|
memset(this, 0, sizeof(ELFLinuxPrPsInfo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch)
|
|
|
|
|
{
|
|
|
|
|
ByteOrder byteorder = data.GetByteOrder();
|
|
|
|
|
size_t len;
|
|
|
|
|
switch(arch.GetCore())
|
|
|
|
|
{
|
|
|
|
|
case ArchSpec::eCore_x86_64_x86_64:
|
|
|
|
|
len = data.ExtractBytes(0, ELFLINUXPRPSINFO64_SIZE, byteorder, this);
|
|
|
|
|
return len == ELFLINUXPRPSINFO64_SIZE;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|