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 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 //----------------------------------------------------------------------
26 // Construct a Thread object with given PRSTATUS, PRPSINFO and FPREGSET
27 //----------------------------------------------------------------------
28 ThreadElfCore::ThreadElfCore (Process &process, tid_t tid, DataExtractor prstatus,
29                               DataExtractor prpsinfo, DataExtractor fpregset) :
30     Thread(process, tid),
31     m_thread_reg_ctx_sp ()
32 {
33     ProcessElfCore *pr = static_cast<ProcessElfCore *>(GetProcess().get());
34     ArchSpec arch = pr->GetArchitecture();
35 
36     /* Parse the datastructures from the file */
37     m_prstatus.Parse(prstatus, arch);
38     m_prpsinfo.Parse(prpsinfo, arch);
39 
40     m_prstatus_data = prstatus;
41     m_fpregset_data = fpregset;
42 
43     m_thread_name = std::string(m_prpsinfo.pr_fname);
44 }
45 
46 ThreadElfCore::~ThreadElfCore ()
47 {
48     DestroyThread();
49 }
50 
51 void
52 ThreadElfCore::RefreshStateAfterStop()
53 {
54     GetRegisterContext()->InvalidateIfNeeded (false);
55 }
56 
57 void
58 ThreadElfCore::ClearStackFrames ()
59 {
60     Unwind *unwinder = GetUnwinder ();
61     if (unwinder)
62         unwinder->Clear();
63     Thread::ClearStackFrames();
64 }
65 
66 RegisterContextSP
67 ThreadElfCore::GetRegisterContext ()
68 {
69     if (m_reg_context_sp.get() == NULL) {
70         m_reg_context_sp = CreateRegisterContextForFrame (NULL);
71     }
72     return m_reg_context_sp;
73 }
74 
75 RegisterContextSP
76 ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
77 {
78     RegisterContextSP reg_ctx_sp;
79     uint32_t concrete_frame_idx = 0;
80     Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
81 
82     if (frame)
83         concrete_frame_idx = frame->GetConcreteFrameIndex ();
84 
85     if (concrete_frame_idx == 0)
86     {
87         if (m_thread_reg_ctx_sp)
88             return m_thread_reg_ctx_sp;
89 
90         ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
91         ArchSpec arch = process->GetArchitecture();
92         size_t header_size = ELFPrStatus::GetSize(arch);
93         size_t len = m_prstatus_data.GetByteSize() - header_size;
94         DataExtractor gpregset_data = DataExtractor(m_prstatus_data, header_size, len);
95         switch (arch.GetMachine())
96         {
97             case llvm::Triple::x86_64:
98 #ifdef __FreeBSD__
99                 m_thread_reg_ctx_sp.reset(new RegisterContextCoreFreeBSD_x86_64 (*this, gpregset_data, m_fpregset_data));
100 #else
101                 m_thread_reg_ctx_sp.reset(new RegisterContextCoreLinux_x86_64 (*this, gpregset_data, m_fpregset_data));
102 #endif
103                 break;
104             default:
105                 if (log)
106                     log->Printf ("elf-core::%s:: Architecture(%d) not supported",
107                                  __FUNCTION__, arch.GetMachine());
108         }
109         reg_ctx_sp = m_thread_reg_ctx_sp;
110     }
111     else if (m_unwinder_ap.get())
112     {
113         reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
114     }
115     return reg_ctx_sp;
116 }
117 
118 bool
119 ThreadElfCore::CalculateStopInfo ()
120 {
121     ProcessSP process_sp (GetProcess());
122     if (process_sp)
123     {
124         SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, m_prstatus.pr_cursig));
125         return true;
126     }
127     return false;
128 }
129 
130 //----------------------------------------------------------------
131 // Parse PRSTATUS from NOTE entry
132 //----------------------------------------------------------------
133 ELFPrStatus::ELFPrStatus()
134 {
135     memset(this, 0, sizeof(ELFPrStatus));
136 }
137 
138 bool
139 ELFPrStatus::Parse(DataExtractor &data, ArchSpec &arch)
140 {
141     ByteOrder byteorder = data.GetByteOrder();
142     size_t len;
143     switch(arch.GetCore())
144     {
145         case ArchSpec::eCore_x86_64_x86_64:
146             len = data.ExtractBytes(0, ELFPRSTATUS64_SIZE, byteorder, this);
147             return len == ELFPRSTATUS64_SIZE;
148         default:
149             return false;
150     }
151 }
152 
153 //----------------------------------------------------------------
154 // Parse PRPSINFO from NOTE entry
155 //----------------------------------------------------------------
156 ELFPrPsInfo::ELFPrPsInfo()
157 {
158     memset(this, 0, sizeof(ELFPrPsInfo));
159 }
160 
161 bool
162 ELFPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch)
163 {
164     ByteOrder byteorder = data.GetByteOrder();
165     size_t len;
166     switch(arch.GetCore())
167     {
168         case ArchSpec::eCore_x86_64_x86_64:
169             len = data.ExtractBytes(0, ELFPRPSINFO64_SIZE, byteorder, this);
170             return len == ELFPRPSINFO64_SIZE;
171         default:
172             return false;
173     }
174 }
175 
176