LinuxThread.cpp revision 3bf3a9df7a920591092ef13c735cb65854a29a35
1//===-- LinuxThread.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// C Includes
11#include <errno.h>
12
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Debugger.h"
17#include "lldb/Host/Host.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/StopInfo.h"
20#include "lldb/Target/Target.h"
21#include "LinuxStopInfo.h"
22#include "LinuxThread.h"
23#include "ProcessLinux.h"
24#include "ProcessLinuxLog.h"
25#include "ProcessMonitor.h"
26#include "RegisterContextLinux_i386.h"
27#include "RegisterContextLinux_x86_64.h"
28#include "UnwindLLDB.h"
29
30using namespace lldb_private;
31
32
33LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
34    : Thread(process, tid),
35      m_frame_ap(0)
36{
37    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
38    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
39        log->Printf ("LinuxThread::%s (tid = %i)", __FUNCTION__, tid);
40}
41
42LinuxThread::~LinuxThread()
43{
44    DestroyThread();
45}
46
47ProcessMonitor &
48LinuxThread::GetMonitor()
49{
50    ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
51    return process.GetMonitor();
52}
53
54void
55LinuxThread::RefreshStateAfterStop()
56{
57    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
58    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
59        log->Printf ("LinuxThread::%s ()", __FUNCTION__);
60
61    // Let all threads recover from stopping and do any clean up based
62    // on the previous thread state (if any).
63    ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
64    process.GetThreadList().RefreshStateAfterStop();
65}
66
67const char *
68LinuxThread::GetInfo()
69{
70    return NULL;
71}
72
73lldb::RegisterContextSP
74LinuxThread::GetRegisterContext()
75{
76    if (!m_reg_context_sp)
77    {
78        ArchSpec arch = Host::GetArchitecture();
79
80        switch (arch.GetCore())
81        {
82        default:
83            assert(false && "CPU type not supported!");
84            break;
85
86        case ArchSpec::eCore_x86_32_i386:
87        case ArchSpec::eCore_x86_32_i486:
88        case ArchSpec::eCore_x86_32_i486sx:
89            m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0));
90            break;
91
92        case ArchSpec::eCore_x86_64_x86_64:
93            m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
94            break;
95        }
96    }
97    return m_reg_context_sp;
98}
99
100lldb::RegisterContextSP
101LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
102{
103    lldb::RegisterContextSP reg_ctx_sp;
104    uint32_t concrete_frame_idx = 0;
105
106    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
107    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
108        log->Printf ("LinuxThread::%s ()", __FUNCTION__);
109
110    if (frame)
111        concrete_frame_idx = frame->GetConcreteFrameIndex();
112
113    if (concrete_frame_idx == 0)
114        reg_ctx_sp = GetRegisterContext();
115    else
116    {
117        assert(GetUnwinder());
118        reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
119    }
120
121    return reg_ctx_sp;
122}
123
124lldb::StopInfoSP
125LinuxThread::GetPrivateStopReason()
126{
127    return m_stop_info;
128}
129
130Unwind *
131LinuxThread::GetUnwinder()
132{
133    if (m_unwinder_ap.get() == NULL)
134        m_unwinder_ap.reset(new UnwindLLDB(*this));
135
136    return m_unwinder_ap.get();
137}
138
139bool
140LinuxThread::WillResume(lldb::StateType resume_state)
141{
142    SetResumeState(resume_state);
143
144    ClearStackFrames();
145    if (m_unwinder_ap.get())
146        m_unwinder_ap->Clear();
147
148    return Thread::WillResume(resume_state);
149}
150
151bool
152LinuxThread::Resume()
153{
154    lldb::StateType resume_state = GetResumeState();
155    ProcessMonitor &monitor = GetMonitor();
156    bool status;
157
158    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
159    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
160        log->Printf ("LinuxThread::%s ()", __FUNCTION__);
161
162    switch (resume_state)
163    {
164    default:
165        assert(false && "Unexpected state for resume!");
166        status = false;
167        break;
168
169    case lldb::eStateRunning:
170        SetState(resume_state);
171        status = monitor.Resume(GetID(), GetResumeSignal());
172        break;
173
174    case lldb::eStateStepping:
175        SetState(resume_state);
176        status = monitor.SingleStep(GetID(), GetResumeSignal());
177        break;
178    }
179
180    return status;
181}
182
183void
184LinuxThread::Notify(const ProcessMessage &message)
185{
186    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
187    if (log)
188        log->Printf ("LinuxThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());
189
190    switch (message.GetKind())
191    {
192    default:
193        assert(false && "Unexpected message kind!");
194        break;
195
196    case ProcessMessage::eLimboMessage:
197        LimboNotify(message);
198        break;
199
200    case ProcessMessage::eSignalMessage:
201        SignalNotify(message);
202        break;
203
204    case ProcessMessage::eSignalDeliveredMessage:
205        SignalDeliveredNotify(message);
206        break;
207
208    case ProcessMessage::eTraceMessage:
209        TraceNotify(message);
210        break;
211
212    case ProcessMessage::eBreakpointMessage:
213        BreakNotify(message);
214        break;
215
216    case ProcessMessage::eCrashMessage:
217        CrashNotify(message);
218        break;
219    }
220}
221
222void
223LinuxThread::BreakNotify(const ProcessMessage &message)
224{
225    bool status;
226    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
227
228    assert(GetRegisterContextLinux());
229    status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
230    assert(status && "Breakpoint update failed!");
231
232    // With our register state restored, resolve the breakpoint object
233    // corresponding to our current PC.
234    assert(GetRegisterContext());
235    lldb::addr_t pc = GetRegisterContext()->GetPC();
236    if (log)
237        log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);
238    lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
239    assert(bp_site);
240    lldb::break_id_t bp_id = bp_site->GetID();
241    assert(bp_site && bp_site->ValidForThisThread(this));
242
243
244    m_breakpoint = bp_site;
245    m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
246}
247
248void
249LinuxThread::TraceNotify(const ProcessMessage &message)
250{
251    m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
252}
253
254void
255LinuxThread::LimboNotify(const ProcessMessage &message)
256{
257    m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this));
258}
259
260void
261LinuxThread::SignalNotify(const ProcessMessage &message)
262{
263    int signo = message.GetSignal();
264
265    m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
266    SetResumeSignal(signo);
267}
268
269void
270LinuxThread::SignalDeliveredNotify(const ProcessMessage &message)
271{
272    int signo = message.GetSignal();
273
274    // Just treat debugger generated signal events like breakpoints for now.
275    m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
276    SetResumeSignal(signo);
277}
278
279void
280LinuxThread::CrashNotify(const ProcessMessage &message)
281{
282    int signo = message.GetSignal();
283
284    assert(message.GetKind() == ProcessMessage::eCrashMessage);
285
286    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
287    if (log)
288        log->Printf ("LinuxThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());
289
290    m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo(
291                                       *this, signo, message.GetCrashReason()));
292    SetResumeSignal(signo);
293}
294
295unsigned
296LinuxThread::GetRegisterIndexFromOffset(unsigned offset)
297{
298    unsigned reg;
299    ArchSpec arch = Host::GetArchitecture();
300
301    switch (arch.GetCore())
302    {
303    default:
304        assert(false && "CPU type not supported!");
305        break;
306
307    case ArchSpec::eCore_x86_32_i386:
308    case ArchSpec::eCore_x86_32_i486:
309    case ArchSpec::eCore_x86_32_i486sx:
310        reg = RegisterContextLinux_i386::GetRegisterIndexFromOffset(offset);
311        break;
312
313    case ArchSpec::eCore_x86_64_x86_64:
314        reg = RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(offset);
315        break;
316    }
317    return reg;
318}
319
320const char *
321LinuxThread::GetRegisterName(unsigned reg)
322{
323    const char * name;
324    ArchSpec arch = Host::GetArchitecture();
325
326    switch (arch.GetCore())
327    {
328    default:
329        assert(false && "CPU type not supported!");
330        break;
331
332    case ArchSpec::eCore_x86_32_i386:
333    case ArchSpec::eCore_x86_32_i486:
334    case ArchSpec::eCore_x86_32_i486sx:
335        name = RegisterContextLinux_i386::GetRegisterName(reg);
336        break;
337
338    case ArchSpec::eCore_x86_64_x86_64:
339        name = RegisterContextLinux_x86_64::GetRegisterName(reg);
340        break;
341    }
342    return name;
343}
344
345const char *
346LinuxThread::GetRegisterNameFromOffset(unsigned offset)
347{
348    return GetRegisterName(GetRegisterIndexFromOffset(offset));
349}
350
351