]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r308421, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / Process / NetBSD / NativeThreadNetBSD.cpp
1 //===-- NativeThreadNetBSD.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 "NativeThreadNetBSD.h"
11 #include "NativeRegisterContextNetBSD.h"
12
13 #include "NativeProcessNetBSD.h"
14
15 #include "Plugins/Process/POSIX/CrashReason.h"
16 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
17 #include "lldb/Core/RegisterValue.h"
18 #include "lldb/Core/State.h"
19 #include "lldb/Utility/LLDBAssert.h"
20
21 #include <sstream>
22
23 using namespace lldb;
24 using namespace lldb_private;
25 using namespace lldb_private::process_netbsd;
26
27 NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process,
28                                        lldb::tid_t tid)
29     : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
30       m_stop_info(), m_reg_context_sp(), m_stop_description() {}
31
32 void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
33                                             const siginfo_t *info) {
34   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
35   LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo);
36
37   SetStopped();
38
39   m_stop_info.reason = StopReason::eStopReasonSignal;
40   m_stop_info.details.signal.signo = signo;
41
42   m_stop_description.clear();
43   if (info) {
44     switch (signo) {
45     case SIGSEGV:
46     case SIGBUS:
47     case SIGFPE:
48     case SIGILL:
49       const auto reason = GetCrashReason(*info);
50       m_stop_description = GetCrashReasonString(reason, *info);
51       break;
52     }
53   }
54 }
55
56 void NativeThreadNetBSD::SetStoppedByBreakpoint() {
57   SetStopped();
58   m_stop_info.reason = StopReason::eStopReasonBreakpoint;
59   m_stop_info.details.signal.signo = SIGTRAP;
60 }
61
62 void NativeThreadNetBSD::SetStoppedByTrace() {
63   SetStopped();
64   m_stop_info.reason = StopReason::eStopReasonTrace;
65   m_stop_info.details.signal.signo = SIGTRAP;
66 }
67
68 void NativeThreadNetBSD::SetStoppedByExec() {
69   SetStopped();
70   m_stop_info.reason = StopReason::eStopReasonExec;
71   m_stop_info.details.signal.signo = SIGTRAP;
72 }
73
74 void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
75   SetStopped();
76
77   lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
78
79   std::ostringstream ostr;
80   ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
81   ostr << wp_index;
82
83   ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
84
85   m_stop_description = ostr.str();
86
87   m_stop_info.reason = StopReason::eStopReasonWatchpoint;
88   m_stop_info.details.signal.signo = SIGTRAP;
89 }
90
91 void NativeThreadNetBSD::SetStopped() {
92   const StateType new_state = StateType::eStateStopped;
93   m_state = new_state;
94   m_stop_description.clear();
95 }
96
97 void NativeThreadNetBSD::SetRunning() {
98   m_state = StateType::eStateRunning;
99   m_stop_info.reason = StopReason::eStopReasonNone;
100 }
101
102 void NativeThreadNetBSD::SetStepping() {
103   m_state = StateType::eStateStepping;
104   m_stop_info.reason = StopReason::eStopReasonNone;
105 }
106
107 std::string NativeThreadNetBSD::GetName() { return std::string(""); }
108
109 lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
110
111 bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info,
112                                        std::string &description) {
113   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
114
115   description.clear();
116
117   switch (m_state) {
118   case eStateStopped:
119   case eStateCrashed:
120   case eStateExited:
121   case eStateSuspended:
122   case eStateUnloaded:
123     stop_info = m_stop_info;
124     description = m_stop_description;
125
126     return true;
127
128   case eStateInvalid:
129   case eStateConnected:
130   case eStateAttaching:
131   case eStateLaunching:
132   case eStateRunning:
133   case eStateStepping:
134   case eStateDetached:
135     LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(),
136              StateAsCString(m_state));
137     return false;
138   }
139   llvm_unreachable("unhandled StateType!");
140 }
141
142 NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() {
143   // Return the register context if we already created it.
144   if (m_reg_context_sp)
145     return m_reg_context_sp;
146
147   ArchSpec target_arch;
148   if (!m_process.GetArchitecture(target_arch))
149     return NativeRegisterContextSP();
150
151   const uint32_t concrete_frame_idx = 0;
152   m_reg_context_sp.reset(
153       NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(
154           target_arch, *this, concrete_frame_idx));
155
156   return m_reg_context_sp;
157 }
158
159 Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
160                                          uint32_t watch_flags, bool hardware) {
161   if (!hardware)
162     return Status("not implemented");
163   if (m_state == eStateLaunching)
164     return Status();
165   Status error = RemoveWatchpoint(addr);
166   if (error.Fail())
167     return error;
168   NativeRegisterContextSP reg_ctx = GetRegisterContext();
169   uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags);
170   if (wp_index == LLDB_INVALID_INDEX32)
171     return Status("Setting hardware watchpoint failed.");
172   m_watchpoint_index_map.insert({addr, wp_index});
173   return Status();
174 }
175
176 Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) {
177   auto wp = m_watchpoint_index_map.find(addr);
178   if (wp == m_watchpoint_index_map.end())
179     return Status();
180   uint32_t wp_index = wp->second;
181   m_watchpoint_index_map.erase(wp);
182   if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
183     return Status();
184   return Status("Clearing hardware watchpoint failed.");
185 }
186
187 Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr,
188                                                  size_t size) {
189   if (m_state == eStateLaunching)
190     return Status();
191
192   Status error = RemoveHardwareBreakpoint(addr);
193   if (error.Fail())
194     return error;
195
196   NativeRegisterContextSP reg_ctx = GetRegisterContext();
197   uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size);
198
199   if (bp_index == LLDB_INVALID_INDEX32)
200     return Status("Setting hardware breakpoint failed.");
201
202   m_hw_break_index_map.insert({addr, bp_index});
203   return Status();
204 }
205
206 Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
207   auto bp = m_hw_break_index_map.find(addr);
208   if (bp == m_hw_break_index_map.end())
209     return Status();
210
211   uint32_t bp_index = bp->second;
212   if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) {
213     m_hw_break_index_map.erase(bp);
214     return Status();
215   }
216
217   return Status("Clearing hardware breakpoint failed.");
218 }