1//===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/DataExtractor.h"
11#include "lldb/Target/RegisterContext.h"
12#include "lldb/Target/StopInfo.h"
13#include "lldb/Target/Target.h"
14#include "lldb/Target/Unwind.h"
15#include "ProcessPOSIXLog.h"
16
17#include "ThreadElfCore.h"
18#include "ProcessElfCore.h"
19#include "RegisterContextCoreFreeBSD_x86_64.h"
20#include "RegisterContextCoreLinux_x86_64.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25//----------------------------------------------------------------------
26// Construct a Thread object with given data
27//----------------------------------------------------------------------
28ThreadElfCore::ThreadElfCore (Process &process, tid_t tid,
29                              const ThreadData &td) :
30    Thread(process, tid),
31    m_thread_name(td.name),
32    m_thread_reg_ctx_sp (),
33    m_signo(td.signo),
34    m_gpregset_data(td.gpregset),
35    m_fpregset_data(td.fpregset)
36{
37}
38
39ThreadElfCore::~ThreadElfCore ()
40{
41    DestroyThread();
42}
43
44void
45ThreadElfCore::RefreshStateAfterStop()
46{
47    GetRegisterContext()->InvalidateIfNeeded (false);
48}
49
50void
51ThreadElfCore::ClearStackFrames ()
52{
53    Unwind *unwinder = GetUnwinder ();
54    if (unwinder)
55        unwinder->Clear();
56    Thread::ClearStackFrames();
57}
58
59RegisterContextSP
60ThreadElfCore::GetRegisterContext ()
61{
62    if (m_reg_context_sp.get() == NULL) {
63        m_reg_context_sp = CreateRegisterContextForFrame (NULL);
64    }
65    return m_reg_context_sp;
66}
67
68RegisterContextSP
69ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
70{
71    RegisterContextSP reg_ctx_sp;
72    uint32_t concrete_frame_idx = 0;
73    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
74
75    if (frame)
76        concrete_frame_idx = frame->GetConcreteFrameIndex ();
77
78    if (concrete_frame_idx == 0)
79    {
80        if (m_thread_reg_ctx_sp)
81            return m_thread_reg_ctx_sp;
82
83        ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
84        ArchSpec arch = process->GetArchitecture();
85        switch (arch.GetMachine())
86        {
87            case llvm::Triple::x86_64:
88                switch (arch.GetTriple().getOS())
89                {
90                    case llvm::Triple::FreeBSD:
91                        m_thread_reg_ctx_sp.reset(new RegisterContextCoreFreeBSD_x86_64 (*this, m_gpregset_data, m_fpregset_data));
92                        break;
93                    case llvm::Triple::Linux:
94                        m_thread_reg_ctx_sp.reset(new RegisterContextCoreLinux_x86_64 (*this, m_gpregset_data, m_fpregset_data));
95                        break;
96                    default:
97                        if (log)
98                            log->Printf ("elf-core::%s:: OS(%d) not supported",
99                                         __FUNCTION__, arch.GetTriple().getOS());
100                        assert (false && "OS not supported");
101                        break;
102                }
103                break;
104            default:
105                if (log)
106                    log->Printf ("elf-core::%s:: Architecture(%d) not supported",
107                                 __FUNCTION__, arch.GetMachine());
108                assert (false && "Architecture not supported");
109        }
110        reg_ctx_sp = m_thread_reg_ctx_sp;
111    }
112    else if (m_unwinder_ap.get())
113    {
114        reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
115    }
116    return reg_ctx_sp;
117}
118
119bool
120ThreadElfCore::CalculateStopInfo ()
121{
122    ProcessSP process_sp (GetProcess());
123    if (process_sp)
124    {
125        SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, m_signo));
126        return true;
127    }
128    return false;
129}
130
131//----------------------------------------------------------------
132// Parse PRSTATUS from NOTE entry
133//----------------------------------------------------------------
134ELFLinuxPrStatus::ELFLinuxPrStatus()
135{
136    memset(this, 0, sizeof(ELFLinuxPrStatus));
137}
138
139bool
140ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch)
141{
142    ByteOrder byteorder = data.GetByteOrder();
143    size_t len;
144    switch(arch.GetCore())
145    {
146        case ArchSpec::eCore_x86_64_x86_64:
147            len = data.ExtractBytes(0, ELFLINUXPRSTATUS64_SIZE, byteorder, this);
148            return len == ELFLINUXPRSTATUS64_SIZE;
149        default:
150            return false;
151    }
152}
153
154//----------------------------------------------------------------
155// Parse PRPSINFO from NOTE entry
156//----------------------------------------------------------------
157ELFLinuxPrPsInfo::ELFLinuxPrPsInfo()
158{
159    memset(this, 0, sizeof(ELFLinuxPrPsInfo));
160}
161
162bool
163ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch)
164{
165    ByteOrder byteorder = data.GetByteOrder();
166    size_t len;
167    switch(arch.GetCore())
168    {
169        case ArchSpec::eCore_x86_64_x86_64:
170            len = data.ExtractBytes(0, ELFLINUXPRPSINFO64_SIZE, byteorder, this);
171            return len == ELFLINUXPRPSINFO64_SIZE;
172        default:
173            return false;
174    }
175}
176
177