1f678e45dSDimitry Andric //===-- NativeThreadNetBSD.cpp -------------------------------- -*- C++ -*-===//
2f678e45dSDimitry Andric //
3f678e45dSDimitry Andric //                     The LLVM Compiler Infrastructure
4f678e45dSDimitry Andric //
5f678e45dSDimitry Andric // This file is distributed under the University of Illinois Open Source
6f678e45dSDimitry Andric // License. See LICENSE.TXT for details.
7f678e45dSDimitry Andric //
8f678e45dSDimitry Andric //===----------------------------------------------------------------------===//
9f678e45dSDimitry Andric 
10f678e45dSDimitry Andric #include "NativeThreadNetBSD.h"
11f678e45dSDimitry Andric #include "NativeRegisterContextNetBSD.h"
12f678e45dSDimitry Andric 
13f678e45dSDimitry Andric #include "NativeProcessNetBSD.h"
14f678e45dSDimitry Andric 
15f678e45dSDimitry Andric #include "Plugins/Process/POSIX/CrashReason.h"
16f678e45dSDimitry Andric #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
176bc11b14SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
18*b5893f02SDimitry Andric #include "lldb/Utility/RegisterValue.h"
19*b5893f02SDimitry Andric #include "lldb/Utility/State.h"
206bc11b14SDimitry Andric 
216bc11b14SDimitry Andric #include <sstream>
22f678e45dSDimitry Andric 
23f678e45dSDimitry Andric using namespace lldb;
24f678e45dSDimitry Andric using namespace lldb_private;
25f678e45dSDimitry Andric using namespace lldb_private::process_netbsd;
26f678e45dSDimitry Andric 
NativeThreadNetBSD(NativeProcessNetBSD & process,lldb::tid_t tid)27b40b48b8SDimitry Andric NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process,
28f678e45dSDimitry Andric                                        lldb::tid_t tid)
29f678e45dSDimitry Andric     : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
30acac075bSDimitry Andric       m_stop_info(), m_reg_context_up(
31acac075bSDimitry Andric NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this)
32acac075bSDimitry Andric ), m_stop_description() {}
33f678e45dSDimitry Andric 
SetStoppedBySignal(uint32_t signo,const siginfo_t * info)34f678e45dSDimitry Andric void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
35f678e45dSDimitry Andric                                             const siginfo_t *info) {
36f678e45dSDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
37f678e45dSDimitry Andric   LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo);
38f678e45dSDimitry Andric 
39f678e45dSDimitry Andric   SetStopped();
40f678e45dSDimitry Andric 
41f678e45dSDimitry Andric   m_stop_info.reason = StopReason::eStopReasonSignal;
42f678e45dSDimitry Andric   m_stop_info.details.signal.signo = signo;
43f678e45dSDimitry Andric 
44f678e45dSDimitry Andric   m_stop_description.clear();
45f678e45dSDimitry Andric   if (info) {
46f678e45dSDimitry Andric     switch (signo) {
47f678e45dSDimitry Andric     case SIGSEGV:
48f678e45dSDimitry Andric     case SIGBUS:
49f678e45dSDimitry Andric     case SIGFPE:
50f678e45dSDimitry Andric     case SIGILL:
51f678e45dSDimitry Andric       const auto reason = GetCrashReason(*info);
52f678e45dSDimitry Andric       m_stop_description = GetCrashReasonString(reason, *info);
53f678e45dSDimitry Andric       break;
54f678e45dSDimitry Andric     }
55f678e45dSDimitry Andric   }
56f678e45dSDimitry Andric }
57f678e45dSDimitry Andric 
SetStoppedByBreakpoint()58f678e45dSDimitry Andric void NativeThreadNetBSD::SetStoppedByBreakpoint() {
59f678e45dSDimitry Andric   SetStopped();
60f678e45dSDimitry Andric   m_stop_info.reason = StopReason::eStopReasonBreakpoint;
61f678e45dSDimitry Andric   m_stop_info.details.signal.signo = SIGTRAP;
62f678e45dSDimitry Andric }
63f678e45dSDimitry Andric 
SetStoppedByTrace()64f678e45dSDimitry Andric void NativeThreadNetBSD::SetStoppedByTrace() {
65f678e45dSDimitry Andric   SetStopped();
66f678e45dSDimitry Andric   m_stop_info.reason = StopReason::eStopReasonTrace;
67f678e45dSDimitry Andric   m_stop_info.details.signal.signo = SIGTRAP;
68f678e45dSDimitry Andric }
69f678e45dSDimitry Andric 
SetStoppedByExec()70f678e45dSDimitry Andric void NativeThreadNetBSD::SetStoppedByExec() {
71f678e45dSDimitry Andric   SetStopped();
72f678e45dSDimitry Andric   m_stop_info.reason = StopReason::eStopReasonExec;
73f678e45dSDimitry Andric   m_stop_info.details.signal.signo = SIGTRAP;
74f678e45dSDimitry Andric }
75f678e45dSDimitry Andric 
SetStoppedByWatchpoint(uint32_t wp_index)766bc11b14SDimitry Andric void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
776bc11b14SDimitry Andric   SetStopped();
786bc11b14SDimitry Andric 
796bc11b14SDimitry Andric   lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
806bc11b14SDimitry Andric 
816bc11b14SDimitry Andric   std::ostringstream ostr;
82acac075bSDimitry Andric   ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " ";
836bc11b14SDimitry Andric   ostr << wp_index;
846bc11b14SDimitry Andric 
85acac075bSDimitry Andric   ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index);
866bc11b14SDimitry Andric 
876bc11b14SDimitry Andric   m_stop_description = ostr.str();
886bc11b14SDimitry Andric 
896bc11b14SDimitry Andric   m_stop_info.reason = StopReason::eStopReasonWatchpoint;
906bc11b14SDimitry Andric   m_stop_info.details.signal.signo = SIGTRAP;
916bc11b14SDimitry Andric }
926bc11b14SDimitry Andric 
SetStopped()93f678e45dSDimitry Andric void NativeThreadNetBSD::SetStopped() {
94f678e45dSDimitry Andric   const StateType new_state = StateType::eStateStopped;
95f678e45dSDimitry Andric   m_state = new_state;
96f678e45dSDimitry Andric   m_stop_description.clear();
97f678e45dSDimitry Andric }
98f678e45dSDimitry Andric 
SetRunning()99f678e45dSDimitry Andric void NativeThreadNetBSD::SetRunning() {
100f678e45dSDimitry Andric   m_state = StateType::eStateRunning;
101f678e45dSDimitry Andric   m_stop_info.reason = StopReason::eStopReasonNone;
102f678e45dSDimitry Andric }
103f678e45dSDimitry Andric 
SetStepping()104f678e45dSDimitry Andric void NativeThreadNetBSD::SetStepping() {
105f678e45dSDimitry Andric   m_state = StateType::eStateStepping;
106f678e45dSDimitry Andric   m_stop_info.reason = StopReason::eStopReasonNone;
107f678e45dSDimitry Andric }
108f678e45dSDimitry Andric 
GetName()109f678e45dSDimitry Andric std::string NativeThreadNetBSD::GetName() { return std::string(""); }
110f678e45dSDimitry Andric 
GetState()111f678e45dSDimitry Andric lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
112f678e45dSDimitry Andric 
GetStopReason(ThreadStopInfo & stop_info,std::string & description)113f678e45dSDimitry Andric bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info,
114f678e45dSDimitry Andric                                        std::string &description) {
115f678e45dSDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
116f678e45dSDimitry Andric 
117f678e45dSDimitry Andric   description.clear();
118f678e45dSDimitry Andric 
119f678e45dSDimitry Andric   switch (m_state) {
120f678e45dSDimitry Andric   case eStateStopped:
121f678e45dSDimitry Andric   case eStateCrashed:
122f678e45dSDimitry Andric   case eStateExited:
123f678e45dSDimitry Andric   case eStateSuspended:
124f678e45dSDimitry Andric   case eStateUnloaded:
125f678e45dSDimitry Andric     stop_info = m_stop_info;
126f678e45dSDimitry Andric     description = m_stop_description;
127f678e45dSDimitry Andric 
128f678e45dSDimitry Andric     return true;
129f678e45dSDimitry Andric 
130f678e45dSDimitry Andric   case eStateInvalid:
131f678e45dSDimitry Andric   case eStateConnected:
132f678e45dSDimitry Andric   case eStateAttaching:
133f678e45dSDimitry Andric   case eStateLaunching:
134f678e45dSDimitry Andric   case eStateRunning:
135f678e45dSDimitry Andric   case eStateStepping:
136f678e45dSDimitry Andric   case eStateDetached:
137f678e45dSDimitry Andric     LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(),
138f678e45dSDimitry Andric              StateAsCString(m_state));
139f678e45dSDimitry Andric     return false;
140f678e45dSDimitry Andric   }
141f678e45dSDimitry Andric   llvm_unreachable("unhandled StateType!");
142f678e45dSDimitry Andric }
143f678e45dSDimitry Andric 
GetRegisterContext()144acac075bSDimitry Andric NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() {
145acac075bSDimitry Andric   assert(m_reg_context_up);
146acac075bSDimitry Andric return  *m_reg_context_up;
147f678e45dSDimitry Andric }
148f678e45dSDimitry Andric 
SetWatchpoint(lldb::addr_t addr,size_t size,uint32_t watch_flags,bool hardware)1495517e702SDimitry Andric Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
150f678e45dSDimitry Andric                                          uint32_t watch_flags, bool hardware) {
1516bc11b14SDimitry Andric   if (!hardware)
1525517e702SDimitry Andric     return Status("not implemented");
1536bc11b14SDimitry Andric   if (m_state == eStateLaunching)
1545517e702SDimitry Andric     return Status();
1555517e702SDimitry Andric   Status error = RemoveWatchpoint(addr);
1566bc11b14SDimitry Andric   if (error.Fail())
1576bc11b14SDimitry Andric     return error;
158acac075bSDimitry Andric   uint32_t wp_index = GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags);
1596bc11b14SDimitry Andric   if (wp_index == LLDB_INVALID_INDEX32)
1605517e702SDimitry Andric     return Status("Setting hardware watchpoint failed.");
1616bc11b14SDimitry Andric   m_watchpoint_index_map.insert({addr, wp_index});
1625517e702SDimitry Andric   return Status();
163f678e45dSDimitry Andric }
164f678e45dSDimitry Andric 
RemoveWatchpoint(lldb::addr_t addr)1655517e702SDimitry Andric Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) {
1666bc11b14SDimitry Andric   auto wp = m_watchpoint_index_map.find(addr);
1676bc11b14SDimitry Andric   if (wp == m_watchpoint_index_map.end())
1685517e702SDimitry Andric     return Status();
1696bc11b14SDimitry Andric   uint32_t wp_index = wp->second;
1706bc11b14SDimitry Andric   m_watchpoint_index_map.erase(wp);
171acac075bSDimitry Andric   if (GetRegisterContext().ClearHardwareWatchpoint(wp_index))
1725517e702SDimitry Andric     return Status();
1735517e702SDimitry Andric   return Status("Clearing hardware watchpoint failed.");
174f678e45dSDimitry Andric }
175f678e45dSDimitry Andric 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)1765517e702SDimitry Andric Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr,
177f678e45dSDimitry Andric                                                  size_t size) {
1786bc11b14SDimitry Andric   if (m_state == eStateLaunching)
1795517e702SDimitry Andric     return Status();
1806bc11b14SDimitry Andric 
1815517e702SDimitry Andric   Status error = RemoveHardwareBreakpoint(addr);
1826bc11b14SDimitry Andric   if (error.Fail())
1836bc11b14SDimitry Andric     return error;
1846bc11b14SDimitry Andric 
185acac075bSDimitry Andric   uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size);
1866bc11b14SDimitry Andric 
1876bc11b14SDimitry Andric   if (bp_index == LLDB_INVALID_INDEX32)
1885517e702SDimitry Andric     return Status("Setting hardware breakpoint failed.");
1896bc11b14SDimitry Andric 
1906bc11b14SDimitry Andric   m_hw_break_index_map.insert({addr, bp_index});
1915517e702SDimitry Andric   return Status();
192f678e45dSDimitry Andric }
193f678e45dSDimitry Andric 
RemoveHardwareBreakpoint(lldb::addr_t addr)1945517e702SDimitry Andric Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
1956bc11b14SDimitry Andric   auto bp = m_hw_break_index_map.find(addr);
1966bc11b14SDimitry Andric   if (bp == m_hw_break_index_map.end())
1975517e702SDimitry Andric     return Status();
1986bc11b14SDimitry Andric 
1996bc11b14SDimitry Andric   uint32_t bp_index = bp->second;
200acac075bSDimitry Andric   if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) {
2016bc11b14SDimitry Andric     m_hw_break_index_map.erase(bp);
2025517e702SDimitry Andric     return Status();
2036bc11b14SDimitry Andric   }
2046bc11b14SDimitry Andric 
2055517e702SDimitry Andric   return Status("Clearing hardware breakpoint failed.");
206f678e45dSDimitry Andric }
207